Как получить правильный "this" в Array.map?
Я предполагаю, что здесь есть приложение call
или apply
, но я не уверен, как его реализовать.
http://codepen.io/anon/pen/oXmmzo
a = {
foo: 'bar',
things: [1, 2, 3],
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
});
}
}
a.showFooForEach();
Скажем, я хочу map
массив, но в функции мне нужен доступ к this
, к которому принадлежит foo
. function
из map
создает новый this
контекст, поэтому мне, очевидно, нужно как-то сгладить этот контекст, но как мне это сделать, все еще имея доступ к thing
?
Ответы
Ответ 1
Только что понял, что я должен внимательно прочитать документацию для Array.map()
. Просто нужно передать значение this
в качестве второго параметра map()
http://codepen.io/anon/pen/VLggpX
a = {
foo: 'bar',
things: [1, 2, 3],
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
}, this);
}
}
a.showFooForEach();
Кроме того, понимание того, как работают bind()
, call()
и apply()
, необходимо для серьезных разработчиков JavaScript. Это позволяет нам пропустить глупые задания типа
var self = this;
myItems.map(function(item) {
self.itemArray.push(item);
});
с
myItems.map(function(item) {
this.itemArray.push(item);
}.bind(this));
Ответ 2
Ничего сложного! map
принимает второй параметр thisArg
, поэтому вы просто передаете его с помощью функции, которую вы хотите вызвать для каждого элемента:
a = {
foo: 'bar',
things: [1, 2, 3],
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
}, this);
}
}
a.showFooForEach();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Ответ 3
Существует три способа:
Явная переменная
Тот, у кого нет специальной нечетности this
:
var self = this;
this.things.map(function(thing) {
console.log(self.foo, thing);
});
Function.prototype.bind
this.things.map(function(thing) {
console.log(this.foo, thing);
}.bind(this));
Использовать второй параметр Array.prototype.map
Второй параметр (необязательный) - это контекст, с которым вызывается внутренняя функция.
this.things.map(function(thing) {
console.log(this.foo, thing);
}, this);
Первые два способа - это общие способы работы с this
; третья специфична для map
, filter
, forEach
.
Ответ 4
Вы можете использовать bind()
его в своем контексте.
a = {
foo: 'bar',
things: [1, 2, 3],
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
}.bind(this));
}
}
a.showFooForEach();
Это из-за лексической области JS
Из MDN:
Метод bind() создает новую функцию, которая при вызове имеет свой это ключевое слово установлено на предоставленное значение, с заданной последовательностью аргументы, предшествующие любому, предоставленному при вызове новой функции.
Подробнее здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
И здесь: http://javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals/
Кроме того, map()
принимает второй параметр как "this"
a = {
foo: 'bar',
things: [1, 2, 3],
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
}, this);
}
}
a.showFooForEach();
Из документации MDN map()
:
Параметры
callback Функция, которая создает элемент нового массива
thisArg Дополнительно. Значение, которое будет использоваться при выполнении обратного вызова.
Дополнительная литература: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Ответ 5
карта допускает второй аргумент, называемый "thisArg", поэтому вы просто используете его так:
showFooForEach: function() {
this.things.map(function(thing) {
console.log(this.foo, thing);
},this);