#javascript #arrays #dictionary #this #call
#javascript #массивы #словарь #это #вызов
Вопрос:
Я обновил свои знания о call()
и map()
использовании JavaScript на NodeList
.
Было довольно легко найти в Google, что call()
следует делать, и есть ресурсы с примерами того, как это работает с map()
.
Однако, как я заметил в MDN, map()
функция также может принимать второй аргумент, который должен задавать this
ключевое слово для map()
— или, по крайней мере, это то, что я думаю, что это должно делать.
Я попытался проверить это сам с помощью простых массивов:
var numbers = [1, 2, 3];
var letters = ['a', 'b', 'c'];
..и с помощью простой функции, которая будет передана в качестве параметра для map()
:
var effector = function (x) {
console.log(x);
}
Теперь, чего я не понимаю, так это почему эти два вызова функции дают разные результаты:
numbers.map(effector, letters);
numbers.map.call(letters, effector);
Я ожидаю, что они оба будут выводить буквы на консоль, поскольку оба this
ключевых слова должны ссылаться на них (соответственно на их объекты).
Я провел некоторые дальнейшие исследования и попробовал использовать эту модифицированную эффекторную функцию:
var effector = function () {
console.log(this);
}
..снова на:
numbers.map(effector, letters);
numbers.map.call(letters, effector);
Предполагая, что мы находимся в режиме «использовать строго», первый вызов регистрируется letters
, а второй регистрируется undefined
.
Но опять же, я бы ожидал, что оба этих вызова выдадут одинаковый результат.
Чего мне не хватает?
Редактировать:
Я читал, как .map
может быть заполнено, если вы проверите это в MDN, там вы увидите, как используется второй параметр .map в callback.call()
.
Я полагаю, что в конце концов даже это callback.call()
должно иметь то же самое, this
что и в .map
.
Комментарии:
1. Я ожидаю, что они будут иметь одинаковые результаты, без какой-либо возможной разницы. Однако я должен выделить это в сообщении.
2. примечание: вы также можете изменить
this
с помощью.bind()
метода
Ответ №1:
Здесь используются две привязки this
ссылки:
this
для контекста выполненияmap
функцииthis
для контекста выполнения функции обратного вызова
Они не связаны друг с другом.
Второй аргумент map
диктует, что this
будет для обратного вызова. Если оно не указано, по умолчанию используется undefined
(не массив).
Первый аргумент map.call
определяет, что this
будет для map
— и, следовательно, какой массив будет повторен.
Это также отражено в polyfill, предоставленном в mdn: он идеально соответствует этим спецификациям: O
получает значение this
для map
функции и T
получает значение this
для обратного вызова. Они, как правило, разные.
map
против forEach
Не имеет отношения к вашему вопросу, но стоит упомянуть: не используйте, map
когда вы на самом деле ничего не отображаете. map
предназначено для создания нового массива, в котором каждое значение было сопоставлено путем вызова функции обратного вызова для исходного значения с тем же индексом.
Однако, когда вам просто нужно выполнить итерацию значений массива без какого-либо намерения выполнить такое сопоставление, используйте forEach
метод или for...of
цикл. Оба они работают NodeList
из коробки, без необходимости .call
.
Комментарии:
1. Вы пришли туда примерно за минуту до меня 🙂 (и выразили это гораздо яснее, чем я)
2. Спасибо, что попытались разъяснить использование карты и ответить на мой вопрос, но не могли бы вы, пожалуйста, проверить мою правку? Я, наверное, понимаю ваш ответ, но я думаю, что есть что-то большее. Я знаю о возвращаемом значении .map, я был сосредоточен на нем, потому что скоро я начну изучать React, и я знаю, что map используется для возврата JSX, а не для forEach. И я не хотел менять свой вопрос на forEach, так как хотел избежать возможных новых проблем из-за различий map / forEach.
3. Я прочитал вашу правку, но я не вижу ничего в polyfill, что не соответствует моему ответу. Переменная
T
не определена, еслиmap
не получен второй аргумент: в этом случаеT
становится этим значением.T
будетthis
значением для обратного вызова (только). Это то, что я говорю в своем ответе: этоthis
не имеет ничего общего с тем,this
с помощью которогоmap
вызывается само.4. Практическое использование полностью зависит от программиста: это удобство, которое предлагается. Это может быть полезно, когда такое
map
вызывается в методе класса, где вы хотите, чтобы обратный вызов имелthis
ссылку на этот экземпляр класса, чтобы он мог вызывать другие методы класса сthis.method
обозначением.5. Обратите внимание, что все аргументы функции являются локальными переменными в этой функции. Это общий принцип.
Ответ №2:
Разница между numbers.map(effector, letters)
и numbers.map.call(letters, effector)
заключается в том, на какую функцию this
letters
установлено значение.
Во-первых, как объясняет MDN, второй аргумент — это значение, которое нужно использовать как this
внутри обратного вызова, то есть аргумент, предоставленный map
. То есть в numbers.map(effector, letters)
this
inside effector
будет letters
. Поскольку effector
(в первой версии) не имеет значения, что this
есть, этот аргумент по существу не имеет никакого эффекта, и содержимое numbers
регистрируется.
В numbers.map.call(letters, effector)
, с другой стороны, это то, numbers.map
для this
которого letters
установлено значение. Что фактически означает, что map
метод, хотя и вызывается numbers
, вместо этого «захвачен» для регистрации записей letters
.
Второй пример работает аналогично — решающее значение имеет то, в какой функции this
установлен effector
: numbers.map
в одном случае,, в другом.
Комментарии:
1. Я поддержал вас, поэтому, даже если вы не будете показаны выше предыдущего ответа, вы можете заработать некоторую репутацию. Как я прокомментировал в предыдущем ответе, может быть что-то более неясное с использованием map, не могли бы вы, пожалуйста, проверить «РЕДАКТИРОВАТЬ» в конце моего вопроса?