我想知道以下之间是否有任何区别
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在后台是如何工作的,我希望能澄清一下。
第一个和第二个几乎相同。真正的区别可以在第三个选项中注意到。在这种情况下,您将返回一个函数,该函数可能会用new运算符调用。然而,第三种选择有一些缺点,使其成为最糟糕的选择:
所有Dog函数的Fisrt将创建一个新对象,在内存中分配一个新的Bark功能。因此,就内存效率而言,这个选项显然比其他两个最差,因为其他两个选项只创建了一个分配给单个Bark函数的对象。回到第三种情况,你可以通过以下操作来改进它:
define(
function () {
function Dog() {
};
Dog.prototype.Bark = function () { alert('Woof! Woof! Woof!'); };
return Dog;
});
通过这样做,您可以确保只有一个Bark函数的实例,该实例将由使用Dog功能创建的所有对象共享。
我注意到的另一个缺陷是,您没有确保Dog函数将创建一个对象。我的意思是,如果在没有新运算符的情况下调用它,会发生什么?。这可能是像这样的非常讨厌的错误的原因:
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;
});
有了这个改进的第三个选项,选择取决于您试图解决的问题。您需要该对象的多个实例吗?如果是这种情况,那么您应该使用改进的第三个选项,否则您可以使用第一个或第二个选项。
第一个和第二个示例实际上是相同的,在第一个示例中,您只需通过使用临时变量命名对象来向读取器发出返回对象"类型"的信号。需要注意的一点是,这个对象在所有需要这个模块作为依赖项的模块中都是共享的,因此是一种单例。
第三个则大不相同。如果Dog
是该模块的别名,并且需要该模块作为依赖项,则返回的函数将用于根据new Dog()
创建新对象(或多个对象)。此函数是共享的,但不包含Bark
或其他方法,它的实例包含,但这些不共享。
你可以把第三个也写成
define(function () {
return function Dog() {
this.Bark = function () { alert('Woof! Woof! Woof!'); };
};
});
其中函数的Dog名称甚至是可选的(但通常建议用于可读性/调试)。