闭包
概念:
内层函数可以访问到外层函数的作用域
function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); console.log(add10(2));
|
add5()和add10()都会使用外部函数makeAdder的形参x,这个形参x就是共享的变量 外部函数makeAdder被称之为函数工厂
可以使用闭包来模拟私有函数
var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var Counter1 = makeCounter(); var Counter2 = makeCounter(); console.log(Counter1.value()); Counter1.increment(); Counter1.increment(); console.log(Counter1.value()); Counter1.decrement(); console.log(Counter1.value()); console.log(Counter2.value());
|
以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装
闭包的错误使用:
循环中使用闭包
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++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } } } setupHelp();
|
每一个onfocus都是一个闭包,但是都指向helpText的最后一项 解决这个问题可以使用let关键字
for (var i = 0; i < helpText.length; i++) { let item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } }
|
let为块级作用域关键字,声明的变量的范围为onfocus绑定的块,var声明的范围为给onfocus提供的词法作用域