1

函数作用域

为了隐藏内部实现,可以通过在任意代码片段外部添加包装函数,但是这并不理想,因为必须声明一个具名函数,意味着这个函数名称本身会污染函数所在的作用域;同时必须通过显式地调用函数才能运行其中的代码。

*:区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。

JS提供了同时解决这两个问题的方案:

var a=2;
(function foo(){
    var a=3;
    console.log(a);//3
})();

console.log(a);//2

以上这种模式称为立即执行函数表达式(IIFE)。

有一个改进的形式:

var a=2;
(function foo(){
    var a=3;
    console.log(a);//3
}());//调用的括号包含在用来包装的()里

console.log(a);//2

两种形式在功能上是一致的。

IIFE有一个进阶用法:把它们当作函数调用并传递参数进去。

var a=2;
(function IIFE(global){
    var a=3;
    console.log(a);//3
    console.log(global.a);//2
})(window);

console.log(a);//2

IIFE还有一种变化的用途是倒置代码的运行顺序,将需要运行的函数放在第二位。

var a=2;
(function IIFE(def){
    def(window);
})(funtion def(global){
    var a=3;
    console.log(a);//3
    console.log(global.a);//2
})

块作用域

let

只要声明是有效的,在声明中的任意位置都可以使用{...}括号来为let创建一个用于绑定的块。

var foo=true;
if(foo){
    {//显式的块
        let bar=foo*2;
        console.log(bar);//2
    }
     console.log(bar);//ReferenceError
}
console.log(bar);//ReferenceError

**:let循环:for的循环头部使用let,不仅将i绑定到for的块中,事实上它将其重新绑定到了循环的每个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。

*:块作用域不应该完全作为函数作用域的替代方案,两种功能应该同时存在。


Teemo
38 声望1 粉丝