JavaScript: привязка контекста методов объекта к родителю - PullRequest
1 голос
/ 23 сентября 2019

Этот пример работает, как и ожидалось:

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» ине "а", как хотелось бы.Итак, «this.name» внутри этих методов теперь будет «неопределенным».

Так можно ли связать контекст методов с основным объектом?

В настоящее время я знаю только один способ сделать это.Примерно так в конструкторе:

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 голосов
/ 23 сентября 2019

Да, возможно, вы можете определить экземпляр класса и затем добавить метод к прототипу, связав его с 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()
0 голосов
/ 23 сентября 2019

Вы можете сделать 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()

Та же логика может быть реализована с помощью методов класса без прототипа.Вы также можете опустить связывание с функциями стрелок в качестве свойств класса, но вам следует позаботиться о поддержке в этом случае.

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, чтобы вместо метода вызывать его как свойство.

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())
0 голосов
/ 23 сентября 2019

Это может быть совсем не то, что вы ищете, но вы можете подумать о том, чтобы сделать что-то вроде этого:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...