TypeScript模块的JavaScript IIFE中默认参数的用途是什么?

TypeScript模块的JavaScript IIFE中默认参数的用途是什么?,javascript,typescript,iife,Javascript,Typescript,Iife,如果我创建一个名为test的简单TypeScript模块,它将如下所示: module test { export class MyTest { name = "hello"; } } var test; (function (test) { var MyTest = (function () { function MyTest() { this.name = "hello"; }

如果我创建一个名为
test
的简单
TypeScript模块
,它将如下所示:

module test
{
    export class MyTest {
        name = "hello";
    }
}
var test;
(function (test) {
    var MyTest = (function () {
        function MyTest() {
            this.name = "hello";
        }
        return MyTest;
    })();
    test.MyTest = MyTest;
})(test || (test = {}));
生成的
JavaScript
创建一个
iLife
,如下所示:

module test
{
    export class MyTest {
        name = "hello";
    }
}
var test;
(function (test) {
    var MyTest = (function () {
        function MyTest() {
            this.name = "hello";
        }
        return MyTest;
    })();
    test.MyTest = MyTest;
})(test || (test = {}));
我不明白的是
IIFE
末尾的下一行包含
函数的参数的目的是什么:

(test || (test = {}));
结果函数还接受参数
test

(function (test) {
当使用参数传入一个“
jQuery
对象,比如
}”(jQuery)时,我理解了这一点和生成的函数可以采用别名,如
(函数($){
。但是,我没有看到
(test | |(test={}))
参数的用途


我知道
test.MyTest=MyTest;
公开了公共方法
MyTest
,但是为什么
(test | | |(test={}))
以及这些参数是如何工作的呢?

它是一种扩展已经存在的对象的方法,或者在尚未定义的情况下对其进行初始定义。让我们把它分解一下

var test;
此行声明变量
test
,以便以后使用时不会抛出
ReferenceError
。它的值将是
未定义的
,或者是
test
已有的任何值

(test || (test = {}))

如果
test
为真值(即未定义
未定义
),则本节通过
test
的值,或将
test
分配给新对象,并将该对象传递给函数。这样,使用此代码的每个文件都可以扩展一个公共名称空间对象,而不是覆盖名称空间。

它允许您将模块设为开放式。例如

(function (test) {
    var MyTest = (function () {
        function MyTest() {
            this.name = "hello";
        }
        return MyTest;
    })();
    test.MyTest = MyTest;
})(test || (test = {}));


(function (test) {
    var SecondTest = (function () {
        function SecondTest() {
            this.name = "hello";
        }
        return SecondTest;
    })();
    test.SecondTest= SecondTest;
})(test || (test = {}));
第一次
测试
将是
未定义的
,因此被分配
{}
。下一次它已经定义,这就是我们用
第二次测试扩展的内容

这有帮助吗

var test;

function IIFE(test) {
    var MyTest = (function () {
        function MyTest() {
            this.name = "hello";
        }
        return MyTest;
    })();
    test.MyTest = MyTest;
}

test = test || {}
IIFE(test);
由于
var test
被拉到顶部,并且不会“取消分配”或覆盖任何现有的
test
,因此如果test定义在与iLife相同的范围内,则将使用它而不是空对象。

要扩展其他人所说的内容并回答您的其他一些在线问题:

“开放式”,它们指的是以后继续向对象添加成员的能力。如果您只能在单个源文件中创建和扩展对象,那么我们可以保证初始化顺序并使代码更简单,但是您可以在script1.ts和script2.ts中包含以下代码,并将其包含在第i页中n任意顺序,因此我们无法知道脚本运行时M1是否已初始化

script1.ts

模块M1{
导出模块M2{
导出函数F1(){return 42;}
}
}
script2.ts

模块M1{
导出模块M2{
导出函数F2(){返回“测试”;}
}
}
虽然重新定义变量没有吸引力,但它是无害的(请参阅)。初始化之前的值为“未定义”,这意味着表达式“M1 | |(M1={})”的第二部分计算并返回,新初始化的对象在第一次命中时作为参数传递,否则表达式开头的现有值作为后续声明的参数传递

在我的示例中,我特意使用嵌套模块来说明这不仅适用于变量,还适用于对象的属性。为上面的“script1”文件(与“script2”类似)生成的代码是:

script1.js

var-M1;
(功能(M1){
var M2;
(功能(平方米){
函数F1(){
返回42;
}
M2.F1=F1;
})(M2=M1.M2 | |(M1.M2={}));
})(M1 | |(M1={}));
这里,嵌套模块M2作为立即数函数的参数提供为“M1.M2 | |(M1.M2={}”,如果M1.M2存在,则再次提供其现有值,否则将其初始化为空对象,然后提供此值。此对象属性表示模块M1.M2,由嵌套函数中的参数M2引用,该参数随后向其添加更多成员(其导出)


我希望这有助于澄清。

它确保测试是先前定义的,或者它被实例化为空对象。内部函数不需要检查它的存在,相同的“模块”可以传递给其他导出。记住我的这个老问题,并看到了这篇博文:“全局导入”解释中的部分在我的代码示例和你的解释中,由于
test
是在顶部
var test
定义的,所以test永远不会
未定义
,test永远是真实的,对吗?@atconway
test
如果是第一个声明
var-test
并在以后分配它。如果它是第二个带有
var-test
的脚本,
test
将已经被定义,并且将是真实的。因此我理解您关于第1次/2次的解释以及
test
的值,但是您能否详细说明它与您关于
允许模块的评论的关系是否为开放式
?我不确定我是否理解该部分。@atconway可能是开放式
,就像中的多文件内部模块一样