我们知道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");
但是,这并不能证明这种设置非常合理(因为函数/类是唯一对自身具有这种循环引用的对象),这是不合理的。这个决定背后还有其他原因吗?
答案 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
可能会将init
和mydog = 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
对象。