闭包就是在函数内部创建一个函数,内部函数可以访问函数的作用域。闭包会随着函数的创建而创建。
举例说明:
function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
alert('执行的init函数')
return function() { // 匿名的内部函数,一个闭包
// 闭包可以访问外部函数的作用域
alert(name); // 使用了父函数中声明的变量
}
}
init(); 执行init函数,创建了匿名闭包函数,但是没有执行。
init()();执行init函数,并且执行了匿名闭包函数。
1. forEach与js闭包
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(item){
document.getElementById(item.id).onfocus = function(){
showHelp(item.help)
}
})
}
2. for循环与js闭包
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
//创建一个单独的词法作用域,
function a(item){
return function(){
console.log(item)
showHelp(item.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)'}
];
// onfocus事件会创建一个闭包,使用的同一个词法作用域。
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = a(item)
}
}
setupHelp();
3. 定时器与js闭包
function a(i){
return function(){
console.log(i)
}
}
for(var i=0;i<5;i++) {
var fn = a(i) //每个定时器都创建一个独立的词法作用域
setTimeout(fn,1000)
}
4. let和const与js闭包
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)'}
];
// 使用let或者const定义item之后,item会转换为块级作用域。从而无需使用闭包来实现。
for (let i = 0; i < helpText.length; i++) {
let item = helpText[i];
document.getElementById(item.id).onfocus = function(){
showHelp(item.help);
}
}
}
setupHelp();
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)'}
];
// 错误的js闭包。
/**
* 错误原因:循环创建的闭包在同一个词法作用域下。在这个作用域中存在一个变量 item。
* 这是因为变量 item 使用 var 进行声明,由于变量提升,所以具有函数作用域。
* 当 onfocus 的回调执行时,item.help 的值被决定。
* 由于循环在事件触发之前早已执行完毕,变量对象 item(被三个闭包所共享)已经指向了 helpText 的最后一项。
**/
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
console.log(i) // 先遍历了三次。item为helpText最后一个
document.getElementById(item.id).onfocus = function(){ //回调
showHelp(item.help)
console.log("我是onfocus事件执行")
}
}
}
setupHelp();
代码已经上传到 https://gitee.com/usuing/lession.git
,喜欢可以star一下。