Контекст функции JavaScript Неправильный

Я заметил странную вещь в javascript. Рассмотрим ниже:

var fn = ''.toUpperCase.call
console.log(typeof fn); // "function"
fn(); // Uncaught TypeError: `fn` is not a function

Вышеупомянутое было выполнено на моей консоли разработчика Chrome. Версия 43.0.2357.81 m.

Оператор typeof ясно показывает, что fn является функцией, но ошибка предполагает иное.

Я заметил, что Function.apply показывает хотя бы какое-то значимое сообщение об ошибке.

Итак, когда функция, а не функция?

Ответы

Ответ 1

Контекст в Javascript всегда устанавливается так, как вы вызываете функцию.

var fn = ''.toUpperCase.call

Это назначает прототип реализации функции call на fn. Если вы теперь вызываете fn(), контекст для вызова отсутствует. call попытается вызвать объект функции, с которым он был связан. Однако этот контекст устанавливается во время вызова. Поскольку вы не даете ему никакого контекста во время вызова, некоторый внутренний компонент call выдает ошибку.

Вам нужно будет сделать это:

fn.call(''.toUpperCase)

Правильно, вы call функция call, устанавливая контекст, а именно строковая функция toUpperCase. В этом конкретном случае это приведет к другой ошибке внутри toUpperCase, поскольку она не привязана к конкретному контексту. Вам также необходимо будет установить этот контекст:

var fn = ''.toUpperCase.call
fn.call(''.toUpperCase.bind(''))

Также см. Как работает ключевое слово "his" ?

Ответ 2

отменить ответ, я просто хочу объяснить это с другой точки зрения.

Ваш fn является ссылкой на Function.prototype.call, который должен быть вызван с помощью функции в качестве ссылки this, в этом случае контекст для call равен String.prototype.toUpperCase, который был унаследован через ''.toUpperCase

Кроме того, String.prototype.toUpperCase также должен вызываться с конкретным контекстом, строка в верхний регистр.

Вот еще один способ кодировать то, что вы хотели, что может помочь вам понять, что происходит.

    var str = 'aaa';
    var upper = ''.toUpperCase;
    var fn = upper.call;
    // Now we have to specify the context for both upper and fn
    console.log( fn.call(function() { return upper.call(str)}) ); // AAA

Ответ 3

Итак, когда функция, а не функция?

Функция - это функция, но вы не выполняете ее правильно, как объяснено в комментариях и ответе @deceze

Я заметил странную вещь в javascript.

Вы, похоже, смущены сообщением о том, что вы попадаете в среду, в которой вы протестировали, сообщение не является строго правильным.

Uncaught TypeError: fn не является функцией

Текущая стабильная версия хром (40.0.2214.91 на моем Linux-установке, хром не работает на моем оборудовании без внесения изменений настроек), хром, являющийся средой, на которой вы протестировали, дает, казалось бы, более правильное сообщение об ошибке, которое делает больше чувство.

Uncaught TypeError: undefined is not a function

Итак, вы спрашивали/хотели задать серьезный вопрос, или вы просто подшучивали над ошибкой в ​​версии хром?