Используя «это» в качестве функции в Javascript применить - PullRequest
2 голосов
/ 16 марта 2019
    Function.prototype.defer = function(ms) {
    let f = this
    return function(...args) {
        setTimeout(()=>this.apply(this, args), ms); //**
    }
};


function f(a, b) {
  alert( a + b );
}

f.defer(1000)(1, 2); // shows 3 after 1 second

Таким образом, приведенный выше код выдает ошибку, говорящую «this.apply не является функцией».Однако, если я изменю строку с (**) на

setTimeout(()=>f.apply(this, args), ms);

, код будет работать нормально, даже если f по-прежнему ссылается на «this».Что дает?

Ответы [ 4 ]

1 голос
/ 16 марта 2019

Давайте посмотрим на код, приведенный в вопросе, чтобы понять, почему один работает, а другой нет.

Давайте сначала посмотрим на работающий пример:

Function.prototype.defer = function (ms) {
  let f = this;
  return function(...args) {
    setTimeout(() => f.apply(this, args), ms);
  };
};

function f(a, b) {
  alert(a + b);
}

f.defer(1000)(1, 2); // shows 3 after 1 second
// translates to
setTimeout(() => f.appy(this, [1, 2]), 1000);
//                       ^
// here `this` refers to the global object (window)

Давайте посмотрим на нерабочий пример:

Function.prototype.defer = function (ms) {
  return function(...args) {
    setTimeout(() => this.apply(this, args), ms);
  };
};

function f(a, b) {
  alert(a + b);
}

f.defer(1000)(1, 2); // shows 3 after 1 second
// translates to
setTimeout(() => this.appy(this, [1, 2]), 1000);
//                ^         ^
// here `this` refers to the global object (window)

Поскольку this в вышеприведенном контексте указывает наглобальный объект (окно), вы также можете написать это как:

setTimeout(() => window.appy(window, [1, 2]), 1000);

Поскольку window является объектом, а не функцией, это объясняет ошибку, которую вы получаете.

1 голос
/ 16 марта 2019

Каждый function имеет свой собственный this, который необязательно идентичен внешнему this.

. Вы можете связать this с возвращенной функцией дляпараметры.

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

Function.prototype.defer = function(ms) {
    return function(...args) {
        setTimeout(() => this.apply(this, args), ms); //**
    }.bind(this);
};

function f(a, b) {
    console.log(a + b);
}

f.defer(1000)(1, 2); // shows 3 after 1 second
0 голосов
/ 19 марта 2019

Использование this отличается между функциями стрелки и обычными функциями.Для функций стрелок у них есть свои this .

Но когда this используется в других функциях, существует более сложный набор правил, и часто это зависит ототкуда вызывается функцияВот список тех правил, если вам интересно: https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#review-tldr

0 голосов
/ 16 марта 2019

функция this изменится, как если бы у вас было то же имя параметра (ms в следующем примере), что и для внешней области видимости.

Function.prototype.defer = function(ms) {
    let f = this
    return function(ms,...args) {
        setTimeout(() => f.apply(this, args), ms); //**
    }
};

function f(a, b) {
    console.log(a + b);
}

f.defer(100000)(1000, 1, 2); // shows 3 after 1 second (not 100 second)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...