第一章 作用域是什么


作用域就是一套方便查找存储变量的规则。

引用变量的时候有两种引用方式:LHS引用和RHS引用。

当变量出现在赋值操作的左侧时进行LHS查询,出现在右侧时进行RHS引用。LHS引用是试图找到变量的容器本身,从而可以对其赋值。RHS不需要找到变量的容器本身,只需要知道变量的值即可。

console.log(a);
这是一个RHS引用,因为这条语句并不是赋值操作。只是需要查找到a的值,传递给console.log。

a = 2;
这是一个LHS引用,因为我们并不关心a是什么值,只是要把2这个值赋给一个对象。

当我们在当前作用域中无法找到某个变量时,引擎会在外层嵌套的作用域中继续查找,知道找到该变量,或抵达最外层的作用域(全局作用域)为止。

而当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非“严格模式”下

异常:

 如果RHS查询找到了一个变量,但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或着引用null或undefined类型的值中的属性,那么引擎会抛出另外一种类型的异常,叫作TypeError。ReferenceError同作用域判别失败相关,而TypeError则代表作用域判别成功了,但是对结果的操作是非法或不合理的。

 

实例分析:

1.

function test(a){

  console.log(a + b);

  b = a;

}

test(2);

当执行到console.log(a+b)时,由于b未声明,并且还未执行到b=a这条语句,所以引擎不会自动对b进行全局声明,于是此时会跳出ReferenceError的 异常。

2.

function test(a){

  b = 2;

  console.log(a + b);

}

 console.log("b==="+b);

test(2);

当执行到console.log("b==="+b)时,此时是一个RHS,同时b未声明,引擎会报ReferenceError的异常。

3.

function test(a){

  b = 2;

  console.log(a + b);     /4

}

test(2);

 console.log("b==="+b);  /b=2

例3和例2的区别是把test(2)和console.log("b==="+b)这两条语句的位置变换了一下,此时引擎上输出 4和b===2。为什么此时又能够顺利执行呢?因为test(2)中,b=2是LHS查询,当程序执行到b=2时,编译器会在当前test函数作用域中查找b的声明,当前作用域中没有b的声明,就跳出当前test函数作用域,跑到全局作用域中查找,还是没有b的声明,就在全局作用域中直接隐性对b进行了全局声明。所以当test(2)执行完成之后,全局作用域中已经有了b的声明,并且在test(2)中对b进行了赋值,b=2。再console.log("b==="+b)的时候,b有值,并且b=2。

 4.

function test(a){

  var b = 2;

  console.log(a + b);     /4

}

test(2);

 console.log("b==="+b);  /ReferenceError

例4和例3的区别在test中var b=2,在test函数作用域中对b进行了声明,此时b的作用域在test函数作用域中,超出test函数作用域的范围,就无法获取到b。所以在全局作用域中console.log("b==="+b)打印b的值的时候,会报ReferenceEror的异常。

posted on 2019-02-02 00:26  atomgame的记事本  阅读(93)  评论(0)    收藏  举报

导航