【问题标题】:Adding to the prototype of an instance of another prototype: JavaScript添加到另一个原型实例的原型:JavaScript
【发布时间】:2014-09-12 23:40:54
【问题描述】:

我的问题很简单:

如何设置继承自另一个类原型的类的原型?

我的代码在我尝试调用 Pierre.mySkill() 之前一直有效,此时控制台显示该函数未定义。

理论上,我这样做的原因是能够创建 Pirault 的实例以及 Person 的实例,并且能够添加到 Pirault 的原型中而无需添加到 Person 的原型中。

function Person (name, age){
    this.name = name;
    this.age = age;
}

Person.prototype.info = function(){
    console.log('I am '+this.name+' and I am '+this.age+' years old.');
};

function Pirault (){
    this.skill = arguments[2];

    Person.apply(this, arguments);
}

Pirault.prototype.mySkill = function(){
    console.log('My skill is '+this.skill);
}

Pirault.prototype = Object.create(Person.prototype);
Pirault.prototype.constructor = Pirault;

var Pierre = new Pirault('Pierre', 30, 'Programming');

【问题讨论】:

  • 所以skill"Pierre"
  • 哎呀!感谢您发现它,我打算在发布之前对其进行更新。
  • 这是您问题的简化版本:var foo = {}; foo.name = 'foo'; foo = {}; console.log(foo.name);。为什么foo.name 返回undefined 应该很明显了。

标签: javascript prototype


【解决方案1】:

组织您的代码,以便在创建原型对象之后定义所有原型方法。例如:

Pirault.prototype = Object.create(Person.prototype);
Pirault.prototype.constructor = Pirault;

Pirault.prototype.mySkill = function(){
    console.log('My skill is '+this.skill);
}

Demo。就目前而言,您在原型上正确定义了一个方法 - 但是当一个对象(由Object.create 创建)变成一个新的Pirault.prototype 时,它就会丢失。

【讨论】:

    【解决方案2】:

    作为一种替代方法,您不需要构造函数来执行此操作。在现代浏览器中你只需要对象和Object.create:

    var Person = {
      info: function() {
        console.log('I am '+ this.name +'and I am '+ this.age +' years old.')
      }
    }
    
    var Pirault = Object.create(Person)
    Pirault.mySkill = function() {
      console.log('My skill is '+ this.skill)
    }
    
    var pierre = Object.create(Pirault)
    pierre.name = 'Pierre'
    pierre.age = 30
    pierre.skill = 'Programming'
    
    pierre.mySkill() //=> My skill is Programming
    
    console.log(Pirault.isPrototypeOf(pierre)) //=> true
    console.log(Person.isPrototypeOf(pierre)) //=> true
    

    【讨论】:

    • 如果所有基础对象都是“界面”(咳咳)——即只包含要处理的方法,这种方法效果很好。否则,我认为也必须实例化它们,这可能会变得一团糟。不过,不错的方法,我+1。 )
    • 万分感谢。如果我能不止一次地给你投票,我会的。你无法想象我读了多少关于类/构造函数/基于新方法的文章,我总觉得有些东西“不太对劲”……
    • 实际上,组织对象层次结构的方法不止一种——例如,mixins (Base.call(this))。
    • @papiro 这真是一个长篇大论,我觉得我无法在 SO 答案中解释它(更不用说在评论中了)。但是请注意区别:在您的情况下,您没有在 pierre 上分配属性 - 您只是使用 Person.apply(this, arguments) 行将其传递给基类的构造函数类。使用此答案中给出的方法,情况并非如此-在 Object 的实例上设置属性是客户端的责任,即创建该实例的客户端。
    • @papiro 我可以推荐你阅读 Addy Osmani 的 this wonderful book 吗?在我看来,它很好地解释了 JS 中不同创建模式的差异和潜在用例。 )
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多