【问题标题】:javascript class members are undefined in child classesjavascript 类成员在子类中未定义
【发布时间】:2013-03-28 17:41:09
【问题描述】:

这是我的代码,B类继承A类:

function A() {
    this.msg = 'meuahah';
    A.prototype.foo = function() {
        alert(this.msg);
    }
}

function B() {
    A.call(this);
    B.prototype.bar = function() {
        A.prototype.foo();
    }
}

a = new A();
a.foo(); // alerts 'meuahah'
b = new B();
b.bar(); // alerts 'undefined'

为什么 b.bar() 不显示“meuahah”?

【问题讨论】:

  • 哇...为什么我们每次调用构造函数时都要为原型设置东西?
  • 当你尝试 alert(a.msg); 时它会起作用;

标签: javascript class inheritance


【解决方案1】:

您的原型继承不太正确。这可能是您更想做的事情:

function A() {
    this.msg = 'meuahah';
}

A.prototype.foo = function() {
    alert(this.msg);
}

function B() {
    A.call(this);
}

B.prototype = new A();
B.prototype.bar = function() {
    this.foo();
}

a = new A();
a.foo(); 
b = new B();
b.bar();

您可以像这样在B 中覆盖foo

B.prototype.foo = function() {
    // Call the original foo method
    A.prototype.foo.apply(this, arguments);
}

【讨论】:

  • B.prototype = A.prototype。这有点危险......在设置B.prototype.bar 之后,现在还有一个A.prototype.bar,这可能不是预期的行为。
  • 好点,我想我暂时忘记了这一点;)现在应该修复了。
  • 这肯定更好,但现在的问题是您将拥有一个B.prototype.msg(以及在A() 构造函数中设置的任何其他属性。最好从@987654330 复制每个属性@到B.prototype
  • 为了扩展,A() 构造函数中的任何行为都会在创建 B() 构造函数的原型链时被调用,因此在实际创建任何实例之前运行构造函数有点“奇怪”。
  • 可能想要使用 Object.create 而不是这些选项中的任何一个。看我的回答。这样可以保留原型,而无需创建实例或将 A 的本地属性放在 B 的原型链上(在这种情况下无害,但如果您没有全部复制它们可能会有害)
【解决方案2】:

因为this 在这种情况下绑定到全局对象。

你正在调用这个函数

function() {
        alert(this.msg);
    }

当它没有绑定到一个对象时。所以this 将引用全局对象(在浏览器中为window),因为它没有msg 属性,它会提醒未定义。

当您调用a = new A() 时,您会创建一个新对象,将 msg 作为属性添加,并在其原型链上设置 foo()。因此,当您调用 a.foo() 时,foo 绑定到 a 并且 this 指的是 a

一般来说,您可能想要看起来更像这样的东西。

function A() {
    this.msg = 'meuahah';
}

A.prototype.foo = function() {
    alert(this.msg);
}

function B() {
    A.call(this);
}

B.prototype = Object.create(A.prototype);

B.prototype.bar = function() {
    this.foo();
}

您可以从this question 阅读更多关于this 如何在javascript 中工作的信息

【讨论】:

    【解决方案3】:

    之所以b.bar显示undefined是因为foo方法的thisprototype,而prototype没有msg属性。

    你基本上错过了重点,继承。所以,这里重新审视了代码:

    function A() {
      this.msg = 'meuahah';
    }
    
    A.prototype.foo = function() {
      alert(this.msg);
    }
    
    function B() {
        A.call(this);
    }
    
    // Set the inheritance! Or better, the prototype's chain,
    // so that any instance of B will have methods of A too
    B.prototype = Object.create(A.prototype);
    
    B.prototype.bar = function() {
      // Because the inheritance, now B has the A's `foo` method too
      this.foo();
    }
    
    // But... We can also override it.
    B.prototype.foo = function() {
      // do something
      alert("override");
      // then call the original one
      A.prototype.foo.call(this);
    }
    

    希望对对象和构造函数有更好的了解会有所帮助。我也建议在Object.create 上进行调查,这真的很有帮助;以及一般的 ES5 方法。

    阅读Working with Objects也是一个好的开始,虽然有点老了。

    【讨论】:

      【解决方案4】:

      你只是被称为 A.prototype.foo 函数,所以 msg 不存在。这是当您在console.log(this)A.prototype.foo 时控制台的输出

      A {msg: "meuahah", foo: function}
      A {foo: function}
      

      第二个是当您从B 内部调用它时,您可以看到msg 不存在。

      【讨论】:

        猜你喜欢
        • 2018-10-06
        • 1970-01-01
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 2014-02-17
        相关资源
        最近更新 更多