这几天看了《你不知道的Javascript》,对作用域有了一些新的认识和理解,这篇文章将会详细的整理一下这些天来我的理解和认识。

一、LHS查询和RHS查询

“L”和“R”分别代表赋值操作的左侧和右侧。通俗点来说,可以这样理解,LHS查询代表所有赋值操作,而RHS查找代表取原值的操作

例如 var a = 1;这是一个LHS查询,console.log(a);这是一个RHS查询。

下面的程序中既有LHS查询,也有RHS查询:

function foo(a){

var b=a;

console.log(b)
}

foo(1);

其中LHS查询有:a=1(隐式)b=a;RHS查询有:foo(a…; log(b…;a…;b…。

二、作用域和作用域链的创建时间

作用域链的非自己部分在函数对象被建立(函数声明、函数表达式)的时候建立,而不需要等到执行

        作用域链的前面部分是静态的,所有函数共享同一个链,当函数执行时,建立一个自己当次执行的作用域,然后把这个作用域与前面共享的链关联起来。
        下面的代码将会证明作用域是在函数声明时被建立的。
         var a=1;
          function foo(callback){
              var a = 2;
             callback(a)
         }
          foo(function(a){
              console.log(a)//2
         })
        其中在对a进行RHS查找时,找到foo作用域下的 a=2;完成赋值,证明作用域是在函数声明时被建立。
三、块级作用域的作用
      首先先看这样一段代码
       <ul>
         <li></li>
         <li></li>
         <li></li>
         <li></li>
        </ul>
       var li = document.querySelectorAll(‘ul li’);
        for (var i=0; i<li.length; i++){
li[i].onclick = function(){
alert(i) //4
          }
}
     按照预期,我们点击每一个li,应该分别显示0,1,2,3,4四个值,可是我们却输出了4个4。这是为什么呢?
    因为,我们在执行这段循环时,会创建4个function,在alert(i)引用时,循环已经完成了,i=4;所以实际上,这四个函数都共享一个变量var i=4;
   那么如何解决这个问题呢?在Es6以前,我们可以使用这种方法:

  var li = document.querySelectorAll(‘ul li’);
        for (var i=0; i<li.length; i++){
          (function(){
             li[i].onclick = function(){
alert(i) //4
          }
        })()
    }
这种做法,实际上给每个函数创建了个私有的作用域,可以分别保存每次循环的到的i变量,即可解决这个问题。
而在Es6中,我们有了更通用的做法:使用let ,即可达到同样的效果。

   for (let i=0; i<li.length; i++){
             li[i].onclick = function(){
alert(i) //4
        })()
    }
四、提升
五、闭包