JavaScript构造函数方法返回的结果与预期的有所不同 [英] Javascript constructor method returning something different than expected

查看:44
本文介绍了JavaScript构造函数方法返回的结果与预期的有所不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 函数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不是

  [功能:水果] 

但是

  [功能:植物]? 

我认为这就是构造方法的作用:

此外,所有从另一个对象继承的对象也都继承一个构造函数属性.而且,该构造函数属性只是一个保存或指向对象构造函数的属性(与任何变量一样).

解决方案

该代码存在两个问题:

  1. 使用 new Plant()创建 Fruit.prototype 是一种可悲的反模式;而是使用 Object.create 并从 Fruit 中调用 Plant .特定代码无关紧要,但是如果您想从 Fruit 派生某些东西,或者是否想将 country 用作植物.

  2. 如果要使其指向 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:

  1. Using new Plant() to create the Fruit.prototype is a sadly-common anti-pattern; instead, use Object.create and call Plant from within Fruit. It doesn't matter a lot in your specific code, but it would matter if you wanted to derive something from Fruit, or if you wanted to make country an argument to Plant.

  2. You need to set constructor on Fruit.prototype if you want it to point to Fruit.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