
闭包:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。指有权访问另一个函数作用域中变量的函数。
闭包可以在一个内层函数中访问到其外层函数的作用域。延伸了变量的作用域
在JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
示例1:
// 外层函数 -- 声明一个变量;return 一个内部函数
funciton fn() {
var num = 0;
// 内层函数
return function() { // 调用外部函数 fn()的变量 num
console.log(++num) // 延伸了num 作用域
}
}
var fun = fn();
fun(); // 打印结果为 1
fun(); // 打印结果为 2
在本例子中,fun 是执行 fn 时创建的函数实例(return 的函数)的引用。该函数的实例维持了一个对它的词法环境(变量 num存在于其中)的引用。因此,当fun被调用时,变量num` 仍然可用,所以打印结果为 1
词法作用域
词法(lexical):指的是,词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。
嵌套函数可访问声明于它们外部作用域的变量。
示例2:
function makeAdder(x) {
return function(y) {
return x + y;
}
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 打印结果为 5
console.log(add10(2)); // 打印结果为 12
// 解析
add5 = makeAdder(5) = function(y) = 5+y
add5(2) = makeAdder(5) = function(2) = 5+2 = 7
add10 = makeAdder(10) = function(y) = 10+y
add10(2) = makeAdder(10) = function(2) = 10+2 = 12
add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。在 add5 的环境中,x为5。而在add10中,x则为10。
用闭包模拟私有方法 – 面试时可能会问道
私有方法的好处:
利于限制对代码的访问;提供了管理全局命名空间的强大能力;避免非核心的方法弄乱代码的公共接口部分。在循环中创建闭包:一个常见错误 – 面试时可能会问道
在for循环中创建闭包时,可能会因为闭包共享一个词法作用域,造成错误。
解决方法:
为每个闭包创建单独的词法环境
使用匿名闭包
示例:
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
(function() {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
})(); // 马上把当前循环项的item与事件回调相关联起来
}
}
setupHelp();
使用关键词 let 而非 var (let 关键字有作用域;var 关键字无作用域)
可选方案 – 使用forEach()遍历数组
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
helpText.forEach(function(text) {
document.getElementById(text.id).onfocus = function() {
showHelp(text.help);
}
});
}
setupHelp()
性能考量
闭包的缺点:闭包在处理速度和内存消耗方面对脚本性能具有负面影响。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)