Javascript:函数/类的原型属性的默认值背后的逻辑是什么?

时间:2019-11-12 18:38:53

标签: javascript function inheritance prototype

我们知道JavaScript具有原型继承而不是经典继承,这意味着每个对象 具有[[Prototype]]属性,可用于通过原型链进行继承。

但是,我无法理解的原型继承模型的一部分是默认的原型属性背后的逻辑,该默认原型属性是函数(或类)对象最初获得的。即

  //For classes
  class Dog {}
  Dog.prototype // {constructor: Dog}

  //For functions
  function Cat() {}
  Cat.prototype // {constructor: Cat};

让此属性包含指向函数本身的构造函数有什么用?我了解一种用法,即如果定义以某种方式丢失(像这样),则任何创建的对象都将获得构造函数属性,并可用于创建其他对象:

function Dog(name) {
  this.name = name;
  alert(name);
}

let dog = new Dog("White Dog");

let dog2 = new dog.constructor("Black Dog");

但是,这并不能证明这种设置非常合理(因为函数/类是唯一对自身具有这种循环引用的对象),这是不合理的。这个决定背后还有其他原因吗?

1 个答案:

答案 0 :(得分:0)

(已更新为回答实际问题,请参见下面的旧答案)

  

此决定背后还有其他原因吗?

我只能猜测,但这可能来自影响javascript的语言的设计。在pure prototype-based programming中,根本没有构造函数。只有原型对象本身定义了一个“类”,并且它将有一个init方法要在从其派生的实例上调用。伪语言示例:

dog = object create()
dog init = (name) {
  this name = name
}
mydog = dog create()
mydog init("whitey")

请注意mydog是如何从dog继承的,而object是从dog继承的。 init对象具有一个new方法,这是自然的链接。辅助方法create可能会将initmydog = dog new("blackey")捆绑在一起,称为new

现在在JavaScript中,所有东西都变成了对象,甚至函数/方法本身也成为对象。为了更像Java(当时很流行),.prototype成为了运算符,而不是继承的方法。由于某种原因,决定不将其应用于原型对象,而是将其应用于构造函数-为此,该函数具有一个function属性。也许这样可以使用简单的.prototype声明类?还是通过使用自定义对象覆盖.constructor来启用继承?我不知道。

无论如何,.prototype是两个圆形属性中更自然的一个。没有 // assuming builtins: const object = Object.create(null) object.create = function() { return Object.create(this) } object.new = function() { const o = this.create(); o.constructor(); return o } // we would use them as (assuming the object literal to inherit from `object`) var Dog = { constructor(name) { this.name = name }, woof() { alert(this.name + "makes: Woof!") } } var myDog = Dog.new("Whitey") myDog.woof() ,我们可以轻松生活:

new

强大之处在于,该对象被用作使用const mydog = new Dog("White Dog"); console.assert(Object.getPrototypeOf(mydog) === Dog.prototype) 运算符创建的所有实例的[[prototype]]:

Dog.prototype.woof = function() {
    alert(this.name + "makes: Woof!");
};

这是您所有共享方法都存在的类的中心对象。其中的.constructor property只是一个有用的(if rarely used)默认值。但是你会写

dog.woof();

,该方法可以通过继承方式获得

class

使用Dog.prototype语法定义方法将导致相同的List对象。