JavaScript闭包和作用域链的定义实现
什么是闭包?
在JavaScript中,闭包是指每个函数在创建时会生成一个自己的执行环境,这个执行环境可以访问到它自身定义的变量、参数,也可以访问父级的变量,而且这个执行环境可以一直存在,即使函数执行完,此时这个执行环境也不会被销毁。
简单来说,就是可以访问父级作用域的函数,创建出来的执行环境,这种执行环境中包含了函数内部定义的变量、参数以及外层函数和全局作用域中定义的变量。
闭包的实现方式
闭包的实现方式很简单,即函数内部又嵌套了一个函数,并且内部的函数引用了外部函数的变量或参数。这样的话,内部函数就形成了一个闭包,因为它可以访问到外部函数中的变量或参数。
下面是一个简单的闭包示例:
function outer() {
var a = 1;
return function inner() {
console.log(a);
}
}
var innerFunc = outer();
innerFunc(); // 输出:1
在这个示例中,outer返回了内部函数inner。内部函数使用了外部函数outer中的变量a,这种使用即为闭包。
什么是作用域链?
在JavaScript中,每一个执行环境都会有一个变量对象,叫做活动对象(activation object,AO)或者执行上下文(Execution context)。
"作用域链"是JavaScript中非常重要的概念之一。每一个函数的执行上下文中有一个变量对象,而这个变量对象中包含了当前作用域中所有的局部变量。在获取一个变量的时候,JavaScript会从当前执行上下文的变量对象中寻找,如果找不到则会从父级执行上下文的变量对象中寻找,直到找到全局执行上下文的变量对象。
即,当一个变量在当前执行上下文中被引用时,JavaScript会按照作用域链的顺序依次查找该变量所在的执行上下文,直到找到该变量所在的变量对象为止。
作用域链的实现方式
在JavaScript中,作用域的链式结构可以用一组对象来实现,这个对象集合被称为“作用域链”。
作用域链的实现与闭包密切相关,当一个函数调用时,它会创建一个新的执行上下文,并且在该执行上下文中自动创建一个新的作用域链,这个链的头节点指向该执行上下文的变量对象。
下面是一个示例:
var a = 1;
function outer() {
var b = 2;
function inner() {
var c = 3;
console.log(a + b + c);
}
inner();
}
outer(); // 输出:6
在这个示例中,当执行outer函数时,会在全局上下文中自动创建一个outer
的函数执行上下文,它会在其自身的变量对象上查找变量b
,并在其作用域链的下一级作用域对象上查找变量a
,最后,在inner
的执行上下文中查找到变量c
。使用作用域链,我们可以在当前作用域上方的作用域中查找变量a的值。
示例说明
示例一
function getCounter() {
var count = 0;
return function inc() {
count++;
console.log(count);
}
}
var counter = getCounter();
counter(); // 输出:1
counter(); // 输出:2
在这个示例中,函数getCounter
返回了一个内部函数inc
(即闭包),它引用了getCounter
函数中的变量count
。这里我们通过将闭包inc
的引用赋值给counter
,并调用它两次,捕获和维护了count
变量的状态信息,每次调用输出递增的计数器值。
示例二
function createAdditionFunc(x) {
return function(y) {
return x + y;
};
}
var addTen = createAdditionFunc(10);
console.log(addTen(5)); // 输出:15
在这个示例中,createAdditionFunc
返回了一个闭包函数,该函数可以捕获到外部函数中传入的参数x的值,并返回一个内部函数addition
,该函数在被调用时,可以接收参数y,并将外部函数的x和参数y相加并返回。
我们通过在创建addTen
时向createAdditionFunc
中传入参数10,就得到了一个新的闭包函数addTen
,它的执行结果就是x为10时的返回结果。在我们调用addTen(5)
时,就得到了15这个结果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript闭包和作用域链的定义实现 - Python技术站