17

我正在阅读来自 Microsoft 的名为TypeScript的新的类似 JavaScript 的语言。在Playground(示例部分)中,有一个 TypeScript 语法转换为 JavaScript 代码的简单类。来自 Java 编程背景,学习如何在 JavaScript 中完成从 TypeScript 编译的 OOP 对我来说很有趣。

打字稿代码:

class Greeter {
    greeting: string;
    constructor (message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}   

var greeter = new Greeter("world");

var button = document.createElement('button')
button.innerText = "Say Hello"
button.onclick = function() {
    alert(greeter.greet())
}

document.body.appendChild(button)

和等效的 JavaScript 代码:

var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
var greeter = new Greeter("world");
var button = document.createElement('button');
button.innerText = "Say Hello";
button.onclick = function () {
    alert(greeter.greet());
};
document.body.appendChild(button);

Typescript 部分与 Java 非常相似,所以我理解这一点。现在我的问题是为什么在 JavaScript 中Greeter类的主体嵌入在匿名function()调用中?

为什么不这样写呢?

function Greeter(message) {
    this.greeting = message;
}
Greeter.prototype.greet = function () {
    return "Hello, " + this.greeting;
};

每种方法的优点/缺点是什么?

4

6 回答 6

15

以下称为立即调用函数表达式

(function(){ ... })();

它用于保持全局范围清洁。但是,在这种情况下,它不是必需的,因为返回值已分配给 variable Greeter。这种模式唯一有用的时候是当您需要“私有”静态成员时。

例如:

var Greeter = (function () {
    var foo = 'foo', bar = 'bar'; /* only accessible from function's defined
                                     in the local scope ... */

    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
于 2012-10-02T14:30:10.447 回答
3

这是为了允许私人成员。在此示例中,所有成员都是公共的,因此您的两个结构是等效的。但是,如果您想提供私有成员,则需要通过闭包将它们隐藏在调用范围之外。因此,如果您有这样的私人成员:

class Greeter {
    private greeting: string;
    constructor (message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
} 

你可能会得到这样的东西:

var Greeter = (function () {
    var greeting="";
    function Greeter(message) {
        greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + greeting;
    };
    return Greeter;
})();

问候变量将可用于匿名函数内定义的任何函数,但在其他任何地方都不可见。

于 2012-10-02T14:36:14.053 回答
3

除了明显的范围/关闭推理。使用立即调用自身的匿名函数预加载(解释)类定义。这允许在执行中预先加载任何 JIT 优化。简而言之,对于更大更复杂的应用程序,它将提高性能。

于 2012-10-02T14:44:19.133 回答
2

匿名函数/自执行闭包通常用于封装作用域,以便在其外部只能访问返回值。(或您附加到其他对象的任何东西,如窗口)

于 2012-10-02T14:31:01.710 回答
1

匿名函数可能是为了防止与代码的其他部分发生名称冲突。这样想,在您的匿名函数中,您甚至可以将名为“$”的变量声明为您想要的任何变量,同时在代码的其他部分使用 jQuery 而不会发生冲突。

于 2012-10-02T14:31:08.120 回答
-4

闭包是使用参数调用构造函数的唯一方法:

var w = new Greeter("hello")

还有其他方法,但都很复杂,有局限性和缺点。

于 2014-07-18T08:13:57.677 回答