Обычно применять контекст к псевдонимам методов - PullRequest
2 голосов
/ 18 июня 2019

Я столкнулся с проблемой, которую не могу решить. Я не знаю, является ли это недостатком знаний, или фактом, что это даже невозможно в Javascript, но я надеюсь узнать это.

Я пытаюсь выполнить список псевдонимов функций в объекте. При выполнении этих функций я хотел бы использовать их так, как если бы они выполнялись прямо из самого экземпляра, поэтому я могу использовать другие методы и переменные экземпляра внутри этого вызываемого метода. Чтобы сделать мое объяснение немного более понятным, вот пример:

class Bar {
  constructor() {
    this.name = "Bar";
  }
    
  someMethod() {
    console.log(this.name) // should log Bar
  }
}

class Foo {
  constructor() {
    this.name = "Foo";
  }

  someOtherMethod() {
    console.log(this.name) // should log Foo
  }
}

const bar = new Bar();
const foo = new Foo();


const methodList = {
  foo: bar.someMethod,
  baz: foo.someOtherMethod,
}

for(let prop in methodList) {
  methodList[prop](); // logs 2x undefined
}

for(let prop in methodList) {
  methodList[prop].apply(foo); //logs 2x Foo
}

Как видно из приведенного выше примера, this.name - это переменная в экземпляре класса. При выполнении второго цикла, контекст применяется и регистрируется правильно, как и ожидалось. Мне бы хотелось, чтобы этот контекст применялся автоматически, поскольку объект псевдонима функции выполняется в другом файле, не зная о foo или bar и просто получая список.

Есть ли способ достичь этого?

Ответы [ 2 ]

2 голосов
/ 18 июня 2019

Вы можете обернуть ваши foo и bar методы в свои собственные функции.В этих методах вы можете затем вызвать метод объекта someMethod() / someOtherMethod() для объекта следующим образом:

const methodList = {
  foo: (...args) => bar.someMethod(...args),
  baz: (...args) => foo.someOtherMethod(...args),
}

В данный момент ваш первый цикл не работает, потому что ваш this не работаетобратитесь к фактическому контексту объекта, поскольку это не то, что используется для вызова метода.Вместо этого он относится к вашему methodList

См. Пример ниже:

class Bar {
  constructor() {
    this.name = "Bar";
  }
    
  someMethod() {
    console.log(this.name) // should log Bar
  }
}

class Foo {
  constructor() {
    this.name = "Foo";
  }

  someOtherMethod() {
    console.log(this.name) // should log Foo
  }
}

const bar = new Bar();
const foo = new Foo();


const methodList = {
  foo: (...args) => bar.someMethod(...args),
  baz: (...args) => foo.someOtherMethod(...args),
}

for(let prop in methodList) {
  methodList[prop](); // correct logs
}
1 голос
/ 18 июня 2019

Это происходит потому, что контекстный this при вызове methodList[prop] равен methodList, следовательно this в someMethod и someOtherMethod на самом деле:

{
  foo: bar.someMethod,
  baz: foo.someOtherMethod,
}

Чтобы решить проблему,вы можете обернуть методы в анонимную функцию, возвращающую вызванный метод, как показано ниже:

class Bar {
  constructor() {
    this.name = "Bar";
  }
    
  someMethod(a,b,c) {
    console.log(a,b,c,this.name) // should log Bar
  }
}

class Foo {
  constructor() {
    this.name = "Foo";
  }

  someOtherMethod(a,b,c) {
    console.log(a,b,c,this.name) // should log Foo
  }
}

const bar = new Bar();
const foo = new Foo();


const methodList = {
  foo: (...args) => bar.someMethod(...args), // <-- anonymous function that, once invoked, returns `bar.someMethod()`, hence the contextual `this` of someMethod will be `bar`.
  baz: function() {  // <-- same as above, just written without the lambda notation.
     return foo.someOtherMethod(...arguments);
  }//^
}//  | <-- that evaluation is actually calling the above code block.
//   |-------------------------------------|
for(let prop in methodList) {//            |
  methodList[prop](1,4,'hello'); // <------|
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...