使用此JavaScript编码模式定义构造函数有什么好处?

使用此JavaScript编码模式定义构造函数有什么好处?,javascript,constructor,anonymous-function,function-prototypes,module-pattern,Javascript,Constructor,Anonymous Function,Function Prototypes,Module Pattern,我倾向于用以下方式编写对象构造函数: function Person(name) { this.name = name; } Person.prototype.greet = function () { alert("Hello! My name is " + this.name + "."); }; 我注意到一些JavaScript库和框架添加了一些额外的代码,如下所示: var Person = (function () { function Person(name

我倾向于用以下方式编写对象构造函数:

function Person(name) {
    this.name = name;
}
Person.prototype.greet = function () {
    alert("Hello! My name is " + this.name + ".");
};
我注意到一些JavaScript库和框架添加了一些额外的代码,如下所示:

var Person = (function () {
    function Person(name) {
        this.name = name;
    }
    Person.prototype.greet = function () {
        alert("Hello! My name is " + this.name + ".");
    };
    return Person;
})();
我知道自动执行匿名函数的作用和用途。目前我没有看到的是,在定义构造函数及其原型时,它提供了什么优势或好处

编辑#1:

我知道模块模式及其优点,并在编码中经常使用它。我在沟通中的错误是不清楚我的第一个代码示例不应该在全局范围内。我总是将所有外部JavaScript文件包装在一个自动执行的匿名函数中,以在代码上强制执行本地作用域

例如:

;(function ( window, undefined ) {
    var p = function (name) {
        this.name;
    };
    p.prototype.greet = function () {
        alert("Hello! My name is " + this.name + ".");
    };
    window.Person = window.Person || p;
})(window);
;(function ( window, undefined ) {
    var p = (function () {
        var q = function (name) {
            this.name = name;
        };
        q.prototype.greet = function () {
            alert("Hello! My name is " + this.name + ".");
        };
        return q;
    })();
    window.Person = window.Person || p;
})(window);
问题是,我在第二个代码示例中看到了在这样一个匿名函数中使用的技术

例如:

;(function ( window, undefined ) {
    var p = function (name) {
        this.name;
    };
    p.prototype.greet = function () {
        alert("Hello! My name is " + this.name + ".");
    };
    window.Person = window.Person || p;
})(window);
;(function ( window, undefined ) {
    var p = (function () {
        var q = function (name) {
            this.name = name;
        };
        q.prototype.greet = function () {
            alert("Hello! My name is " + this.name + ".");
        };
        return q;
    })();
    window.Person = window.Person || p;
})(window);

这就是我对这项技术的重要性感到困惑的地方。

第二种方法,模块模式,更便于移植。请注意,您可以将
Person
命名为任何您想要的名称

在第一种方法中,您必须跟踪每次出现的
Person
,并且在将构造函数+原型复制到另一个项目时,小心不要意外删除部分方法


第二种方法还有一个额外的优点:您可以使用本地/临时/丢弃变量,这些变量可以用来动态定义命名空间上的常量/方法/属性。

它实际上是一个命名空间,不是吗?

我更喜欢第一种解决方案,代码越少越清晰


我认为只有经常将代码复制粘贴到其他库中,第二种解决方案才会更好,但我认为这不是一个好的理由,这是我的同事的答案,他不仅对JavaScript有着不可思议的了解,而且对浏览器中的各种JavaScript引擎的工作方式也有着不可思议的了解,他告诉我,这种代码模式是一种不必要的过度防御的方式,用于定义对象,这些对象用于处理某些JavaScript解析器(他特别引用了Opera版本)中允许范围爬行的错误。这听起来确实是一个合理的答案……

在这个具体的例子中,没有区别。我认为对于一个更复杂的类来说,这可能很重要,这取决于框架在额外作用域中所做的工作。@Domenic-您的答案与我所希望的一样。我想知道是否有人能详细说明这一点。不,你是对的。这通常就是这种模式的用途;为了避免通过将所有内容包装在closure.Na中而污染全局名称空间,我认为“namespace”和“closure”之间有区别。当然,窗口对象类似于名称空间,您可以使用闭包来填充名称空间,但在这些示例中不能。