Лучший метод тестирования функции в JavaScript?
-
03-07-2019 - |
Вопрос
Я провел немало исследований по этому поводу, но кажется, что используемые методы непоследовательны и разнообразны.
Вот некоторые методы, которые я использовал в прошлом:
/* 1: */ typeof myFunc === 'function'
/* 2: */ myFunc.constructor === Function
/* 3: */ myFunc instanceof Function
В рамках своего исследования я рассмотрел, как это удалось сделать некоторым известным библиотекам:
/* jQuery 1.2.6: */ !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test( fn + "" )
/* jQuery 1.3b1: */ toString.call(obj) === "[object Function]"
/* Prototype 1.6: */ typeof object == "function"
/* YUI 2.6: */ typeof o === 'function'
Я поражен тем, что используется так много разных методов, неужели не был согласован единый приемлемый тест?И я совершенно не понимаю, каковы были намерения при использовании jQuery 1.2.6, выглядит немного ОТТ...
Итак, мой вопрос остается: каков наилучший* способ тестирования функции?
Я также был бы признателен за некоторую информацию о некоторых из вышеперечисленных методов, особенно о jQuery 1.2.6.(Я вижу, что они делают, просто это кажется странным)
[*] Под «лучшим» я подразумеваю наиболее широко распространенный метод, совместимый с разными браузерами.
РЕДАКТИРОВАТЬ:Да, я знаю, что это обсуждалось раньше, но мне все же хотелось бы обсудить наиболее эффективный метод.Почему существует так много различных используемых методов?
В дискуссиях по SO до сих пор упоминался только оператор typeof (в основном), но никто не намекнул на эффективность альтернативных методов.
Решение
Лучший способ проверить, является ли объект функцией: typeof myFunc === 'function'
.Если вы используете библиотеку, используйте функциональный тест этой библиотеки: jQuery.isFunction(myFunc)
.
Вещи может быть ошибочно сообщены как функции при использовании typeof
.Это очень редко, но существует библиотека, которая устраняет эти несоответствия.jQuery решает эти проблемы:
- Функция отчетов Firefox работает с
typeof document.createElement("object")
- Отчеты Safari функционируют с
typeof document.body.childNodes
- Более старые версии Firefox сообщали о регулярных выражениях как о функциях (в версии 3.0 это не так).
- Некоторые IE встроены в глобальные функции (
alert
) и некоторые методы узлов (getAttribute
), как сообщается, относятся к типу «объект».
С использованием instanceof
скорее, чем typeof
обходит некоторые из них.Например, document.createElement("object") instanceof Function
является false
в Фаерфоксе.
Рождение первого метода вы можете посмотреть в комментариях к оригинальный билет (#3618).Новый метод взят из набор изменений 5947 и, кажется, был изобретен Ресигом для решения Утечки памяти IE.Вероятно, он медленнее, но меньше и чище.
Здесь нет большой разницы между == и === с точки зрения того, как все работает, но строгая оценка немного быстрее и поэтому предпочтительнее.
Другие советы
Джон Ресиг, разработчик jQuery, похоже, сделал несколько странный выбор во внутреннем устройстве jQuery.
toString.call(obj) === "[object Function]"
выглядит довольно аккуратно, но я не могу придумать ни одной ситуации, в которой вышесказанное было бы правдой, где простой typeof
подход потерпит неудачу, но, возможно, он знает что-то, чего не знают остальные пользователи.
typeof o === "function"
Я бы выбрал последнее, поскольку оно более ясно, если только у вас нет убедительных доказательств того, что оно не сработает.
Зачем использовать строгое равенство typeof
поскольку оба операнда являются строками?Я упускаю из виду какую-то проблему?
В любом случае, я бы пошел по более простому пути typeof, который, кажется, сделан для этого и читаем. instanceof
тоже читается, но, похоже, больше настаивает на том факте, что функция является объектом, что может не иметь отношения к проблеме.