概念篇
闭包介绍
闭包是js开发常的技巧,那么什么是闭包呢?
来自百度百科
闭包就是能够读取其他函数内部变量的函数。
例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁
来自菜鸟教程
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。
直观的说就是形成一个不销毁的栈环境。
简而言之:闭包就是一个函数。
稍微具体点:闭包就是能够读取另一个函数内部变量的函数
闭包特点:
- 让外部访问函数内部变量成为可能
- 函数变量会常驻在内存中,不会随着函数的结束而自动销毁。
- 可以避免使用全局变量,防止全局变量污染
- 会造成内存泄漏(有一块内存空间被长期占用而不被释放)
应用篇
结论:闭包找到的是同一地址中父级函数中对应变量最终的值
咱先以菜鸟教程的计数器来谈一哈
例一:
var add = (function () {
var counter = 0;
return function () {
return counter += 1;
}
})();
add(); //1
add(); //2
add(); //3
变量 add 指定了函数自我调用的返回值。自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。add变量可以作为一个函数使用。它可以访问函数上一层作用域的计数器。计数器受匿名函数的作用域保护,只能通过 add 方法修改。
例二:
function funA() {
var a = 10; // funA的活动对象之中;
return function(){ //匿名函数的活动对象;
alert(a);
}
}
var b = funA();
b(); //10
例三:
function funA() {
var a = 0;
function funB(){
a++;
console.log(a);
}
return funB;
}
var b = funA();
b(); //1
b(); //2
b(); //3
var b2 = funA();
b2(); //1
b2(); //2
例四:
var i = 0;
function funA(){
function funB(){
i++;
console.log(i);
}
return funB;
}
var b1 = funA();
var b2 = funA();
b1(); //1
b2(); //2
b1(); //3
b2(); //4
例五:
function fn(){
var a = 5;
return function(){
return ++a;
}
}
console.log(fn()()); //6
console.log(fn()()); //6
例六:
(function() {
var m = 0;
function getM() { return m; }
function seta(val) { m = val; }
window.g = getM;
window.f = seta;
})();
f(100);
console.log(g()); //100 闭包找到的是同一地址中父级函数中对应变量最终的值
例七:
var add = function(x) {
var sum = x;
var tmp = function(x) {
sum = sum + x;
return tmp;
}
tmp.toString = function() {
return sum;
}
return tmp;
}
alert(add(1)(2)(3)); //6
例八:
var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
console.log(i);
};
})(i); //事件处理函数中闭包的写法
}
例九:
function m1(){
var x = 1;
return function(){
console.log(++x);
}
}
m1()(); //2
m1()(); //2
var m2 = m1();
m2(); //2
m2(); //3
例十:
var fn=(function(){
var i=10;
function fn(){
console.log(++i);
}
return fn;
})()
fn(); //11
fn(); //12
面试篇
var x = 2
var y = {
x:3,
z:(function(x){
this.x *= x;
x += 2
return function(n) {
this.x *= n;
x += 3;
console.log(x)
}
})(x)
}
var m = y.z
m(4) //7
y.z(6) //10
console.log(x,y.x) //16 18