2013-11-15 48 views
0

发现了TypeScript后,我玩了在线编译器,生成的JavaScript代码让我怀疑函数表达式。全局范围内的函数表达式

一个简单的打字稿类:

class Person { 
    firstName: String = "John"; 
    lastName: String = "Doe"; 
} 

结果在下面的JavaScript代码:

var Person = (function() { 
    function Person() { 
     this.firstName = "John"; 
     this.lastName = "Doe"; 
    } 
    return Person; 
})(); 

这让我不知道为什么他们选择了与自动执行功能,走的时候更简单的东西可能有足够了。与变量名称相同的内部函数的目的是什么?
又为什么不走的东西比较简单,如:

var Person = function() { 
    this.firstName = "John"; 
    this.lastName = "Doe"; 
}; 

甚至:

function Person() { 
    this.firstName = "John"; 
    this.lastName = "Doe"; 
} 


至于我可以告诉使用在全球范围函数表达式没有提供优点,只有在声明之前不能调用该函数的缺点。

+0

我很快玩过,找不到任何有效的理由。即使对于私有静态变量,他们也没有使用它们的模块范围,因为私有仅在编译时执行。 – plalx

+0

这只是编译器的一个缺陷。类将始终编译为IEFE,因为“模块”模式有助于组织类构造代码,并允许静态(全班范围的“私有”)变量。当他们不需要它们时,他们忘了解开IEFE。 – Bergi

回答

2

它有助于继承。这使他们能捕捉到基类的重命名,以_super与代码生成例如为:

class Foo{ 

} 

class Bar extends Foo{ 

} 

成为帮助:

var __extends = this.__extends || function (d, b) { 
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 
    function __() { this.constructor = d; } 
    __.prototype = b.prototype; 
    d.prototype = new __(); 
}; 
var Foo = (function() { 
    function Foo() { 
    } 
    return Foo; 
})(); 

var Bar = (function (_super) { 
    __extends(Bar, _super); 
    function Bar() { 
     _super.apply(this, arguments); 
    } 
    return Bar; 
})(Foo); // Notice base class is captured here 

这是JS很好的做法也是如此。例如,如果在此示例中保留使用Foo而不是_super,并且您要更改基类,则可能会产生令人头痛的一系列可以避免的干扰。

-1

这允许您制作一些私有变量。

在JS:

var Person = (function() { 
    var firstName, lastName; //static private vars 
    function Person(fName, lName) { 
     firstName = fName; 
     lastName = lName; 
    } 
    return Person; 
})(); 
+0

你也可以在我提供的其他选项中做到这一点。 – Acidic

+1

这些将在所有实例之间共享。非常糟糕的例子。 – plalx

+1

@您的示例中的酸性首字母和姓氏是**不是**私人的,可以从外部访问。 – qwertynl

1

你真的不希望能够它的声明已执行之前调用的类。考虑以下代码:

class Person { 
    static nameSeparator = ' '; 

    public fullName: string; 

    constructor(public firstName, public lastName) { 
     this.fullName = firstName + Person.nameSeparator + lastName; 
    } 
} 

而其产生的形式:

var Person = (function() { 
    function Person(firstName, lastName) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
     this.fullName = firstName + Person.nameSeparator + lastName; 
    } 
    Person.nameSeparator = ' '; // <-- Important! 
    return Person; 
})(); 

你想要的意外运行之前指定的线与未定义行为运行代码(在这种情况下,Person.fullName是“JohnundefinedSmith “),还是只是失败?

在其他情况下,该类根本不会在所有的工作:

class Person { 
    constructor(public firstName, public lastName) { 
     // Will fail until Person.prototype.getFullName gets set 
     console.log('New person, name = ' + this.getFullName()); 
    } 

    getFullName() { 
     return this.firstName + " " + this.lastName; 
    } 
} 
+0

为什么必须定义为Person.nameSeparator? – qwertynl

+0

而不是什么? –

+0

而不是像我的答案中定义的那样声明静态变量。 – qwertynl