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