js闭包
function foo() { var x = 10; return function bar() { console.log(x); } } var returntedFunction = foo(); var x = 20; returntedFunction();
1、输出10而不是20,这种形式的作用域称为静态作用域[static/lexical scope]。上面的x变量就是在函数bar的[[Scope]]中搜寻到的。理论上来说,也会有动态作用域[dynamic scope], 也就是上述的x被解释为20,而不是10. 但是EMCAScript不使用动态作用域。
var x = 10; function foo() { console.log(x); } (function (funArg) { var x = 20; funArg(); })(foo);
2、输出10而不是20
闭包是一系列代码块(在ECMAScript中是函数),并且静态保存所有父级的作用域。通过这些保存的作用域来搜寻到函数中的自由变量。
function baz() { var x = 1; return { foo: function foo() { return (x+=3); }, bar: function bar() { return (x+=3); } }; } var closures = baz(); console.log( closures.foo(), // 4 closures.bar() // 7 );
3、几个函数可能含有相同的父级作用域,例如好几个内部或者全局的函数,这样Scope中存在的变量是会共享的。一个闭包中变量的变化,也会影响另个闭包。
var data = []; for (var k = 0; k < 3; k++) { data[k] = function () { console.log(k); }; } data[0]();//3 data[1]();//3 data[2]();//3
4、在某个循环中创建几个函数时,如果在创建的函数中使用循环变量(如k),那么所有的函数都使用同样的循环变量,导致得不到预期值,因为所有函数共享同一个scope,其中循环变量为最后一次赋值
var data = []; for (var k = 0; k < 3; k++) { data[k] = (function (x) { return function () { console.log(x); }; })(k); } data[0]();//3 data[1]();//3 data[2]();//3
5、其中一种技巧是在作用域链中提供一个额外的对象,比如增加一个函数

浙公网安备 33010602011771号