JavaScript继承-我做得对吗? 问题: 为什么第一种方法能正确地将物体识别为法拉利? (镀铬测试) 我在这两种方法中是否正确地进行了继承 我对第一个例子中有一些隐藏的“构造函数”属性的理解正确吗?如果是的话,它们在哪里?是什么把它们放在那里的?在第二个示例中,是否有我没有明确输入的隐藏构造函数属性 如果我已经正确地完成了继承,那么最后我应该使用两种方法中的哪一种来将对象标识为法拉利?还是我不在乎——毕竟“instanceof”仍然有效 背景:

JavaScript继承-我做得对吗? 问题: 为什么第一种方法能正确地将物体识别为法拉利? (镀铬测试) 我在这两种方法中是否正确地进行了继承 我对第一个例子中有一些隐藏的“构造函数”属性的理解正确吗?如果是的话,它们在哪里?是什么把它们放在那里的?在第二个示例中,是否有我没有明确输入的隐藏构造函数属性 如果我已经正确地完成了继承,那么最后我应该使用两种方法中的哪一种来将对象标识为法拉利?还是我不在乎——毕竟“instanceof”仍然有效 背景:,javascript,inheritance,prototype,Javascript,Inheritance,Prototype,使用JavaScript的“新”方法创建对象,效果很好: Vehicle.prototype = {}; // Not required I know function Vehicle() { } Car.prototype = new Vehicle(); function Car() { } Ferrari.prototype = new Car(); function Ferrari() { } var o = new Ferrari(); console.log(o); &g

使用JavaScript的“新”方法创建对象,效果很好:

Vehicle.prototype = {}; // Not required I know
function Vehicle() {

}

Car.prototype = new Vehicle();
function Car() {

}

Ferrari.prototype = new Car();
function Ferrari() {

}
var o = new Ferrari();
console.log(o);
> Ferrari
  > __proto__ : Car
    > __proto__ : Vehicle
      > __proto__ : Object <- The one that isn't required
        > __proto__ : Object <- Provided by JS
          ...
          hasOwnProperty: function hasOwnProperty() { [native code] }
          ...
Vehicle.prototype = {};
function Vehicle() {
  var vehicle = Object.create(Vehicle.prototype);
  return vehicle;
}

Car.prototype = Vehicle();
Car.prototype.constructor = Vehicle;
function Car() {
  var car = Object.create(Car.prototype);
  return car;
}

Ferrari.prototype = Car();
Ferrari.prototype.constructor = Car;

function Ferrari() {
  var ferrari = Object.create(Ferrari.prototype);
  //ferrari.constructor = Ferrari;  <- Lookey here - commented line
  return ferrari;
}

var o = new Ferrari();
console.log(o);
> **Car**
  > __proto__ : Car
    > constructor : function Car()
      __proto__ : Vehicle
      > constructor : function Vehicle()
        __proto__ : Object <- The one that isn't required
        > __proto__ : Object
          ...
          hasOwnProperty: function hasOwnProperty() { [native code] }
          ...
哪个输出:

Vehicle.prototype = {}; // Not required I know
function Vehicle() {

}

Car.prototype = new Vehicle();
function Car() {

}

Ferrari.prototype = new Car();
function Ferrari() {

}
var o = new Ferrari();
console.log(o);
> Ferrari
  > __proto__ : Car
    > __proto__ : Vehicle
      > __proto__ : Object <- The one that isn't required
        > __proto__ : Object <- Provided by JS
          ...
          hasOwnProperty: function hasOwnProperty() { [native code] }
          ...
Vehicle.prototype = {};
function Vehicle() {
  var vehicle = Object.create(Vehicle.prototype);
  return vehicle;
}

Car.prototype = Vehicle();
Car.prototype.constructor = Vehicle;
function Car() {
  var car = Object.create(Car.prototype);
  return car;
}

Ferrari.prototype = Car();
Ferrari.prototype.constructor = Car;

function Ferrari() {
  var ferrari = Object.create(Ferrari.prototype);
  //ferrari.constructor = Ferrari;  <- Lookey here - commented line
  return ferrari;
}

var o = new Ferrari();
console.log(o);
> **Car**
  > __proto__ : Car
    > constructor : function Car()
      __proto__ : Vehicle
      > constructor : function Vehicle()
        __proto__ : Object <- The one that isn't required
        > __proto__ : Object
          ...
          hasOwnProperty: function hasOwnProperty() { [native code] }
          ...
为什么第一种方法能正确地将物体识别为法拉利?

因为对象
o
的构造函数是函数
ferari

这两种方法的继承是否正确?

您在第一种方法中做得正确,但在第二种方法中做得不正确

