IIFE 执行的意外顺序



我有点自学成才的JS黑客,并试图变得更加正式,因为我必须构建一个行为更好的JS应用程序,它是命名空间和更好的JS公民。我将不胜感激一些关于我在这里做错了什么的指示。

这个想法是使用第一个闭包来构造命名空间,然后在第二个闭包中,我将一个方法添加到命名空间对象中,一个"类"构造函数。I 在子上调用方法。

(function() {
'use strict';
/**
* @namespace ProjectX
*/
var ProjectX = {
attr1: 'I am inside ProjectX'

}
window.ProjectX = ProjectX;
})()
//console.log(ProjectX.attr1); // When this line is uncommented the code will output 'foobar' as expected?
(function() {
'use strict';
ProjectX.subObj = function(val) {
this.name = val;
return this;
};
})();
var subObj = new ProjectX.subObj('Foobar');
console.log(subObj.name);

我希望在控制台日志中看到"Foobar"。但是,这会在控制台中产生以下结果:

{ "消息": "未捕获的类型错误: (中间值)(中间值)(中间值)(...)不是函数", "文件名": "http://stacksnippets.net/js", "线号": 03, "科尔诺":1 }

当我阅读这段代码时,我希望两个IIFE将按顺序执行,第一个使ProjectX栩栩如生,然后第二个向ProjectX添加另一个构造函数,该构造函数将返回一个subObj。此外,如果第 16 行的 console.log((ProjectX.attr1) 未注释,则代码将按我的预期运行。这似乎表明ProjectX实体在我引用它之前并不"存在"。这与我对IIFE的理解相矛盾,即它们立即运行,无论如何,ProjectX不是一个构造函数 - 它是一个全局变量。

在研究中,我发现 IIFE 内部的功能无法识别,这似乎是类似的领域,但与将事件绑定到 DOM 有关,而不是与我的查询并行。

您在第一个 IIFE 之后缺少一个分号,当控制台及其分号被删除时.log分号将变得相关。您可以在 JS 中搜索需要分号的情况

如果没有分号,您的代码可以解释为:

(function() {
var ProjectX = {
attr1: 'I am inside ProjectX'
}
window.ProjectX = ProjectX;
})()(function() {
ProjectX.subObj = function(val) {
this.name = val;
return this;
};
})();

检查以下格式为(IIFE)()()的函数,这是有效的,因为 IIFE 返回一个函数,该函数使用('Hey')

调用

(function() {
return function(msg){console.log(msg)}
})()('Hey')

如果没有分号,javascript 期望你的第一个 IIFE 返回一个函数,而你的代码并非如此,所以它会抛出一个 Type 错误,说它需要一个函数,但没有得到定义。代码最终计算结果为:

undefined(function() {
ProjectX.subObj = function(val) {
this.name = val;
return this;
};
})();

或更简化为

undefined(<a function as parameter>)()

然后抛出错误,即此处应function而不是undefined

阅读 javascript 中的高阶函数,以更好地了解此语法以及您的代码不明确的内容。

最新更新