根据闭包的定义,我们知道,无论通过何种手段,只要将内部函数传递到所在的词法作用域以外,它都会持有对原始作用域的引用,无论在何处执行这个函数都会使用闭包。接下来,本文将详细介绍闭包的7种形式
返回值
最常用的一种形式是函数作为返回值被返回
var F = function(){ var b = 'local'; var N = function(){ return b;
} return N;
}
console.log(F()());
函数赋值
一种变形的形式是将内部函数赋值给一个外部变量
var inner;var F = function(){ var b = 'local'; var N = function(){ return b;
};
inner = N;
};
F();
console.log(inner());
函数参数
闭包可以通过函数参数传递函数的形式来实现
var Inner = function(fn){
console.log(fn());
}var F = function(){ var b = 'local'; var N = function(){ return b;
}
Inner(N);
}
F();
IIFE
由前面的示例代码可知,函数F()都是在声明后立即被调用,因此可以使用IIFE来替代。但是,要注意的是,这里的Inner()只能使用函数声明语句的形式,而不能使用函数表达式。详细原因移步至此
function Inner(fn){
console.log(fn());
}
(function(){ var b = 'local'; var N = function(){ return b;
}
Inner(N);
})();
循环赋值
在闭包问题上,最常见的一个错误就是循环赋值的错误。关于其错误原因的详细解释移步至此
function foo(){ var arr = []; for(var i = 0; i < 2; i++){
arr[i] = function(){ return i;
}
} return arr;
}var bar = foo();
console.log(bar[0]());//2
正确的写法如下
function foo(){ var arr = []; for(var i = 0; i < 2; i++){
arr[i] = (function fn(j){ return function test(){ return j;
}
})(i);
} return arr;
}var bar = foo();
console.log(bar[0]());//0
g(s)etter
我们通过提供getter()和setter()函数来将要操作的变量保存在函数内部,防止其暴露在外部
var getValue,setValue;
(function(){ var secret = 0;
getValue = function(){ return secret;
}
setValue = function(v){ if(typeof v === 'number'){
secret = v;
}
}
})();
console.log(getValue());//0setValue(1);
console.log(getValue());//1
迭代器
我们经常使用闭包来实现一个累加器
var add = (function(){ var counter = 0; return function(){ return ++counter;
}
})();
console.log(add())//1console.log(add())//2
类似地,使用闭包可以很方便的实现一个迭代器
function setup(x){ var i = 0; return function(){ return x[i++];
}
}var next = setup(['a','b','c']);
console.log(next());//'a'console.log(next());//'b'console.log(next());//'c'
本文转自xsster51CTO博客,原文链接: http://blog.51cto.com/12945177/1948454,如需转载请自行联系原作者