作用域闭包

1.作用域

作用域是根据名称找变量的一套规则。

变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。

引擎在查找变量时执行怎样的查找,会影响最终的查找结果。

当变量出现在赋值操作的左侧时进行LHS查询,出现在右侧时进行RHS查询:

  • console.log(a)对a的引用是一个RHS引用,这里a并没有赋予任何值。相应地,需要查找并取得a的值,这样才能将值传递给console.log(..)

  • a = 2对a的引用是LHS引用,因为实际上我们并不关心当前的值是什么,只是 为=2这个赋值操作找到一个目标。

当一个块或函数嵌套在另一块或函数中时,就发生了作用域的嵌套。在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域为止。

2.函数作用域

function foo(a){
    var b = ;
    function bar(){
        //...
    }
    //更多代码
    var c = ;
}

foo(...)的作用域气泡中包含了标识符a、b、c和bar。
bar(...)拥有自己的作用域气泡。全局作用域也有自己的作用域气泡,它只包含了一个标识符foo。
由于a、b、c和bar都附属于foo(...)的作用域气泡,因此无法从foo(...)的外部对它们进行访问。
函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用。

“隐藏”作用域中的变量和函数好处是可以避免标识符之间的冲突。
当程序中加载了多个第三方库时,如果它们没有妥善地将内部私有的函数或变量隐藏起来,就会很容易引发变量冲突。
这些库通常会在全局作用域中声明一个名字足够独特的变量,通常是一个对象。这个对象被用作库的命名空间,所有需要暴露给外界的功能都会成为这个对象的属性。

var MyReallyCoolLibrary = {
    awesome::"stuff",
    doSomething:function(){
        //...
    },
    doAnotherThing:function(){
        //...
    }
};

函数声明函数表达式之间最重要的区别是它们的名称标识符将会绑定在何处。

var a = ;
//函数声明
function foo(){
    var a = ;
    console.log(a);//3
}
foo();
console.log(a);//2
var a = ;
//函数表达式
(function foo(){
    var a = ;
    console.log(a);//3
})();
console.log(a);//2

(function foo(){...})作为函数表达式意味着foo只能在...所代表的位置中被访问,外部作用域则不行。

匿名函数表达式:

相关推荐