【问题标题】:Prototypal Inheritance Not Working When Instances Are Stored In An Array当实例存储在数组中时,原型继承不起作用
【发布时间】:2014-07-02 15:36:44
【问题描述】:

我在上一个项目中偶然发现了一个非常奇怪的问题。我已经实现了如下继承:

    function Parent(){}
    Parent.prototype.hi = function(){
        alert("Parent: hi!");
    };
    Parent.prototype.bye = function(){
        alert("Parent: bye!");
    };

    function Child(){
        this.hi = function(){
            alert("Child: hi!");
        };
    }
    Child.prototype = new Parent();

这样我可以在 Child 构造函数中只覆盖我需要的函数,其余的将从父级继承。

这工作正常。这是测试:

var test = function(){
    var p = new Parent();
    p.hi();
    p.bye();
    var c = new Child();
    c.hi();
    c.bye();
};
test();

并且输出是预期的:

Parent: hi!
Parent: bye!
Child: hi!
Parent: bye!

但是,当我将实例存储在数组中时,子实例中的 bye 函数不会被继承,并且会引发错误。测试代码:

var anArray = [
    new Parent(),
    new Child()
];

var test2 = function(){
    for(var i = 0, m = null; i < anArray.length; i++){
        m = anArray[i];
        m.hi();
        m.bye();  //WTF not working for the child?
    }
};
test2();

输出:

Parent: hi!
Parent: bye!
Child: hi!
TypeError: m.bye is not a function

JSFiddle here

我花了一个多小时盯着这段代码并调试它,我看不出问题出在哪里。原始代码要复杂得多,功能也更多。我认为数组有问题,但我不想放弃它,因为我认为表驱动方法是我要实现的最佳方法。

【问题讨论】:

  • 在您的 Child() 函数中,您只定义了 this.hi,而不是 this.bye。这就是为什么 bye() 会以未定义的形式返回。
  • @athms:不,不是这个原因。
  • 为变量或属性赋值从不更改另一个变量或属性的值。因此,为Child.prototpye 分配新值不能更改现有 实例的原型。
  • @FelixKling 是的,“现有”是关键词。我没有展示它,但整个代码都在一个模块中。我碰巧忘记了很多模块是执行的常规代码,并且倾向于将其视为一堆函数定义。

标签: javascript arrays inheritance prototypal-inheritance


【解决方案1】:

具有new Child 实例的数组是在您让Child 从Parent 继承之前创建的,并且仍然具有旧原型(没有任何方法)。相比之下,c = new Child 是在test() 函数中在Child.prototype = … 赋值之后执行的。

将数组声明/初始化移动到test2 函数中。或者干脆将所有课程内容移到顶部。

【讨论】:

  • 天哪。我本可以盯着那段代码看一整天。当然,提升仅适用于函数定义,但继承是常规代码和顺序问题。我和我愚蠢的 Java 思维方式。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多