闭包看似很简单,其实牵扯了很多东西,例如:上下文作用域、内存占用、局部以及全局变量等
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。
未完待续。。。