Почему не работает [ "A", "B", "C" ]. Map (String.prototype.toLowerCase.call)?
Это, конечно, возвращает то, что вы ожидаете:
["A","B","C"].map(function (x) {
return x.toLowerCase();
});
// --> ["a", "b", "c"]
Так же использует String.prototype.toLowerCase.call:
["A","B","C"].map(function (x) {
return String.prototype.toLowerCase.call(x);
});
// --> ["a", "b", "c"]
Он также работает, если вы передаете дополнительные аргументы, заданные картой, поскольку это отбрасывает аргументы:
["A","B","C"].map(function (x, index, arr) {
return String.prototype.toLowerCase.call(x, index, arr);
});
// --> ["a", "b", "c"]
Но это не работает:
["A","B","C"].map(String.prototype.toLowerCase.call);
// --> TypeError: undefined is not a function
Не работает также следующее, поскольку arguments
имеет прототип объекта вместо прототипа Array, поэтому slice
есть undefined. Является ли причина вышеуказанного поведения, возможно, из-за чего-то вроде этого: где slice
или какая-либо другая аналогичная функция Array используется внутри?
["A","B","C"].map(function (x) {
return String.prototype.toLowerCase.apply(x, arguments.slice(1));
});
// --> TypeError: undefined is not a function
Ответы
Ответ 1
Это особое поведение точечной нотации JavaScript.
toLowerCase.call(x)
работает, потому что JavaScript использует toLowerCase
как this
при выполнении call
. Вот как call
(который является тем же самым Function.prototype.call
, который вы найдете на каждой функции) знает, что вы хотите выполнить toLowerCase
.
Передача call
в другую функцию теряет эту ссылку, поэтому this
больше не относится к toLowerCase
.
Ответ 2
Аналогичный вопрос: Почему не будет передаваться` `'.trim()` прямо в `[].map()` обратный вызов?
В карте есть необязательный thisArg, который можно использовать следующим образом:
['A', 'B', 'C'].map(Function.prototype.call, String.prototype.toLowerCase);
// gives ["a", "b", "c"]
Ответ 3
Проблема заключается в том, что String.prototype.toLowerCase.call == Function.prototype.call
. Если вы хотите получить функцию, которая преобразует аргумент в нижний регистр, вы можете привязать функцию toLowerCase
к функции call
следующим образом:
var toLowerCase = String.prototype.toLowerCase.call.bind(String.prototype.toLowerCase);
["A","B","C"].map(toLowerCase);
Ответ 4
Но это не работает:
[ "А", "В", "С" ] карта (String.prototype.toLowerCase.call);.
Первым аргументом, переданным map, должна быть функция, которая будет передана значение элементов массива. Вышеприведенная информация ссылается на функцию Function.prototype.call, поэтому функция будет пытаться:
call(x);
Таким образом, вызов был передан без его установки, поэтому при входе в функцию вызова будет undefined.