闭包看似很简单,其实牵扯了很多东西,例如:上下文作用域、内存占用、局部以及全局变量等
function init() { var name = "Mozilla"; // name 是一个被 init 创建的局部变量 function displayName() { // displayName() 是内部函数,一个闭包 alert(name); // 使用了父函数中声明的变量 } displayName(); } init();
init是外部函数,name是外部变量。
displayName属于内部函数调用时使用的是父函数(init())的声明的变量。
嵌套的函数可以访问在其外部声明的变量,简而言之就是内部函数可以访问外部函数。
下面的例子也解释了作用域对变量的影响,请看如下:
function init() { var name = "Mozilla"; // name 是一个被 init 创建的局部变量 function displayName() { // displayName() 是内部函数,一个闭包 var name = "6666"; alert(name); // 使用了父函数中声明的变量 } displayName(); } init();
上下文作用域,同名变量局部作用域最大。
function makeFunc() { var name = "Mozilla"; function displayName() { alert(name); } return displayName; } var myFunc = makeFunc(); myFunc();
JavaScript中的函数会形成闭包。 闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量。在我们的例子中,
myFunc 是执行 makeFunc 时创建的 displayName 函数实例的引用,而 displayName 实例仍可访问其词法作用域中的变量,即可以访问到 name 。
由此,当 myFunc 被调用时,name 仍可被访问,其值 Mozilla 就被传递到alert中。
function makeAdder(x) { return function(y) { console.log(‘:‘ + x); return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12
在这个示例中,我们定义了 makeAdder(x) 函数,他接受一个参数 x ,并返回一个新的函数。返回的函数接受一个参数 y,并返回x+y的值。
从本质上讲,makeAdder 是一个函数工厂 — 他创建了将指定的值和它的参数相加求和的函数。在上面的示例中,我们使用函数工厂创建了两个新函数 — 一个将其参数和 5 求和,另一个和 10 求和。
add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。在 add5的环境中,x 为 5。而在 add10 中,x 则为 10。
未完待续。。。