gpt4 book ai didi

javascript - 对 JavaScript 原型(prototype)继承感到困惑

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:49:04 24 4
gpt4 key购买 nike

在《JavaScript 权威指南 5 版》这本书的 9.2 Prototypes and Inheritance 一节中,我找到了以下的话:

In the previous section, I showed that the new operator creates a new, empty object and then invokes a constructor function as a method of that object. This is not the complete story, however. After creating the empty object, new sets the prototype of that object. The prototype of an object is the value of the prototype property of its constructor function. All functions have a prototype property that is automatically created and initialized when the function is defined. The initial value of the prototype property is an object with a single property. This property is named constructor and refers back to the constructor function with which the prototype is associated. (You may recall the constructor property from Chapter 7 ; this is why every object has a constructor property.) Any properties you add to this prototype object will appear to be properties of objects initialized by the constructor.

现在,如果这是真的,那么原型(prototype)继承怎么可能存在呢?我的意思是,假设构造函数的原型(prototype)对象最初有一个构造函数属性。因为原型(prototype)对象本身就是一个对象,所以我们经常使用prototype_object.constructor来确定它的构造函数。 .但是现在 prototype_object已经有一个 constructor属性本身,它指向与原型(prototype)关联的构造函数。在这种情况下,继承怎么可能存在?

最佳答案

.constructor 属性老实说并不重要,与从 JavaScript 中的其他对象继承几乎没有关系。它只是对象构造函数的一个方便句柄。

例如,如果你有一个实例,你想创建那个实例的另一个实例,但你没有它的构造函数的直接句柄,你可以这样做:

const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]

const car2 = new myCar.constructor();
console.log(car2.constructor); // [Function: Racecar]

.constructor 属性和对象的类不是同义词,理解这一点很重要。正如您可能已经猜到的那样,.constructor 属性是动态的,就像 JavaScript 中的大多数其他内容一样,因此它不应该用于类型检查等任何事情。

同样重要的是要了解 .constructor 属性并不意味着某些东西是其他东西的子类。事实上,在 JavaScript 中没有可靠的方法来确定某个东西是否是其他东西的子类。因为它是一种动态语言,并且因为有很多方法可以从其他对象继承属性(包括在实例化后从其他对象复制属性),类型安全的子类在 JavaScript 中并不像在其他语言中那样存在。

了解某物是否兼容类型的最佳方法是对属性进行功能测试。换句话说,鸭型。

instanceof 运算符忽略 .constructor 属性。相反,它会检查构造函数的 .prototype 是否存在于对象的原型(prototype)链中(通过身份检查)。

对于手动构造函数,继承可能会混淆 .constructor 属性连接(使其引用错误的构造函数)。您可以通过手动连接连接来修复它。例如,在 ES5 中这样做的规范方式是这样的:

function Car () {}

console.log(Car.prototype.constructor); // Car

function Racecar () {}

Racecar.prototype = Object.create(Car.prototype);
// To preserve the same relationship we have with the Car
// constructor, we'll need to reassign the .prototype.constructor:
Racecar.prototype.constructor = Racecar;

var myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]

ES6 类会自动为您完成此操作:

// ES6
class Car {}
class Racecar extends Car {}

const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]

也就是说,我不是构造函数或 ES6 类的忠实粉丝,而且我通常很少使用 .constructor 属性。为什么?因为工厂函数要灵活得多,功能也要强大得多,而且它们没有构造函数和类继承相关的缺陷。参见 "Factory Functions vs Constructor Functions vs Classes" .

关于javascript - 对 JavaScript 原型(prototype)继承感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2182685/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com