Как получить правильный "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);