自定义类的未定义属性

时间:2017-03-24 20:33:42

标签: javascript class prototype

假设我有课程AB。类B有一个成员,它是类A的一个实例,我们称之为this.a

B方法内部,我尝试以A方式访问this.a.<methodName>的方法时,出现以下错误:

TypeError: this.a is undefined

这是我的代码:

function A (name) {
  this.name = name;
}
A.prototype.foo = function () {
  this.name = this.name.toUpperCase();
};
A.prototype.bar = function () {
  this.name = this.name.toLowerCase();
};

function B () {
  this.a = new A('Hello, World!');
}
B.prototype.methodsOfA = {
  foo: this.a.foo, // here is the problem
  bar: this.a.bar  //
};
B.prototype.executeMethodOfA = function (methodName) {
  this.methodsOfA[methodName]();
  //the following works if I delete B.prototype.methodsOfA:
  //if (methodName.toLowerCase() === 'foo') this.a.foo();      
  //else if (methodName.toLowerCase() === 'bar') this.a.bar(); // 
};

b = new B();

console.log(b.a.name);
b.executeMethodOfA('foo');
console.log(b.a.name);
b.executeMethodOfA('bar');
console.log(b.a.name);

相反,如果我使用以下定义:

B.prototype.methodsOfA = {
  foo: A.prototype.foo,
  bar: A.prototype.bar
};

我收到以下错误:

TypeError: this.name is undefined

(可能是因为this在这种情况下是bB对象没有name属性。)

那么,如何从this.a.<methodName>内部访问B

注意:这是一个较大问题的简化版本。我知道我问的问题可以通过类/原型继承解决,但理想情况下我希望B 继承A

2 个答案:

答案 0 :(得分:2)

我的狡猾感觉说有更好的方法可以解决这个问题,但现在这里有一些工作代码..

function A (name) {
    this.name = name;
}
A.prototype.foo = function () {
    this.name = this.name.toUpperCase();
};
A.prototype.bar = function () {
    this.name = this.name.toLowerCase();
};

function B () {
    this.a = new A('Hello, World!');
}
B.prototype.methodsOfA = function (methodName) {
  var methods = {
    foo: this.a.foo.bind(this.a),
    bar: this.a.bar.bind(this.a),
  }
  return methods[methodName];
};
B.prototype.executeMethodOfA = function (methodName) {
    this.methodsOfA(methodName)();
};
b = new B();

console.log(b.a.name);
b.executeMethodOfA('foo');
console.log(b.a.name);
b.executeMethodOfA('bar');
console.log(b.a.name);

你有两个问题:

    对象上下文中的
  • this未引用您正在考虑的this。它指的是窗口,因为methodsOfA作为普通对象,不会注入this。我将其更改为正确的方法,现在this是您想要的this
  • 您需要将A方法绑定到A本身的本地实例。这是因为在样式this中调用时,方法仅被赋予预期的a.foo()指针。将a.foo分配给另一个名称并在您执行时调用它将丢失this上下文。如上所示,您可以使用bind()强制使用正确的上下文。

答案 1 :(得分:1)

  1. 您引用this的方式是错误的。在您的情况下,this指的是全局上下文,即window
  2. 您只需使用Object.create(A.prototype)即可获得A的所有方法。
  3. 在执行this.methodsOfA[methodName]()时 - 它使用A的上下文调用B的方法。因此,name上下文中没有名为B的属性 - 它失败了。
  4. 你必须使用A的上下文调用A的方法,该方法存储在B的上下文中,即{} {}}

    this.a

  5. this.methodsOfA[methodName].call(this.a);