Я играл с методом вызова в JavaScript, и я нашел что-то интересное:
Я создавал пользовательскую функцию карты, и я сделал что-то вроде этого:
function map(collection, callback, context) {
if (!collection || !collection.hasOwnProperty('length') || typeof(callback) !== 'function') {
throw new TypeError();
}
var newArray = [];
var isFunction = typeof(callback.call) === 'function'; // this I added after to prove my point.
console.log('is callback.call a function? ' + (isFunction ? 'yes it is!' : 'no, it is not a function'));
for (var i = 0, len = collection.length; i < len; i++) {
newArray[i] = callback.call(context, collection[i], i, collection);
}
return newArray;
}
В этот момент я выполнил свою функцию map
со следующими аргументами:
var arr = map(Array.apply(null, { length: 2 }), Number.call);
Я пропустил значение для аргумента context, поэтому он не undefined
. Что должно быть круто. Также, что немного странно, как callback
я передал метод call
поэтому в конце: я call
метод call
методу call
(что тоже круто).
Но по неизвестной причине браузер дает мне эту ошибку:
is callback.call a function? yes it is!
Uncaught TypeError: callback.call is not a function
at map (eval at map (:10:9), <anonymous>:10:32)
at eval (eval at map (:10:9), <anonymous>:15:11)
at map (<anonymous>:10:9)
at <anonymous>:1:1
Интересно, что является реальной причиной этого. callback.call
- это функция. Есть ли способ справиться с таким делом? Как я могу проверить, предоставили ли аргументы мне такую ошибку?
Именно тогда я предоставляю контекст:
map(Array.apply(null, { length: 2 }), Number.call, Number)
// is callback.call a function? yes it is!
// [0, 1]
CodePen (отсутствует ошибка в консоли, я рекомендую использовать браузер для воспроизведения)
EDIT: просто для уточнения контекста не требуется вообще:
map([1, 2], function(i) {
return i + 5;
});
// is callback.call a function? yes it is!
// [6, 7]
EDIT # 2 Я вижу, как другие вопросы относятся к моей. И они объяснили причину этого, также в Firefox есть неплохое сообщение об ошибке для этого:
TypeError: Function.prototype.call called on incompatible undefined
Поэтому мой последний вопрос:
Есть ли способ обнаружить такую "несовместимость"?
Вы Number.call
функцию Number.call
в качестве параметра. Таким образом, внутри вашей функции callback
функции map
уже Number.call
функция Number.call
. Тогда вы больше не должны использовать callback.call
. Просто использовать callback
должно быть исправление.
Это всего лишь моя идея с 2 центрами. Надеюсь, поможет!
EDIT: Потому что call
является функцией Function.prototype
поэтому он будет отображаться в каждом экземпляре функции. И this
контекст должен быть функцией. Момент, вы передаете Number.call
на свою новую map
, вы уже потеряли свой контекст, потому что внутри новой map
this
уже не функция.
call
является функциейFunction.prototype
поэтому он будет появляться в каждом экземпляре функции.