В моем конкретном случае:
callback instanceof Function
или
typeof callback == "function"
действительно ли это имеет значение, какая разница?
Дополнительный ресурс:
JavaScript-Garden typeof vs instanceof
В моем конкретном случае:
callback instanceof Function
или
typeof callback == "function"
действительно ли это имеет значение, какая разница?
Дополнительный ресурс:
JavaScript-Garden typeof vs instanceof
instanceof
для настраиваемых типов:var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; //false
instance instanceof Object; //true
instance instanceof ClassFirst; //true
instance instanceof ClassSecond; //false
typeof
для простых встроенных типов:'example string' instanceof String; // false
typeof 'example string' == 'string'; //true
'example string' instanceof Object; //false
typeof 'example string' == 'object'; //false
true instanceof Boolean; // false
typeof true == 'boolean'; //true
99.99 instanceof Number; // false
typeof 99.99 == 'number'; //true
function() {} instanceof Function; //true
typeof function() {} == 'function'; //true
instanceof
для сложных встроенных типов:/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; //object
[] instanceof Array; // true
typeof []; //object
{} instanceof Object; // true
typeof {}; //object
И последнее немного сложнее:
typeof null; //object
Оба одинаковы по функциональности, потому что оба возвращают информацию о типе, однако я лично предпочитаю instanceof
, потому что он сравнивает фактические типы, а не строки. Сравнение типов менее подвержено человеческой ошибке, и оно технически быстрее, поскольку оно сравнивает указатели в памяти, а не выполняет целые сравнения строк.
Причиной использования typeof является то, что переменная может быть undefined.
alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
Хорошей причиной использования instanceof является то, что переменная может быть нулевой.
var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar instanceof Object); // alerts "false"
Так что, на мой взгляд, это будет зависеть от того, какие типы данных вы проверяете.
Чтобы все было ясно, вам нужно знать два факта:
Это означает, что instanceof применим только к объектам.
Именно по этой причине он не используется для проверки примитивных типов. В большинстве случаев вы не используете конструкторы для создания строк или чисел. Ты можешь. Но почти никогда не бывает.
Также он не может проверить, какой именно конструктор использовался для создания объекта, но вернет true, даже если объект получен из проверяемого класса. В большинстве случаев это желаемое поведение, но иногда это не так. Поэтому вам нужно держать этот ум.
Другая проблема заключается в том, что разные области применения имеют разные среды исполнения. Это означает, что они имеют разные встроенные функции (разные глобальные объекты, разные конструкторы и т.д.). Это может привести к неожиданным результатам.
Например, [] instanceof window.frames[0].Array
вернет false
, потому что Array.prototype !== window.frames[0].Array
и массивы наследуются от первого.
Кроме того, он не может использоваться в значении undefined, потому что у него нет прототипа.
Я обнаружил некоторые действительно интересные (прочитанные как "ужасные" ) поведение в Safari 5 и Internet Explorer 9. Я использовал это с большим успехом в Chrome и Firefox.
if (typeof this === 'string') {
doStuffWith(this);
}
Затем я тестирую IE9, и он вообще не работает. Большой сюрприз. Но в Сафари это прерывисто! Поэтому я начинаю отладку, и обнаруживаю, что Internet Explorer всегда возвращает false
. Но самое странное, что Safari, похоже, делает какую-то оптимизацию в своей виртуальной машине JavaScript, где она true
в первый раз, но false
при каждом нажатии на перезагрузку!
Мой мозг почти взорвался.
Итак, теперь я решил:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
И теперь все работает отлично. Обратите внимание, что вы можете вызвать "a string".toString()
, и он просто возвращает копию строки, т.е.
"a string".toString() === new String("a string").toString(); // true
Итак, я буду использовать оба с этого момента.
instanceof
также работает, когда callback
является подтипом Function
, я думаю,
Другие Значительные практические различия:
// Boolean
var str3 = true ;
alert(str3);
alert(str3 instanceof Boolean); // false: expect true
alert(typeof str3 == "boolean" ); // true
// Number
var str4 = 100 ;
alert(str4);
alert(str4 instanceof Number); // false: expect true
alert(typeof str4 == "number" ); // true
instanceof
в Javascript может быть flaky - я считаю, что основные структуры пытаются избежать его использования. Различные окна - один из способов, которыми он может сломаться - я считаю, что иерархии классов тоже могут смутить его.
Существуют ли более эффективные способы проверки того, является ли объект определенным встроенным типом (обычно это то, что вы хотите). Создайте служебные функции и используйте их:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
И так далее.
Я бы рекомендовал использовать прототип callback.isFunction()
.
Они выяснили разницу, и вы можете рассчитывать на их разум.
Я думаю, что у других JS-фреймворков тоже есть такие вещи.
instanceOf
не будет работать над функциями, определенными в других окнах.
Их функция отличается от вашего window.Function
.
instanceof
не будет работать для примитивов, например "foo" instanceof String
вернет false
, тогда как typeof "foo" == "string"
вернет true
.
С другой стороны, typeof
, вероятно, не будет делать то, что вы хотите, когда речь заходит о пользовательских объектах (или классах, что бы вы ни называли). Например:
function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog // true, what we want in this case
Так получилось, что функции являются как "функциональными" примитивами, так и экземплярами "Function", что является немного странным, учитывая, что он не работает так, как для других примитивных типов, например.
(typeof function(){} == 'function') == (function(){} instanceof Function)
но
(typeof 'foo' == 'string') != ('foo' instanceof String)
Производительность
typeof
быстрее, чем instanceof
в ситуациях, когда они применимы.
В зависимости от вашего двигателя разница в производительности typeof
может быть примерно 20%. (Ваш пробег может отличаться)
Ниже приведено тестовое тестирование для Array
:
var subject = new Array();
var iterations = 10000000;
var goBenchmark = function(callback, iterations) {
var start = Date.now();
for (i=0; i < iterations; i++) { var foo = callback(); }
var end = Date.now();
var seconds = parseFloat((end-start)/1000).toFixed(2);
console.log(callback.name+" took: "+ seconds +" seconds.");
return seconds;
}
// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
(subject instanceof Array);
}, iterations);
// Testing typeof
var tot = goBenchmark(function typeofTest(){
(typeof subject == "object");
}, iterations);
var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));
Результат
instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
При проверке функции всегда следует использовать typeof
.
Здесь разница:
var f = Object.create(Function);
console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false
f(); // throws TypeError: f is not a function
Вот почему нельзя использовать instanceof
для проверки функции.
Значительная практическая разница:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
Не спрашивайте меня, почему.
Используйте instanceof, потому что если вы измените имя класса, вы получите ошибку компилятора.
var newObj = new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function
var hello ="hello, "+ name +"!";
return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function
console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!
console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"
Исходя из строгого воспитания ОО, я пошел бы за
callback instanceof Function
Строки подвержены либо моему ужасному написанию, либо другим опечаткам. Плюс я чувствую, что читает лучше.
Несмотря на то, что instanceof может быть немного быстрее, чем typeof, я предпочитаю второй из-за такой возможной магии:
function Class() {};
Class.prototype = Function;
var funcWannaBe = new Class;
console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function
Еще один случай: вы можете сопоставлять только с instanceof
- он возвращает true или false. С помощью typeof
вы можете получить тип предоставленного something
с учетом производительности, вам лучше использовать typeof с типичным оборудованием, если вы создаете script с циклом в 10 миллионов итераций инструкция: typeof str == 'string' займет 9ms в то время как "string" instanceof String займет 19 мс