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永远是真实的,对吗?@atconwaytest
如果是第一个声明var-test
并在以后分配它。如果它是第二个带有var-test
的脚本,test
将已经被定义,并且将是真实的。因此我理解您关于第1次/2次的解释以及test
的值,但是您能否详细说明它与您关于允许模块的评论的关系是否为开放式
?我不确定我是否理解该部分。@atconway可能是开放式
,就像中的多文件内部模块一样