如果我正确地完成了继承,那么最后应该使用两种方法中的哪一种来将对象标识为 法拉利或者我不应该在意——毕竟“instanceof”仍然有效?

为了一致性,您应该在函数体中的每个原型上设置构造函数属性,这样您就不必执行以下操作:

Car.prototype = Vehicle();
Car.prototype.constructor = Vehicle;

Aeroplane.prototype = Vehicle();
Aeroplane.prototype.constructor = Vehicle;

...
相反,您应该使用:

function Vehicle() {
    var vehicle = Object.create(Vehicle.prototype);
    vehicle.constructor = Vehicle;
    return vehicle;
}

Car.prototype = Vehicle();
function Car() {
    var car = Object.create(Car.prototype);
    car.constructor = Car;
    return car;
}

Ferrari.prototype = Car();
function Ferrari() {
    var ferrari = Object.create(Ferrari.prototype);
    ferrari.constructor = Ferrari;
    return ferrari;
}

var o = new Ferrari();
console.log(o);
这将正确地生成与第一个示例中的结构相似的结构

为什么第一种方法能正确地将物体识别为法拉利?(镀铬测试)

我对第一个例子中有一些隐藏的“构造函数”属性的理解正确吗?如果是的话,它们在哪里?是什么把它们放在那里的?在第二个示例中,是否有我没有明确输入的隐藏构造函数属性

是的,如果你分配给函数的
prototype
属性,或者以某种方式创建一个新实例,Chrome似乎会设置一个隐藏的“构造函数”属性。我还没弄清楚

他们在哪里?可能是一些只有
console.log
有权访问的内部属性。然而,您似乎能够使用显式的“构造函数”属性覆盖它们,至少对于
\uuuu proto\uuu
对象的显示是如此

我猜这是由Chrome完成的,因为很多人在覆盖原型对象时忘记了设置构造函数属性(因为),不过也请参见。Chrome开发者想要制作一个漂亮的
log
函数来指示对象的类型,因此他们需要解决人们的懒惰问题

我在这两种方法中是否正确地进行了继承

代码中的继承没有问题。新创建的
Car
实例具有aspired prototype链,使用这两种方法

不过,也有一些陷阱。不要使用
new
关键字来创建原型对象实例。您不需要应用构造函数的完整实例。只需使用
Car.prototype=Object.create(Vehicle.prototype)
;另请参见上的答案

另外,您没有设置“构造函数”属性,或者设置错误。在prototype对象上定义的该属性由对相应构造函数的
new
调用创建的所有对象继承,它应该为这些对象提供对该函数的引用。对于任何创建的函数,默认情况下都会执行此操作,请参阅

如果重新指定给
fn.prototype
,则覆盖该行为(无论它是对象文本、新的
构造还是
对象.create
调用)。实际上,“constructor”属性是-在第一个示例中
o.constructor
Object
,继承自空对象文本。因此,在您的情况下,我们需要在分配后重置它:

Vehicle.prototype.constructor = Vehicle;
Car.prototype.constructor = Car;
Ferrari.prototype.constructor = Ferrari;

// or, we combine it with the Object.create call:
Car.prototype = Object.create(Vehicle.prototype, {
    constructor: {value:Car, configurable:true, writable:true}
});
请注意,无需在构造函数中显式设置它(如第二个示例中所示),从而在对象上创建一个额外属性。这就是继承的目的

或者我们根本不关心“构造函数”属性:

在最后的两种方法中,我应该使用哪一种来让物体被识别为法拉利?还是我不在乎——毕竟“instanceof”仍然有效


要将一个物体识别为法拉利,请始终使用
instanceof
。“构造函数”属性不可靠。它可能已经忘记设置,或者它不是您在比较中所期望的:像
someObj.constructor===Car
这样的“类型检查”对于Ferraris或任何其他正确设置了构造函数属性的“子类”都不起作用。它与
instanceof

有关,您正在将
Ferrari.prototype.constructor
设置为
Car
。但是重置
构造函数
的要点是
法拉利
的实例将其构造函数设置回
法拉利
,而不是
汽车
(当覆盖
原型
时会自动发生)。@pimvdb我没有这样做的原因是因为在第二种方法中它会出现(在对象图中)法拉利的原型是法拉利,而事实上它是“汽车的实例”.有趣的是,当你对第一个方法做同样的事情时,它根本不会改变图形!-这种不一致性向我暗示这不是正确的继承方式?@Lee这种继承方式很好,你只需将每个子类型的构造函数设置为父类。你可以省去一点麻烦,然后再做在函数体中,或者您可以在每次为子类型创建原型时重置构造函数。请参见我的答案。
o
的原型是
Ferrari
,而
Ferrari
的原型不是
Ferrari