【发布时间】:2020-05-21 00:03:49
【问题描述】:
了解 IIFE,我知道使用它们可以:
- 不污染全局范围
- 保护您的代码不受他人影响。
有人可以帮我更好地理解它,并举一个真实的例子说明我在使用常规函数语句(而不是 od IIFE)时会遇到麻烦吗?
【问题讨论】:
-
你的意思是 IIFE:立即调用函数表达式?
-
在模块之外,(几乎)每个脚本都应该在 IIFE 中关闭。
标签: javascript
了解 IIFE,我知道使用它们可以:
有人可以帮我更好地理解它,并举一个真实的例子说明我在使用常规函数语句(而不是 od IIFE)时会遇到麻烦吗?
【问题讨论】:
标签: javascript
假设您有一个相当大的代码库(几千行或更多)。将每个函数都放在顶层并不是一个好主意,因为那样很容易不小心将一个函数名写了两次,这会由于名称冲突而导致错误。例如:
// code around validating user registration
function validate(username) {
return /someValidationRegex/.test(username);
}
// do stuff with validate
// And then, far elsewhere in the code,
// you need to validate an input for sending to the server:
function validate(input) {
return /someOtherValidationRegex/.test(input);
}
// do stuff with validate
这不起作用,因为最后一个validate 函数将覆盖第一个validate 函数,代码将无法按预期运行。
改为将每个代码段放入 IIFE,以避免名称冲突的可能性:
(() => {
// code around validating user registration
function validate(username) {
return /someValidationRegex/.test(username);
}
// do stuff with validate
})();
(() => {
// code around validating an input for sending to the server:
function validate(input) {
return /someOtherValidationRegex/.test(input);
}
// do stuff with validate
})();
这是Stack Overflow's Javascript uses 的技术(至少在某些部分)。
即使您小心不要重复函数名称,使用 IIFE 的另一个原因是您可能不小心复制了 窗口属性。例如,以下是人们遇到的一个比较常见的错误:
// name is defined to be a number...
var name = 5;
// but it's actually a string???
console.log(typeof name);
这里的问题是您不小心引用/覆盖了顶层的window.name 属性,而window.name 可能只是一个字符串。在顶层定义了一大堆函数和变量。为避免名称冲突,请将所有内容放入 IIFE:
(() => {
// name is defined to be a number...
var name = 5;
// And it's still a number, good
console.log(typeof name);
})();
不过,如果您的代码库足够大,名称冲突的可能性很大,而不是手动编写 IIFE,我强烈建议您使用模块系统,例如使用 Webpack。这将允许您在自己的封装范围内编写模块,而不会发生泄漏或名称冲突,并且将更易于维护,因为每个模块只包含它需要运行的代码,仅此而已。这使得识别错误和扩展功能比您必须手动浏览的一大长 <script> 更容易。
【讨论】:
IIFE 将实际运行(立即调用的函数表达式),它们不需要触发器或函数调用来启动它们,因此变量将设置为其响应。
这是一个 Fiddle 来证明这一点:
var iffe = (function() {
return 'foo';
})();
var func = function() {
return 'bar';
};
console.log('iife = ' + iffe);
console.log('non-iife = ' + func);
在您的 JS 控制台中,您会看到类似于以下内容的内容:
iife = foo 和
非生命=函数(){ 返回“酒吧”; }
此外,如果我们需要从外部范围传递 IFFE 范围内的某些内容,我们需要将它们作为参数传递并在 IFFE 包装中定义的函数中接收它,如下所示 -:
var iffe = (function(doc) {
return 'foo';
})(document);
这是更多参考的链接 - http://benalman.com/news/2010/11/immediately-invoked-function-expression/
【讨论】: