1.什么是闭包?
如果一个函数用到了它作用域外面的变量,那么这个变量和这个函数之间的环境就叫闭包。
闭包有3个特性:
①函数嵌套函数;
②函数内部可以引用函数外部的参数和变量;
③参数和变量不会被垃圾回收机制回收。
2.用码举例
function a() {
var i = 0;
return function inner() {
i++;
return i;
};
}
// 或者
function a() {
var i = 0;
function inner() {
return i;
}
}
-
闭包使函数的私有变量不受外部干扰
-
是变量存于内存中不被销毁
function a() {
var i = 0;
return function () {
i++;
return i;
};
}
var fn = a();
console.log(fn()); //输出结果: 1
console.log(fn()); //输出结果: 2
console.log(fn()); //输出结果: 3
变量 i 保存在父作用域中,每次访问函数 y 时, 在函数 y 中找不到变量 i, 会顺着作用域链一直向上找,直到全局作用域中也没找到为止。
闭包常用于实现单例模式、柯里化、防抖、节流、模块化。
滥用闭包可能会造成内存泄漏(无用变量存于内存中无法回收,一直占用内存)。解决此问题的方法是,清除变量(设为 null)。
3.常见面试题:
3.1.输出结果:
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
输出结果为:连续输出 5 个 5 请修改以上代码,使其输出 0、1、2、3、4
//方法一:使用let
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
//方法二:
for (let i = 0; i < 5; i++) {
setTimeout(
function () {
console.log(i);
},
0,
i
);
}
//方法三:使用自执行函数
for (var i = 0; i < 5; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 0);
})(i);
}
//方法四:借用 async
const timeout = function (time) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve();
}, time);
});
};
async function print() {
for (var i = 0; i < 5; i++) {
await timeout(1000);
console.log(i);
}
}
await print();
3.2.实现一个与 sum(x,y)功能相同的 sum(x)(y)函数
function sum(a) {
return function (b) {
return a + b;
};
}
sum(1)(2); // 3
//考察的是柯里化的概念
3.3.输出结果:
var a = 100;
function create() {
var a = 200;
return function () {
console.log(a);
};
}
var fn = new create();
fn();
//输出 200