Как вызвать внешнее «это» во внутренней функции? - PullRequest
5 голосов
/ 23 декабря 2011

Я определил две функции для массива:

Array.prototype.remove = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            this.removeAt(i);
        }
    }
};
Array.prototype.removeAll = function(array2) {
    array2.forEach(function(item) {
        this.remove(item);  // remove not found!!
    });
}

Но в функции removeAll он сообщает function remove is not found.Я исправляю это так:

Array.prototype.removeAll = function(array2) {
    var outer = this;
    array2.forEach(function(item) {
        outer.remove(item);  
    });
}

Но это безобразно.Есть ли лучший способ?

Ответы [ 4 ]

6 голосов
/ 23 декабря 2011

Передача this через другую переменную, как вы это идиоматический подход.В этом нет ничего страшного.(Хотя чаще вызывать переменную that или self)

2 голосов
/ 23 декабря 2011

Альтернатива использованию bind (если вам нужно поддерживать старые браузеры и не хотите расширять Function.prototype) - просто обернуть ваш обратный вызов в функцию immidate и ввести this в качестве аргумента, подобного этому:

Array.prototype.removeAll = function(array2) {
    array2.forEach(function(outer){
     return function(item) {
        outer.remove(item);  
    };}(this));
}

или вы можете написать простую служебную функцию карри и использовать как это

function curry() {
  var fn = Array.prototype.shift.call(arguments), 
      args = Array.prototype.slice.call(arguments);
  return function curryed() {
    return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
  };
};



Array.prototype.removeAll = function(array2) {
    array2.forEach(curry(function(item) {
        outer.remove(item);  
    },this));
}

Если вы не возражаете против расширения Function.prototype, вы можете использовать связывание, как уже описано другими, вы можете найти отличное расширение совместимости для MDN здесь: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

2 голосов
/ 23 декабря 2011

Передав следующий один аргумент forEach , который будет контекстом this в функции обратного вызова, в вашем случае this относится к объекту окна.

Array.prototype.removeAll = function(array2) {

    array2.forEach(function(item) {
        this.remove(item);  
    },this);
}
1 голос
/ 23 декабря 2011

Существует Function.bind и аналогичные.

array2.forEach((function(item) {
    this.remove(item);  
}).bind(this));

Технически это не то же самое, что и предыдущее «внутреннее это» теперь затенено / потеряно (и новая функция-обертка создана), но в некоторых контекстах она прекрасно работает.

В большинстве случаев я предпочитаю стандарт var self = this ...

Счастливое кодирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...