Как передать функцию, которая является свойством другого объекта, в функцию и вызвать ее в javascript? - PullRequest
0 голосов
/ 02 июля 2018

Если у меня есть объект в Javascript и одним из его свойств является функция:

function cow() {

    this.timesMooed = 0;

    this.sayMoo = function () {
        this.timesMooed++;
        return "moo";
    };
}

Скажем, у меня также есть другая функция, которая принимает некоторую функцию в качестве аргумента, вызывает ее и записывает результат:

var actionResults = [];
function doAction(action) {
    actionResults.push(action());
}

Теперь давайте применим это на практике и посмотрим, что произойдет:

var jerry = new cow();
doAction(jerry.sayMoo);
console.log(actionResults);
// Outputs ["moo"] -this is correct
console.log(jerry.timesMooed);
// Outputs 0 -uh oh

Как я могу передать функцию, чтобы Jerry выполнял функцию?

Ответы [ 4 ]

0 голосов
/ 02 июля 2018

попробуйте создать конструктор

       class cow {   
            constructor(){
               this.timesMooed = '';
            }      
            sayMoo() {
               this.timesMooed+=1;
               return "moo";
            }
        }
            
            var actionResults = [];
            function doAction(action) {
            actionResults.push(action);
            }
            
            var jerry = new cow();
            doAction(jerry.sayMoo());
            console.log(actionResults);
            console.log(jerry.timesMooed);
0 голосов
/ 02 июля 2018

Проблема в том, что в методе используется ключевое слово this, и мы вызываем этот метод из объекта-получателя, и this не привязан к объекту, который, как мы ожидаем, будет привязан, то есть к Джерри в этом случае.

Обратите внимание, что значение this в методах и функциях должно быть задано явно, когда нам нужен конкретный объект, связанный со значением this функции.

Решение

Решение простое в использовании правильного контекста

т.е. мы хотим, чтобы this ссылался на jerry, поэтому при вызове метода doAction с методом sayMoo объекта jerry используйте вызов функции bind и передайте jerry в качестве этого аргумента

doAction(jerry.sayMoo.bind(jerry));
0 голосов
/ 02 июля 2018

Как говорит @Mark_M, лучше использовать функцию стрелки, но эта функция заставляет вас использовать ES6 вместо ES5, потому что связанная функция введена в ES5. Другой способ - использовать преимущества переменной области, например:

        function cow() {
            this.timesMooed = 0;
            var that = this;
            this.sayMoo = function (){
                that.timesMooed++;
                return "moo";
            }
        }

        ...
0 голосов
/ 02 июля 2018

Когда вы передаете ссылку на функцию doAction и затем вызываете ее с помощью action(), контекст вызова изменяется, и именно это определяет значение this. Вам нужно использовать bind, чтобы значение this было зафиксировано на jerry:

function cow() {
    this.timesMooed = 0;
    this.sayMoo = function () {
        this.timesMooed++;
        return "moo";
  }
}

var actionResults = [];
function doAction(action) {
    actionResults.push(action());
}

var jerry = new cow();
// use bind, which makes a function with `this` set properly
doAction(jerry.sayMoo.bind(jerry));

console.log(actionResults);
console.log(jerry.timesMooed);

В качестве альтернативы вы можете использовать функции стрелок =>, которые связывают this лексически:

function cow() {
    this.timesMooed = 0;
    // use arrow function here instead
    this.sayMoo = () => {
        this.timesMooed++;
        return "moo";
  }
}

var actionResults = [];
function doAction(action) {
    actionResults.push(action());
}

var jerry = new cow();
// no need to bind() now
doAction(jerry.sayMoo);

console.log(actionResults);
console.log(jerry.timesMooed);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...