Использование toString() вместо конструктора в JavaScript

Это, наверное, глупый вопрос, поэтому, пожалуйста, придерживайтесь меня.

Почему я вижу так много примеров, проверяющих, является ли объект функцией, сравнивая его toString() с "[object Function]"?

Например:

function isFunction(obj) {
    return Object.prototype.toString.call(obj) == "[object Function]";
}

Нельзя использовать instanceof Function или obj.constructor === Function? Не совместимы ли они с несколькими браузерами?

Это кажется неэффективным, но так ли? Почему?

Ответы

Ответ 1

Короткий ответ заключается в том, что typeof /foo/ - это функция в браузерах Webkit. CMS имеет длинное объяснение @jQuery's isFunction и InternetExplorer

И instanceOf не является надежным, так как Zuriy указывает:

Проблемы возникают, когда дело доходит до сценариев в многокадровых средах DOM. В двух словах объекты Array, созданные внутри одного iframe, не разделяют [[Prototype]] s с массивами, созданными в другом iframe. Их конструкторы представляют собой разные объекты, поэтому проверки экземпляров и конструкторов не выполняются:

Отличная статья @http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ от Zuriy по этому вопросу.

Пример, взятый из статьи:

var iframe = document.createElement('iframe'); 
document.body.appendChild(iframe); 
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]  

// Boom! 
arr instanceof Array; // false  

// Boom! 
arr.constructor === Array; // false

Ответ 2

Они не тестируют свой метод toString, они вызывают метод прототипа объекта toString на obj, чтобы передать его в строку. Функция передается как "[функция объекта]" в строку.

instanceof не является надежным и не является конструктором. Конструктор требует проверки, чтобы убедиться, что obj имеет значение null или нет, прежде чем пытаться получить доступ к свойству конструктора. Я также предполагаю, что это медленнее, чем метод toString.