符合AMD标准的JavaScript - 定义然后返回与返回之间的任何区别

时间:2014-09-13 08:54:07

标签: javascript functional-programming

我想知道以下

之间是否有任何区别
define(
    function () {
        var Dog = {
             Bark: function () { alert('Woof! Woof! Woof!'); }
        };
    return Dog;
});

define(
    function () {
        return {
             Bark: function () { alert('Woof! Woof! Woof!'); }
        };
});

define(
    function () {
        function Dog()  {
             this.Bark = function () { alert('Woof! Woof! Woof!'); };
        };
    return Dog;
});

我认为我更喜欢第一个看起来如何,但我担心它与第二个和第三个不同之处在于它会在返回之前进行评估......我意识到这是一个愚蠢的陈述因为很明显所有的函数声明都需要在某些时候进行评估,但不知道JavaScript是如何工作的,我希望得到澄清。

2 个答案:

答案 0 :(得分:1)

第一个和第二个例子实际上是相同的,在第一个例子中,您只是通过使用临时变量命名它来向读者发出对象的“种类”。需要注意的一点是,在需要此模块作为依赖关系的所有模块中共享此对象,因此是一种单例。

第三个是完全不同的。如果new Dog()是此模块的别名(在需要此模块作为依赖项的位置),则返回一个用于创建新对象(或更多)的函数Dog 。此函数是共享的,但不包含Bark或其他方法,其实例可以,但不共享。

您也可以将第三个写为

define(function () {
    return function Dog()  {
         this.Bark = function () { alert('Woof! Woof! Woof!'); };
    };
});

函数的Dog名称甚至是可选的(但通常建议用于可读性/调试)。

答案 1 :(得分:1)

第一和第二几乎相同。在第三个选项中可以注意到真正的差异。在这种情况下,您将返回一个可能使用 new 运算符调用的函数。然而,第三种选择有一些错误使它成为最糟糕的选择:

所有 Dog 函数的Fisrt将创建一个新对象,在内存中分配新的 Bark 函数。所以在内存效率方面,这个选项显然比其他两个选项差,因为其他两个只是在单个 Bark 函数上创建一个单独的对象。回到第三种情况,您可以通过以下方式改进它:

define(
    function () {
        function Dog()  {
        };

        Dog.prototype.Bark = function () { alert('Woof! Woof! Woof!'); };
    return Dog;
});

通过这样做,您可以确定只有一个 Bark 函数的实例将由使用 Dog 函数创建的所有对象共享。< / p>

我注意到的另一个缺点是你没有确保 Dog 函数会创建一个对象。我的意思是,如果在没有 new 运算符的情况下调用它会发生什么?它可能是这个非常讨厌的错误的原因:

var tommy = Dog();
tommy.Bark(); //Bark is undefined because tommy is equal to Dog's return value

所以要解决这个问题,你可以这样做:

define(
    function () {
        function Dog()  {
            if(!(this instanceof Dog)){
                return new Dog();
            }
        };

        Dog.prototype.Bark = function () { alert('Woof! Woof! Woof!'); };
    return Dog;
});

使用改进的第三个​​选项,选择依赖于您尝试解决的问题。您是否需要该对象的多个实例?就是这种情况,那么你应该使用改进的第三个​​选项,否则你可以使用第一个或第二个选项。