作用域
语法作用域:在编写代码时给代码定义的附属作用域,在运行时保持不变。(使用 with 可以改变, eval 可以插入代码进行欺骗)
函数作用域:创建函数时会创建一个可用于变量绑定的作用域。
块作用域:JavaScript if(){ .. } for(){ .. } 不会创建块作用域。仅 try/catch ES3+ 具有块作用域。在 ES6 中可以使用 let 将变量定义绑定到 { .. } 块中。(但是不会进行声明提升)
立即执行函数表达式:函数声明绑定在所处作用域中,而函数表达式将函数名隐藏在自身函数表达式中({ .. }部分)。
函数声明 function(){ .. },函数表达式 (function(){ .. })() 立即执行函数表达式,setTimeout(function(){..},1000) 匿名函数表达式。
闭包
将函数类型的值进行传递,它都会持有对原始定义作用域的引用。
function wait(message) {setTimeout(function timer() {console.log(message);}, 1000);}wait("Hello closure!");
将一个内部函数(名为 timer )传递给 setTimeout(..)。timer 具有涵盖 wait(..)作用域的闭包,因此还保有对变量 message 的引用。
wait(..) 执行 1000 毫秒后,它的内部作用域不会消失,timer 函数依然保有 wait(..) 作用域的闭包。
闭包与循环
for (var i = 0; i != 5; i++) {setTimeout(function timer() {console.log(i);}, 1000);}//Output: 5 5 5 5 5
for (var i = 0; i != 5; i++) {(function () {setTimeout(function timer() {console.log(i);}, 1000);})();}//Output: 5 5 5 5 5
for (var i = 0; i != 5; i++) {(function (j) {setTimeout(function timer() {console.log(j);}, 1000);})(i);}//Output: 0 1 2 3 4
for (var i = 0; i != 5; i++) {let j = i;setTimeout(function timer() {console.log(j);}, 1000);}//Output: 0 1 2 3 4
//let 循环:let 可以将声明绑定在 for(){ .. } 内部,并且在每次迭代都进行重新绑定。for (let i = 0; i != 5; i++) {setTimeout(function timer() {console.log(i);}, 1000);}//Output: 0 1 2 3 4
