JavaScript:将对象方法的上下文绑定到父级

时间:2019-09-23 16:12:22

标签: javascript object methods binding this

此示例按预期工作:

class A {
  constructor(name) {
     this.name = name
  }
}

A.prototype.someMethod1 = function() { console.log("1: " + this.name) }
A.prototype.someMethod2 = function() { console.log("2: " + this.name) }

let a = new A("John")
a.someMethod1()
a.someMethod2()

有时候,我们需要按其含义将方法分组为子对象,以便像这样调用它:a.some.method1(),a.some.method2()。让我们尝试写:

class A {
  constructor(name) {
     this.name = name
  }
}

A.prototype.some = {
  method1: function() { console.log("1: " + this.name) },
  method2: function() { console.log("2: " + this.name) }
}

现在我们可以调用a.some.method1()和a.some.method2()了,但是其中的“ this”指向“ a.some”,而不是所需的“ a”。因此,这些方法中的“ this.name”现在将变为“ undefined”。

那么我可以将方法的上下文绑定到主对象吗?

目前,我只知道一种方法。在构造函数中是这样的:

class A {
  constructor(name) {
    this._name = name

    // bind context to this
    Object.keys(this.name).forEach(n => {
      this.name[n] = this.name[n].bind(this)
    })
  }
}

但是还有更优雅的方法吗?

注意:应在声明时指定。不能接受对诸如a.some.method1()。call(a)之类的方法调用的修改。

3 个答案:

答案 0 :(得分:0)

这可能根本不是您想要的,但是您可以考虑做这样的事情:

class A {
    constructor(name) {
        this.name = name;
        this.some = new Some(this);        
    }
}

class Some {
    constructor(a) {
        this.a = a;
    }

    method1() { console.log("1: " + this.a.name) }
    method2() { console.log("2: " + this.a.name) }
}

var x = new A('x name');
x.some.method1();
x.some.method2();

答案 1 :(得分:0)

是的,您可以定义类的实例,然后通过将其绑定到a

来在原型上添加方法

class A {
  constructor(name) {
     this.name = name
  }
}

let a = new A("Hello")

A.prototype.some = {
  method1: function() { console.log("1: " + this.name) }.bind(a),
  method2: function() { console.log("2: " + this.name) }.bind(a)
}

a.some.method1()

答案 2 :(得分:0)

您可以使some的功能返回一个对象,您可以在其中指定要具有的方法,然后可以从该对象中调用这些方法。

class A {
  constructor(name) {
    this.name = name
  }
}


A.prototype.someMethod1 = function() {
  console.log("1: " + this.name)
}
A.prototype.someMethod2 = function() {
  console.log("2: " + this.name)
}

A.prototype.some = function() {
  return {
    someMethod1: this.someMethod1.bind(this),
    someMethod2: this.someMethod2.bind(this)
  }
}

let a = new A("John")
a.someMethod1()
a.someMethod2()
a.some().someMethod1()
a.some().someMethod2()

可以使用没有原型的类方法来实现相同的逻辑。您也可以省略带有箭头功能的bind作为类属性,但是在这种情况下,您应该注意支持。

class A {
  constructor(name) {
    this.name = name
  }

  some1 = () => `1. ${this.name}`
  some2 = () => `2. ${this.name}`

  some = () => {
    return {
      some1: this.some1,
      some2: this.some2
    }
  }
}

let a = new A("John")
console.log(a.some1())
console.log(a.some2())
console.log(a.some().some1())
console.log(a.some().some2())

您也可以对some使用getter,这样就可以像属性一样调用它,而不是方法。

class A {
  constructor(name) {
    this.name = name
  }

  some1 = () => `1. ${this.name}`
  some2 = () => `2. ${this.name}`

  get some() {
    return {
      some1: this.some1,
      some2: this.some2
    }
  }
}

let a = new A("John")
console.log(a.some1())
console.log(a.some2())
console.log(a.some.some1())
console.log(a.some.some2())