JavaScript作为编程语言,最基本的功能之一就是能够存储变量当中的值。而一套设计良好的用来存储变量,并且之后可以方便地找到这些变量的规则,被称为作用域。
首先要清楚,任何JavaScript代码片段在执行前都要进行编译,然后做好执行他的准备,并且通常马上就会执行他。其中:
这三者如何协同工作?
例如 var a = 2;这段程序,一般认为这是一句声明,但引擎却认为这是两个完全不同的声明:一个由编译器在编译时处理,另一个则由引擎在运行时处理。
这个变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对他赋值。
查找过程中,引擎会进行两种类型的查询:LHS查询、RHS查询。
LHS查询:试图找到变量的容器本身,从而可以对其赋值(当变量出现在赋值操作的左侧时进行,查找的目的是对变量进行赋值);
RHS查询:与简单的查找某个变量的值一样(当变量出现在赋值操作的非左侧时进行,目的是获取变量的值)。
当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。因此,在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(全局作用域)为止。
区分LHS和RHS是一件很重要的事,因为在变量还没有声明的情况下,这两种查询的行为是不一样的。
如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError异常;当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎(前提是程序运作在非‘严格模式’下)。
严格模式禁止自动或隐式地创建全局变量。
如果RHS查询找到了变量,但是接下来对这个变量的值进行不合理的操作的话,比如试图对要给非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性,那么引擎会抛出林外一种类型的异常,叫做 TypeError异常。
ReferenceError跟作用于判别失败相关,而TypeError则代表作用域判别成功了,但是对结果的操作是非法或者不合理的。
function foo(a){ var b = a; return a + b; } var c = foo(2);
这段程序有几处LHS查询?几处RHS查询?
上面的六种异常对象都继承自Error对象;关于异常的更多详情,可参考 JavaScript中的异常处理 一文。
"use strict";
严格模式详情可参考阮一峰的 Javascript 严格模式详解 一文。
LHS查询--3处
c = ..; || a (= 2)(隐士变量分配) || b = ..
RHS查询--4处
foo(2.. || = a; || a .. || ..b
原文:http://www.cnblogs.com/xieyaoming/p/JavaScript.html