定义 Javascript 原型

IT技术 javascript oop prototype
2021-02-04 03:42:43

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

选项1:

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

选项 2:

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

我是否正确地假设选项 2 会导致某些隐式绑定到原型的函数被破坏?

5个回答

我是否正确地假设选项 2 会导致某些隐式绑定到原型的函数被破坏?

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

有哪些功能差异?

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

选择一个而不是另一个有什么好处吗?

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

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

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

您可能需要填充工具Object.assign预ES6环境。或者,$.extend也可以_.extend正常工作。当然,您最喜欢的库也为此提供了一个辅助函数。

@AlexMills:因为您不需要知道原型上已经存在哪些属性,否则您会覆盖这些属性,并且不会破坏它们(无论代码在哪里调用)。它更简单、不易出错且向前兼容。当然,如果您从头开始创建原型对象,您也可以使用对象字面量,但即便如此,大多数人还是忘记了标准constructor属性。
2021-03-13 03:42:43
为什么应该将选项 1 视为更清洁。可以说,选项 2 似乎是从头开始的方式。
2021-04-02 03:42:43

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

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

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

您对新原型非常安全。我尝试在 Google Chrome 控制台中进行试验,但我无法破坏任何重要的东西。请参阅此链接
2021-03-17 03:42:43
我知道在添加到现有代码库(如 Math)时,您不想完全丢弃原型,但是从头开始创建新库时,有什么理由不应该丢弃原型吗?换句话说,当我创建一个新原型时,它是否已经附加了任何功能,或者它只是一个空白占位符?
2021-03-24 03:42:43
@RichardKeller 您将使用 Object 的原型覆盖函数的原型,因此您不能使用它new this.constructor()来创建新的实例thisphrogz.net/JS/classes/OOPinJS2.html
2021-03-27 03:42:43

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


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

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

var method = Person.prototype;

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

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

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

简而言之,区别在于Person.prototype.sayName您所做的只是向prototype. 只是添加新功能。

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

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

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