IIFE 执行的意外顺序

Unexpected sequence of IIFE execution

我是一个自学 JS 的人,我想变得更正式一点,因为我必须构建一个行为更好的 JS 应用程序,它是命名空间的,并且是一个更好的 JS 公民。对于我在这里做错了什么,我将不胜感激。

我的想法是使用第一个闭包来构造一个命名空间,然后在第二个中我向命名空间对象添加一个 'class' 构造函数的方法。我在子上调用了一个方法。

(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'。然而,这会在控制台中产生以下结果:

{ "message": "Uncaught TypeError: (intermediate value)(intermediate value)(intermediate value)(...) is not a function", "filename": "http://stacksnippets.net/js", "lineno": 03, "colno": 1 }

当我阅读这段代码时,我希望两个 IIFE 将按顺序执行,第一个使 ProjectX 生效,然后第二个向 ProjectX 添加一个进一步的构造函数,它将 return 一个 subObj。此外,如果第 16 行的 console.log((ProjectX.attr1) 未注释,代码将如我预期的那样 运行。这似乎表明 ProjectX 实体不是 'present'直到我引用它。这与我对 IIFE 的理解相矛盾,即它们 运行 立即,无论如何,ProjectX 不是构造函数 - 它是一个全局变量。

在研究中我发现 function inside of IIFE not recognized 这似乎是相似的领域,但与将事件绑定到 DOM 有关,而不是与我的查询平行。

您在第一个 IIFE 后缺少一个分号,当 console.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 returns 一个函数,用 ('Hey')

调用

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

没有分号,javascript 期望你的第一个 IIFE returns 是一个函数,而你的代码不是这种情况,所以它抛出一个类型错误,说它期望一个函数但未定义反而。您的代码最终计算为:

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

或更简化为

undefined(<a function as parameter>)()

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

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