При оценке типа функции мы обычно используем метод typeof. В обычных обстоятельствах он дает ожидаемый эффект. Однако есть некоторые детали, которые нам мало известны. Проанализировав эти детали, Джон Резиг предоставил нам идеальное решение, которое будет подробно представлено в этой статье:
1. Неизвестные детали традиционных методов.
Нет сомнений, что при определении типа функции мы используем метод typeof, например:
функция фн(){
//содержание
}
alert(typeof fn)//Результат — «функция».
Однако этот метод не работает должным образом в некоторых браузерах.
1. Firefox2 и Firefox3
В этих двух браузерах использование typeof для определения типа элемента объекта HTML приводит к неточному результату «функция» вместо «объекта», например HTMLDocument. нравиться:
предупреждение (тип HTMLDocument);
//В Firefox2 результатом является «функция»;
//В Firefox3 результатом является «объект»;
2. Firefox2
Для регулярных выражений результатом, возвращаемым в этом браузере, является «функция» (в Firefox3 результатом является «объект»), например:
вар рег = /тест/;
предупреждение (тип reg);
//В Firefox2 результатом является «функция»;
//В Firefox3 результатом является «объект»;
Примечание. Я тестировал это в Safari, и результат тоже был «функциональным».
3. IE6 и IE7
При использовании метода typeof для элемента DOM в IE результатом является «объект». нравиться:
alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//Результатом является «объект»
4. Сафари 3
Safari считает, что NodeList элементов DOM — это функция, например:
предупреждение (тип документа.body.childNodes);
//Результатом является "функция"
Очевидно, что если вы хотите проверить, является ли объект функцией, использование метода typeof не гарантирует результата теста в реальном смысле. Затем нам нужно решение, которое гарантирует результаты тестов во всех браузерах. Мы знаем, что сама функция имеет два метода: apply() и call(), но эти два метода не существуют в проблемной функции в IE. Попробуйте следующий тест:
alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//Результат «не определен» в IE
Очевидно, что мы не можем воспользоваться этими двумя методами.
2. Идеальное решение и процесс реализации.
Джон Резиг предоставил нам идеальное решение. Этот сложный, но стабильный метод определения того, является ли объект функцией, заключается в следующем:
функция isFunction( fn ) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != Массив &&
/function/i.test( fn + "" );
}
Эта функция сначала проверяет существование тестового объекта и сериализует его в строку, содержащую «функцию». Это основа нашего обнаружения (fn.constructor != String, fn.constructor != Array и fn.constructor != RegExp). . Кроме того, нам необходимо убедиться, что объявленная функция не является узлом DOM (fn.nodeName). Затем мы можем выполнить тест toString. Если мы преобразуем функцию в строку, в браузере (fn+"") дает нам результат, подобный этому "имя функции(){...}". Теперь определить, является ли это функцией, так же просто, как проверить, содержит ли строка слово «функция». Это творит чудеса: для любой рассматриваемой функции мы получаем нужные нам результаты во всех браузерах. По сравнению с традиционным методом скорость работы этой функции несколько неудовлетворительна. Автор рекомендует использовать ее консервативно.
Джон Резиг — разработчик библиотеки jQuery. Я уверен, что друзья, использующие эту библиотеку, знакомы с ее лаконичным синтаксисом и превосходной производительностью. Помимо стремления к простоте кода и высокой производительности, впечатляет и дух совершенства автора. Если вы перфекционист, я думаю, эта статья будет вам полезна.
Исходный текст: http://www.denisdeng.com/?p=426.