JavaScript构造函数方法返回的结果与预期的有所不同 [英] Javascript constructor method returning something different than expected
问题描述
函数Plant(){this.country =墨西哥"this.isOrganic = true;}函数Fruit(fName,fColor){this.name = fName;this.color = fColor;}Fruit.prototype = new Plant();var abanana =新水果(香蕉",黄色")console.log(abanana.constructor)
所以在我的代码中,我试图尝试原型继承.每次我创建一个Fruit的新实例(var aFruit = new Fruit())时,都会为该新实例的原型分配来自Fruit构造函数的原型,即Fruit.prototype.
那为什么是abanana.constructor不是
[功能:水果]
但是
[功能:植物]?
我认为这就是构造方法的作用:
此外,所有从另一个对象继承的对象也都继承一个构造函数属性.而且,该构造函数属性只是一个保存或指向对象构造函数的属性(与任何变量一样).
该代码存在两个问题:
-
使用
new Plant()
创建Fruit.prototype
是一种可悲的反模式;而是使用Object.create
并从Fruit
中调用Plant
.特定代码无关紧要,但是如果您想从Fruit
派生某些东西,或者是否想将country
用作植物
. -
如果要使其指向
Fruit
,则需要在Fruit.prototype
上设置constructor
.
所以:
函数Plant(){this.country =墨西哥"this.isOrganic = true;}函数Fruit(fName,fColor){Plant.call(this);//**this.name = fName;this.color = fColor;}Fruit.prototype = Object.create(Plant.prototype);//**Fruit.prototype.constructor =水果;//**
当然,从ES2015开始,我们具有 class
语法,您现在可以将其与编译器一起使用(或者如果您仅需要支持当前版本的Chrome和Firefox):
class Plant {Constructor(){this.country =墨西哥";this.isOrganic = true;}水果延伸类植物{构造函数(fName,fColor){极好的();this.name = fName;this.color = fColor;}}
我认为这就是构造方法的作用:
此外,所有从另一个对象继承的对象也都继承一个构造函数属性.而且,该构造函数属性只是一个保存或指向对象构造函数的属性(与任何变量一样).
constructor
不是方法,它是一个属性,它引用 prototype
对象所关联的函数.JavaScript本身根本不使用 constructor
,但是确实为具有 prototype
属性的所有函数定义了该函数,当该函数首次创建时, prototype
属性指向,将具有指向该函数的 constructor
属性.但是,由于您将 prototype
的值替换为对另一个对象的引用,因此必须更新 constructor
属性,使其指向再次更正功能(如果您想透彻一点,那是最好的方法,即使 JavaScript 不使用它,也不意味着库不使用它)./p>
在非常老的浏览器上,您可能必须填充 Object.create
.不能完全填充垫片,但对于上面的垫片就足够了:
if(!Object.create){Object.create = function(p,props){if(typeof props!=="undefined"){抛出新的错误(无法填充Object.create的第二个参数.");}函数ctor(){}ctor.prototype = p;返回新的ctor;};}
function Plant() {
this.country = "Mexico"
this.isOrganic = true;
}
function Fruit(fName, fColor) {
this.name = fName;
this.color = fColor;
}
Fruit.prototype = new Plant();
var abanana = new Fruit("Banana", "Yellow")
console.log(abanana.constructor)
So in my code, I was trying to play around with prototype inheritance. Each time I created a new instance of Fruit (var aFruit = new Fruit ()), the new instance’s prototype is assigned the prototype from the Fruit constructor, which is Fruit.prototype.
So why is abanana.constructor not
[function: Fruit]
but
[function: Plant]?
I thought this was what the constructor method does:
Moreover, all objects that inherit from another object also inherit a constructor property. And this constructor property is simply a property (like any variable) that holds or points to the constructor of the object.
Two problems with that code:
Using
new Plant()
to create theFruit.prototype
is a sadly-common anti-pattern; instead, useObject.create
and callPlant
from withinFruit
. It doesn't matter a lot in your specific code, but it would matter if you wanted to derive something fromFruit
, or if you wanted to makecountry
an argument toPlant
.You need to set
constructor
onFruit.prototype
if you want it to point toFruit
.
So:
function Plant() {
this.country = "Mexico"
this.isOrganic = true;
}
function Fruit(fName, fColor) {
Plant.call(this); // **
this.name = fName;
this.color = fColor;
}
Fruit.prototype = Object.create(Plant.prototype); // **
Fruit.prototype.constructor = Fruit; // **
Of course, as of ES2015, we have class
syntax, which you can use today with a transpiler (or if you only need to support current versions of Chrome and Firefox):
class Plant {
constructor() {
this.country = "Mexico";
this.isOrganic = true;
}
class Fruit extends Plant {
constructor(fName, fColor) {
super();
this.name = fName;
this.color = fColor;
}
}
I thought this was what the constructor method does:
Moreover, all objects that inherit from another object also inherit a constructor property. And this constructor property is simply a property (like any variable) that holds or points to the constructor of the object.
constructor
isn't a method, it's a property that refers to the function that the prototype
object is related to. JavaScript itself doesn't use constructor
for anything at all, but does define that for all functions that have a prototype
property, when the function is first created, the object that prototype
property points to will have a constructor
property pointing back at the function. But since you replace the value of prototype
with a reference to a different object, you have to update the constructor
property so it points back to the correct function again (if you want to be thorough, which is for the best — even though JavaScript doesn't use it, it doesn't mean that libraries don't use it).
On really old browsers, you may have to shim Object.create
. It can't be completely shimmed, but it can be sufficient for the above:
if (!Object.create) {
Object.create = function(p, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function ctor() { }
ctor.prototype = p;
return new ctor;
};
}
这篇关于JavaScript构造函数方法返回的结果与预期的有所不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!