事件监听器是否需要在 IIFE 中?
Do event listeners need to be inside IIFE?
我经常看到很多事件监听器代码都封装在IIFE里面(function(e){}())
我觉得没有必要把事件监听器放在IIFE里面。例如:
没有 IIFE
jQuery(window).on("load", function(){
console.log("inside plain load");
});
有 IIFE
(function(){
jQuery(window).on("load", function(){
console.log("inside wrapped load");
});
}())
如果我们将以上代码一起包含在一个 js 文件中,则在加载事件时它们仅根据编写的顺序执行。
我知道 IIFE 会调用自身,但是在其中设置事件侦听器有什么用?无论如何它只会在事件发生时触发。
- 是否需要在 IIFE 中包装事件侦听器?
- IIFE 中的事件侦听器真的是一个好习惯吗?
对于你的例子来说没有区别。
使用 IIFE 的主要原因是防止在全局范围内泄漏变量。
(function(){
let notLeakedVariable = 'something'
jQuery(window).on("load", function(){
console.log("inside wrapped load");
console.log(notLeakedVariable)
});
}())
如果没有 IIFE,您将在全局范围内泄漏变量。
通过包装您的侦听器,您甚至可以将多个侦听器分组,它们将通过闭包共享相同的作用域。
(function(){
let sharedVariable = 'something'
jQuery(window).on("load", function(){
console.log("inside wrapped load");
// sharedVariable is accessible
});
jQuery(selector).on("click", function(){
// sharedVariable is accessible
});
}())
它不会影响回调的绑定方式,但您可能会看到它有几个原因。
- 如果JS文件直接通过标签加载,那么IIFE会关闭在IIFE中创建的任何变量,它们在全局
window
对象上是不可见的。例如,如果您在 IIFE 中写了 var x = 'foo'
,它不会显示为 window.x
,但如果没有 IIFE,它就会显示为
- 某些函数 return 您不想公开的值。例如
jQuery(window).on(...)
实际上是 return 的东西。由于 IIFE,您不能简单地在它前面分配一个变量并获取它。
您使用 IIFE 是因为您希望本地作用域将所有内容与全局作用域隔离。
(function() {
var count = 0;
document.body.addEventListener('click', function() {
console.log("hi", count++);
});
}());
hello world
上面的代码,世界上没有其他人可以触摸count
。只有执行 console.log 的函数才能访问它。所以count
不污染全局范围,也不受外界影响。
请注意,IIFE 提供的是局部作用域。某些 JavaScript 专家可能将其称为闭包,但闭包在这里与它无关。您在这里只需要一个本地范围。
执行 console.log
的函数是一个闭包。它是一个采用作用域链并能够访问 count
的函数。这是闭包的行为。
因此此函数可以访问 count
,而其他任何函数都不能。所以这个IIFE提供了一个很好的方式来写一些自包含的东西,不污染外界,也不让外界污染它。
我经常看到很多事件监听器代码都封装在IIFE里面(function(e){}())
我觉得没有必要把事件监听器放在IIFE里面。例如:
没有 IIFE
jQuery(window).on("load", function(){
console.log("inside plain load");
});
有 IIFE
(function(){
jQuery(window).on("load", function(){
console.log("inside wrapped load");
});
}())
如果我们将以上代码一起包含在一个 js 文件中,则在加载事件时它们仅根据编写的顺序执行。
我知道 IIFE 会调用自身,但是在其中设置事件侦听器有什么用?无论如何它只会在事件发生时触发。
- 是否需要在 IIFE 中包装事件侦听器?
- IIFE 中的事件侦听器真的是一个好习惯吗?
对于你的例子来说没有区别。
使用 IIFE 的主要原因是防止在全局范围内泄漏变量。
(function(){
let notLeakedVariable = 'something'
jQuery(window).on("load", function(){
console.log("inside wrapped load");
console.log(notLeakedVariable)
});
}())
如果没有 IIFE,您将在全局范围内泄漏变量。
通过包装您的侦听器,您甚至可以将多个侦听器分组,它们将通过闭包共享相同的作用域。
(function(){
let sharedVariable = 'something'
jQuery(window).on("load", function(){
console.log("inside wrapped load");
// sharedVariable is accessible
});
jQuery(selector).on("click", function(){
// sharedVariable is accessible
});
}())
它不会影响回调的绑定方式,但您可能会看到它有几个原因。
- 如果JS文件直接通过标签加载,那么IIFE会关闭在IIFE中创建的任何变量,它们在全局
window
对象上是不可见的。例如,如果您在 IIFE 中写了var x = 'foo'
,它不会显示为window.x
,但如果没有 IIFE,它就会显示为 - 某些函数 return 您不想公开的值。例如
jQuery(window).on(...)
实际上是 return 的东西。由于 IIFE,您不能简单地在它前面分配一个变量并获取它。
您使用 IIFE 是因为您希望本地作用域将所有内容与全局作用域隔离。
(function() {
var count = 0;
document.body.addEventListener('click', function() {
console.log("hi", count++);
});
}());
hello world
上面的代码,世界上没有其他人可以触摸count
。只有执行 console.log 的函数才能访问它。所以count
不污染全局范围,也不受外界影响。
请注意,IIFE 提供的是局部作用域。某些 JavaScript 专家可能将其称为闭包,但闭包在这里与它无关。您在这里只需要一个本地范围。
执行 console.log
的函数是一个闭包。它是一个采用作用域链并能够访问 count
的函数。这是闭包的行为。
因此此函数可以访问 count
,而其他任何函数都不能。所以这个IIFE提供了一个很好的方式来写一些自包含的东西,不污染外界,也不让外界污染它。