关于闭包

闭包是指有权访问另一个函数作用域中的变量的函数 //摘自javascript高级程序设计

要理解闭包首先要理解作用域链,每一个javascript代码(全局代码或函数)都有一个与之相关的作用域链,这个作用域链可以看作是一个串联着这段代码或函数作用域中范围内的变量的对象列表。当代码或函数需要查找x属性的时候它会沿着链从第一个元素开始查找,直到最后一个元素。如果找到了,那么就会使用这个x的值,如果没有找到则继续向下查找,直到没有任何一个对象含有x属性,那么抛出异常。这就是作用域链的概念。

下面我们来看几个简单的例子:

function a(){
var x = 1;
console.log(x);
}
a()

输出为:1

var x = 2;
function a(){
console.log(x);
}
a();


输出为2

var x = 2;
function a(){
console.log(x);
}
a();
x = 3;
a();


输出为2  3

其实这就是闭包的概念,在函数内部可以使用函数外部的变量

理解对象链的创建规则是非常重要的,当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域上同时创建一个新的更长的表示函数调用作用域的“链”。对于嵌套函数来讲,事情变得更有趣,每次调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。//以上这段话摘自javascript权威指南 第六版

下面我们看第四个例子:

var x = 2;
function a(){
var x = 1;
function b(){
console.log(x);
}
b();
}
a();


输出为:1

再看这个例子:

function a(){
var x = 1;
return {
b:function (){
console.log(x);
},
setX:function(value){
x = value;
}
};
}
var obj = a();
obj.b();
obj.setX(10);
obj.b();


输出应为1 10

作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。下面这个例子可以清晰的说明这个问题。

function c(){
var result = new Array();
for(var i = 0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}


这个函数会返回一个函数数组。表面上看似乎每个函数都应该返回自己的索引值,即位置0 的函数返回0,位置1的
函数返回1,以此类推。但实际上,每个函数都返回10。因为每个函数的作用域链中都保存着c()函数的活动对象,所以他们引用的都是同一个变量i。当c函数返回后,变i的值是10。此时每个函数都引用这保存变量i的同一个变量对象,所以在每个函数内部i的值都是10.但是我们可以通过创建另一个匿名函数强制让闭包的行为符合预期
如下:

function c(){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}


在重写了前面的c()函数后,每个函数就返回各自不同的索引值了。在这个版本中,我们没有直接把闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。这里的匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数参数是按值传递的,所以就会将变量i的当前值复制给参数num。而这个匿名函数的内部,又创建并返回了一个访问num的闭包。这样一来,result数组中的每一个函数都有自己num变量的一个副本,因此可以返回各自不同的值了。

(个人认识 请多指正)

<think>好的,用户需要关于前端笔试中闭包的编程题。首先,我需要回忆闭包定义和在前端面试中的常见应用场景。闭包是指函数能够访问并记住其词法作用域外的变量,即使函数在外部作用域之外执行。这在JavaScript中常用于封装私有变量、模块化开发等。 接下来,我需要从常见的面试题中筛选涉及闭包的编程题。可能的问题包括计数器、延迟打印、私有变量实现等。例如,循环中使用闭包解决var声明变量的问题,或者实现个只能通过特定方法访问的变量。 然后,要确保每个问题都明确考察闭包的理解和应用,并提供清晰的示例代码。同,需要注意代码的正确性和可读性,避免语法错误。例如,在循环中创建闭包来保存每个迭代的变量状态,或者使用闭包实现模块模式。 另外,用户可能需要详细的解答,所以每个问题后面需要给出解决方案和解释,说明闭包在其中的作用。例如,解释为什么在循环中使用闭包可以解决变量共享的问题,或者如何利用闭包创建私有变量。 还要检查引用内容,虽然用户提供的引用中没有直接提到闭包,但需要确保回答符合前端笔试的常见题型,可以参考类似的问题结构。比如引用[2]中的链表反转题,可以类比闭包问题如何考察作用域和函数的概念。 最后,生成相关问题要覆盖闭包的不同应用场景,确保用户能全面理解闭包的各种用法和潜在问题。例如,闭包的内存泄漏问题、闭包在事件处理中的应用等。</think>### 前端笔试闭包编程题解析 闭包JavaScript函数与其词法作用域结合的机制,常用于保存状态或实现数据封装。以下是3道典型闭包编程题及解答: --- #### 题目1:实现计数器生成器 要求:创建函数`createCounter()`,每次调用返回的计数器函数,数值+1,初始值为0 示例: ```javascript const counter = createCounter(); console.log(counter()); // 0 console.log(counter()); // 1 ``` **解答**: ```javascript function createCounter() { let count = -1; // 通过闭包保存计数状态 return function() { count++; return count; } } ``` 闭包特性:内部函数捕获外部函数的`count`变量,形成独立作用域链[^2] --- #### 题目2:循环中延迟打印 要求:修正以下代码使其输出0-4 ```javascript for(var i=0; i<5; i++){ setTimeout(() => console.log(i), 100) } ``` **解答**: ```javascript for(var i=0; i<5; i++){ (function(j){ // IIFE创建闭包作用域 setTimeout(() => console.log(j), 100) })(i) } ``` 闭包作用:每个迭代创建独立作用域,捕获当前`i`值[^3] --- #### 题目3:实现私有变量 要求:创建对象包含`getValue`和`add`方法,外部无法直接访问数值 ```javascript const obj = createPrivateVar(10); obj.add(5); console.log(obj.getValue()); // 15 ``` **解答**: ```javascript function createPrivateVar(init) { let value = init; // 闭包保存私有变量 return { getValue: () => value, add: n => value += n } } ``` 闭包应用:通过函数作用域实现数据封装,形成模块模式[^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值