问题 定义Javascript原型


以下两个Javascript原型之间的功能差异是什么,选择其中一个有什么好处?

选项1:

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

选项2: 

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

我是否正确地假设 选项2 导致某些与原型隐式绑定的函数被废弃?


10038
2017-07-04 15:59


起源

也可以看看 这些原型声明有什么区别? - Bergi


答案:


假设选项2导致某些隐含绑定到原型的函数被废弃,我是否正确?

对,就是这样。虽然唯一隐含约束的属性是 constructor 财产,你很少需要。

有什么功能差异?

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

选择其中一个是否有任何好处?

这些应该是现在自我解释。选项1(扩展)被认为是更清晰的,如果您正在修改外来/未知/原生原型,则必须使用它。尽量避免选项2。

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

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

你可能需要 填充工具 Object.assign 适用于ES6之前的环境。或者, $.extend 要么 _.extend 工作也一样。当然,您最喜欢的库也带有辅助功能。


5
2017-07-04 16:46



为什么选择1应该被视为更清洁。它似乎是选项2是从一个干净的石板开始的方式可以这么说。 - Alexander Mills
@AlexMills:因为你不需要知道你原本会覆盖的原型上已存在哪些属性,并且不会破坏它们(无论代码在何处被调用)。它更简单,更不容易出错并且向前兼容。当然,如果你从头开始创建一个原型对象,你也可以使用对象文字,但即便如此,大多数人都忘记了标准 constructor 属性。 - Bergi


第二个将用对象覆盖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"

3
2017-07-04 16:15





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

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


2
2017-07-04 16:04



我知道当添加到现有的代码库(如Math)时,您不希望完全删除原型,但是从头开始创建新库时,我有什么理由不应该删除原型吗?换句话说,当我创建一个新的原型时,它是否已经附加了任何功能,或者它只是一个空白的占位符? - Richard Keller
@RichardKeller您将使用Object覆盖函数的原型,因此您无法使用 new this.constructor() 创建一个新的实例 this: phrogz.net/JS/classes/OOPinJS2.html - HMR
使用新原型你很安全。我尝试在谷歌Chrome控制台进行实验,但我不能破坏任何重要的东西。看到这个 链接。 - isaach1000


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


选项1优于选项2的优点很简单,就是您不必重新构建构造函数属性,并且保存一个对我来说很大的缩进级别。

为了节省重复,我只需将属性分配给局部变量:

var method = Person.prototype;

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

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

常见的选择也是 fn (jQuery)和 p 甚至更短 method


1
2017-07-04 17:10





简单来说就是差异 Person.prototype.sayName 你所要做的就是添加一个功能 prototype。只是添加新功能。

在第二 Person.prototype = {} 在这里,您正在创建一个新的整个对象并将其分配给 prototype。所以你创建新对象或覆盖 prototype 用一个新的对象。

第一种方法可以根据需要添加许多功能 一经请求。你可以按时添加它们,所以当你的程序很简单并且你的应用程序对象不能在它们之间共享很多函数或对象时,我认为它很好。

如果你的应用程序对象共享一些,第二种方法是好 对象(或@isaach所说的一组功能 Math functions) 其中。


0
2017-07-04 16:39