11

What are the functional differences between the following two Javascript prototypes, and are there any benefits for choosing one over the other?

Option 1:

Person.prototype.sayName = function(name) {
   alert(name);
}

Option 2:

Person.prototype = {
   sayName: function(name) {
      alert(name);
   }
}

Am I correct in assuming that Option 2 results in trashing certain functions that are implicitly bound to the prototype?

4

5 回答 5

6

我是否正确假设选项 2 导致丢弃某些​​隐式绑定到原型的函数?

对,就是这样。尽管唯一隐式绑定的属性是constructor您很少需要的属性。

有什么功能差异?

选项 1 只是扩展现有原型。如果已经有Person从原型对象继承的实例,它们也将能够使用该sayName方法。使用选项 2,新原型将仅用于覆盖后实例化的对象。

选择其中一个有什么好处吗?

这些现在应该是不言自明的了。选项 1(扩展)被认为更简洁,如果您要修改外部/未知/本地原型,则必须这样做。尽量避免选项 2。

如果您仍然更喜欢对象字面量语法,则应考虑使用Object.assign来扩展现有原型:

Object.assign(Person.prototype, {
   sayName: function(name) {
      alert(name);
   }
});

您可能需要为ES6 之前的环境进行polyfillObject.assign。或者,$.extend也可以_.extend正常工作。当然,您最喜欢的库也为此提供了帮助函数。

于 2013-07-04T16:46:54.823 回答
3

第二个将用对象覆盖 person.prototype。

方法一:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype.sayName=function(){}
console.log(Person.prototype.constructor.toString());// "Person to string"

方法二:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype = {
  sayName:function(){}
}
console.log(Person.prototype.constructor.toString());// "Object to string"
于 2013-07-04T16:15:56.440 回答
2

第一个适用于一两个额外的功能,但是定义一个具有许多功能的全新原型将是非常重复的。另一方面,如您所述,执行后者会破坏原型的所有现有定义。

在实践中,我使用第一个来定义 Array 和 Math 等中的附加函数,有点像 Objective-C 中的类别。后者我用作“类定义”。

于 2013-07-04T16:04:23.607 回答
1

构造函数的任何现有实例将继续指向旧的原型对象。创建的任何新实例都将指向新的原型对象。


选项 1 相对于选项 2 的优点仅仅是您不必重新建立构造函数属性,并且您节省了一个缩进级别,这对我来说是巨大的。

为了避免重复,我只是将属性分配给一个局部变量:

var method = Person.prototype;

method.getAge = function() {
    return this.age;
};

method.getName = function() {
    return this.name;
};

同样常见的选择是fn(jQuery),p它甚至比method.

于 2013-07-04T17:10:56.720 回答
0

简而言之,不同之处在于Person.prototype.sayName您所做的只是将一个函数添加到prototype. 只是添加新功能。

在第二个Person.prototype = {}中,您正在制作一个新的整个对象并将其分配给prototype. 因此,您创建新对象或用新对象覆盖prototype

第一种方法可以根据需要添加许多功能。您可以按时添加它们,因此我认为当您的程序很简单并且您的应用程序对象之间不共享太多功能或对象时会很好。

如果您的应用程序对象在它们之间共享一些对象(或@isaach 中所说的一组函数),则第二种方法很好Math functions

于 2013-07-04T16:39:36.773 回答