В моем конкретном случае:
callback instanceof Function
or
typeof callback == "function"
это вообще имеет значение, какая разница?
Дополнительный ресурс:
JavaScript-Garden typeof vs instanceof
В моем конкретном случае:
callback instanceof Function
or
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
typeof
последовательно сообщает вам, является ли что-то функцией или нет. Однако я не могу придумать примеров, когда instanceof
дал бы вам неправильный ответ.
- person froginvasion; 30.07.2014
Use instanceof for complex built in types
- это все еще подвержено ошибкам. Лучше использовать ES5 Array.isArray()
et al. или рекомендуемые прокладки.
- person OrangeDog; 04.05.2016
const a = 'string'; const b = new String('string');
Проверка того, что b instanceof
String вернет истинное значение typeof, будет работать строковый литерал, instanceof, если он создан с помощью конструктора
- person Chris Panayotoff; 23.01.2020
'example string' instanceof String
неверно? Как это не экземпляр строки?
- person David Klempfner; 17.05.2021
new String('example string')
(однако никогда не делайте этого).
- person Szymon Wygnański; 18.05.2021
Оба схожи по функциональности, потому что оба возвращают информацию о типе, однако я лично предпочитаю instanceof
, потому что он сравнивает фактические типы, а не строки. Сравнение типов менее подвержено человеческим ошибкам и технически быстрее, поскольку сравнивает указатели в памяти, а не сравнивает целые строки.
typeof
.
- person RobG; 24.05.2012
typeof something === "type"
специальный корпус, поэтому реального сравнения строк нет.
- person Konrad Borowski; 20.07.2013
instanceof
перемещается вверх по цепочке прототипов в поисках прототипа конструктора [mdn.io/instanceof]. Таким образом, он позволяет проверить, является ли что-то экземпляром подкласса.
- person omninonsense; 21.12.2013
Object.create(Function)
, ваш код сломается, если вы используете instanceof
вместо typeof
.
- person vitaly-t; 20.07.2016
instanceof
, изменив свойство contructor
. См. Сообщение 2ality Какой объект не является экземпляром Object? И потому что javascript превращает нас в студенистую слизь, мы и поступаем так.
- person harpo; 28.03.2017
Хорошая причина использовать typeof - если переменная может быть неопределенной.
alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
Хорошая причина использовать instanceof, если переменная может иметь значение NULL.
var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar instanceof Object); // alerts "false"
Так что на самом деле, на мой взгляд, это будет зависеть от того, какие типы возможных данных вы проверяете.
instanceof
не может сравниваться с примитивными типами, typeof может.
- person Tino; 18.03.2011
undefined instanceof Object
возвращает false и не генерирует исключение. Я не знаю, насколько недавно это изменение, но оно делает instanceof
более привлекательным.
- person Cypress Frankenfeld; 26.06.2013
undefined instanceof Object
не генерирует исключение, потому что, а, undefined
определено. Константа существует в пространстве имен. Если переменная не существует (например, из-за опечатки), instanceof выдаст исключение. С другой стороны, использование typeof для несуществующей переменной дает undefined.
- person cleong; 28.03.2015
Чтобы прояснить ситуацию, вам нужно знать два факта:
Object.setPrototypeOf()
(ECMAScript 2015) или свойством __proto__
(старые браузеры, не рекомендуется). Однако изменять прототип объекта не рекомендуется из-за проблем с производительностью.Таким образом instanceof применим только к объектам. В большинстве случаев вы не используете конструкторы для создания строк или чисел. Вы можете. Но вы почти никогда этого не делаете.
Также instanceof не может проверить, какой именно конструктор использовался для создания объекта, но вернет true, даже если объект является производным от проверяемого класса. В большинстве случаев это желаемое поведение, но иногда это не так. Так что вам нужно помнить об этом.
Другая проблема заключается в том, что разные области видимости имеют разные среды выполнения. Это означает, что они имеют разные встроенные функции (разные глобальные объекты, разные конструкторы и т. Д.). Это может привести к неожиданным результатам.
Например, [] instanceof window.frames[0].Array
вернет false
, потому что Array.prototype !== window.frames[0].Array
и массивы наследуются от первого.
Кроме того, его нельзя использовать для неопределенного значения, потому что у него нет прототипа.
Теперь поговорим об одной хитрости. Что, если вы используете конструктор для создания примитивного типа?
let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number
Похоже на магию. Но это не так. Это так называемый бокс (упаковка примитивного значения по объекту) и распаковка (извлечение завернутого примитивного значения из объекта). Такой код кажется «немного» хрупким. Конечно, вы можете просто избежать создания примитивного типа с помощью конструкторов. Но возможна и другая ситуация, когда бокс может вас задеть. Когда вы используете Function.call () или Function.apply () для примитивного типа.
function test(){
console.log(typeof this);
}
test.apply(5);
Чтобы избежать этого, вы можете использовать строгий режим:
function test(){
'use strict';
console.log(typeof this);
}
test.apply(5);
upd: Начиная с ECMAScript 2015, существует еще один тип, называемый Symbol, который имеет свой собственный typeof == "symbol".
console.log(typeof Symbol());
// expected output: "symbol"
Вы можете прочитать об этом в MDN: (Symbol, typeof).
if an object is created by a given constructor
Это неверно. o instanceof C
вернет истину, если o наследуется от C.prototype. Вы упомянули об этом позже в своем ответе, но это не очень ясно.
- person oyenamit; 13.03.2018
Я обнаружил действительно интересное (читаемое как «ужасное») поведение в Safari 5 и Internet Explorer 9. Я с большим успехом использовал это в Chrome и Firefox.
if (typeof this === 'string') {
doStuffWith(this);
}
Затем я тестирую в IE9, и он вообще не работает. Большой сюрприз. Но в Safari это прерывисто! Итак, я начал отладку и обнаружил, что Internet Explorer всегда возвращает false
. Но самое странное то, что Safari, похоже, выполняет какую-то оптимизацию в своей виртуальной машине JavaScript, где это true
первый раз, но false
каждый раз, когда вы нажимаете перезагрузку! em>
Мой мозг чуть не взорвался.
Итак, теперь я остановился на этом:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
И теперь все отлично работает. Обратите внимание, что вы можете вызвать "a string".toString()
, и он просто вернет копию строки, т.е.
"a string".toString() === new String("a string").toString(); // true
Так что с этого момента я буду использовать оба.
Другие существенные практические отличия:
// 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
также работает, когда callback
является подтипом Function
, я думаю
instanceof
в Javascript может быть нестабильным - я считаю, что основные фреймворки стараются избегать его использования. Разные окна - это один из способов, которым он может сломаться - я считаю, что иерархия классов также может сбить его с толку.
Есть лучшие способы проверить, является ли объект определенным встроенным типом (обычно это именно то, что вам нужно). Создавайте служебные функции и используйте их:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
И так далее.
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
Так уж получилось, что функции являются как примитивами «функции», так и экземплярами «Функции», что немного странно, учитывая, что это не работает так, например, для других примитивных типов.
(typeof function(){} == 'function') == (function(){} instanceof Function)
но
(typeof 'foo' == 'string') != ('foo' instanceof String)
Я бы рекомендовал использовать прототип callback.isFunction()
.
Они поняли разницу, и вы можете рассчитывать на их причину.
Думаю, в других JS-фреймворках тоже есть такие вещи.
Я полагаю, instanceOf
не будет работать с функциями, определенными в других окнах. Их функция отличается от вашей window.Function
.
При проверке функции всегда нужно использовать 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
для проверки функции.
typeof
неверно - f
- это все следующее: Object
(объект) и Function
(функция). За исключением меня, имеет смысл использовать instanceof
, потому что, зная, что это функция, я знаю, что это также объект, поскольку все функции являются объектами в ECMAScript. Обратное неверно - зная из typeof
, что f
действительно object
, я понятия не имею, что это тоже функция.
- person amn; 28.05.2018
length
, name
и call
от Function, но все они больше не функционируют. Что еще хуже, его нельзя назвать, и TypeError
говорит это: f is not a function
.
- person maaartinus; 15.05.2020
Производительность
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
instanceof
всегда следует за цепочкой прототипов объекта, поэтому снижение производительности будет зависеть от того, насколько далеко в цепочке прототипов находится класс, против которого проверяется instanceof
. Таким образом, для короткой цепочки наследования штраф будет ниже (например, [] instanceof Array
, {} instanceof Object
), а для длинной - больше. Итак, если и obj instanceof SomeClass
, и typeof obj !== 'string'
означают одно и то же с точки зрения некоторого вашего гипотетического кода (например, если вы просто проводите тест в if
, а не switch
через несколько классов и т. Д.), Тогда вам лучше выбрать второй, по производительности,
- person ankhzet; 13.06.2017
Это просто дополнительные знания ко всем остальным объяснениям здесь - я не предлагаю везде использовать .constructor
.
TL; DR: в ситуациях, когда typeof
не является вариантом и когда вы знаете, что вас не волнует цепочка прототипов, _ 3_ может быть жизнеспособным или даже лучше альтернатива instanceof
:
x instanceof Y
x.constructor === Y
Он входит в стандарт с версии 1.1, поэтому не стоит беспокоиться об обратной совместимости.
Мухаммад Умер кратко упомянул об этом в комментарии где-то здесь. Он работает со всем, что есть прототипом - так что все, кроме null
или undefined
:
// (null).constructor; // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties
(1).constructor; // function Number
''.constructor; // function String
([]).constructor; // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor; // function Boolean()
true.constructor; // function Boolean()
(Symbol('foo')).constructor; // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor
Array.prototype === window.frames.Array; // false
Array.constructor === window.frames.Array.constructor; // true
Кроме того, в зависимости от вашего варианта использования он может быть намного быстрее, чем instanceof
(вероятно, причина в том, что ему не нужно проверять всю цепочку прототипов). В моем случае мне нужен был быстрый способ проверить, является ли значение типизированным массивом:
function isTypedArrayConstructor(obj) {
switch (obj && obj.constructor){
case Uint8Array:
case Float32Array:
case Uint16Array:
case Uint32Array:
case Int32Array:
case Float64Array:
case Int8Array:
case Uint8ClampedArray:
case Int16Array:
return true;
default:
return false;
}
}
function isTypedArrayInstanceOf(obj) {
return obj instanceof Uint8Array ||
obj instanceof Float32Array ||
obj instanceof Uint16Array ||
obj instanceof Uint32Array ||
obj instanceof Int32Array ||
obj instanceof Float64Array ||
obj instanceof Int8Array ||
obj instanceof Uint8ClampedArray ||
obj instanceof Int16Array;
}
https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812
И результаты:
Chrome 64.0.3282.167 (64-разрядная версия, Windows)
Firefox 59.0b10 (64-разрядная версия, Windows)
Из любопытства я провел небольшой тест на typeof
; на удивление, он работает не намного хуже, а в Chrome он кажется даже немного быстрее:
let s = 0,
n = 0;
function typeofSwitch(t) {
switch (typeof t) {
case "string":
return ++s;
case "number":
return ++n;
default:
return 0;
}
}
// note: no test for null or undefined here
function constructorSwitch(t) {
switch (t.constructor) {
case String:
return ++s;
case Number:
return ++n;
default:
return 0;
}
}
let vals = [];
for (let i = 0; i < 1000000; i++) {
vals.push(Math.random() <= 0.5 ? 0 : 'A');
}
https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570
ПРИМЕЧАНИЕ. Порядок перечисления функций переключается между изображениями!
Chrome 64.0.3282.167 (64-разрядная версия, Windows)
Firefox 59.0b10 (64-разрядная версия, Windows)
ПРИМЕЧАНИЕ. Порядок перечисления функций переключается между изображениями!
Существенная практическая разница:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
Не спрашивайте меня, почему.
str
- это строковый примитив, а не строковый объект. То же самое касается числовых примитивов и логических примитивов, они не являются экземплярами их созданных аналогов, объектов String, Number и Boolean. JavaScript автоматически преобразует эти три примитива в объекты, когда это необходимо (например, используя метод в цепочке прототипов объекта). С другой стороны, instanceof лучше подходит для проверки массивов, так как typeof [] == "object" // true
.
- person Andy E; 03.10.2010
Используйте instanceof, потому что если вы измените имя класса, вы получите ошибку компилятора.
не нужно загромождать кучу приведенных выше примеров, просто помните две точки зрения:
typeof var;
- унарный оператор, который возвращает исходный тип или корневой тип переменной. так что он будет возвращать примитивные типы (string
, number
, bigint
, boolean
, undefined
и symbol
) или object
тип.
в случае объекта более высокого уровня, такого как встроенные объекты (String, Number, Boolean, Array ..) или сложных или настраиваемых объектов, все они относятся к корневому типу object
, но тип экземпляра, построенный на их основе, может быть разным (например, ООП концепция наследования классов), здесь a instanceof A
- бинарный оператор - вам поможет, он пройдёт по цепочке прототипов, чтобы проверить, появляется ли конструктор правого операнда (A) или нет.
поэтому всякий раз, когда вы хотите проверить «корневой тип» или работать с примитивной переменной - используйте «typeof», иначе используйте «instanceof».
null
- это особый случай, который кажется примитивным, но на самом деле это особый случай для объекта. Вместо этого используйте a === null
для проверки нуля.
с другой стороны, function
также является особым случаем, который является встроенным объектом, но typeof
возвращает function
как видите, instanceof
должен пройти через цепочку прототипов, а typeof
просто проверьте корневой тип один раз, чтобы легко понять, почему typeof
быстрее, чем instanceof
typeof: согласно документации MDN typeof - это унарный оператор, который возвращает строку, указывающую тип неоцененного операнда.
В случае строковых примитивов и строковых объектов typeof возвращает следующее:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
typeof a; --> returns 'string'
typeof b; --> returns 'object'
instanceof: бинарный оператор, принимающий объект и конструктор. Он возвращает логическое значение, указывающее, есть ли у объекта данный конструктор в цепочке прототипов.
При применении к экземплярам строки выше и по сравнению со строкой он ведет себя следующим образом:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
a instanceof String; --> returns false
b instanceof String; --> returns true
Ссылка: https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/
Исходя из строгого OO воспитания, я бы пошел на
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
вы можете получить тип предоставленного чего-нибудь
имея в виду производительность, вам лучше использовать typeof с типичным оборудованием, если вы создаете скрипт с циклом из 10 миллионов итераций, инструкция: typeof str == 'string' займет 9 мс, а 'string' instanceof String займет 19 мс
Конечно, имеет значение ........!
Давайте рассмотрим это на примерах. В нашем примере мы объявим функцию двумя разными способами.
Мы будем использовать как function declaration
, так и Конструктор функций. Мы рассмотрим, как typeof
и instanceof
ведут себя в этих двух разных сценариях.
Создание функции с помощью объявления функции:
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
Возможное объяснение такого разного результата состоит в том, что, когда мы объявили функцию, typeof
может понять, что это функция. Потому что typeof
проверяет, является ли выражение, для которого typeof операция on, в нашем случае MyFunc
реализована Метод вызова или нет. Если он реализует метод Call
, это функция. В противном случае - нет. Для уточнения проверьте спецификация ecmascript для typeof.
Создание функции с помощью конструктора функций:
var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used
typeof MyFunc2 == 'function' // true
MyFunc2 instanceof Function // true
Здесь typeof
утверждает, что MyFunc2
является функцией, а также оператором instanceof
. Мы уже знаем typeof
, проверяем, < strong> MyFunc2
реализовал метод Call
или нет. Поскольку MyFunc2
является функцией и реализует метод call
, вот как typeof
знает, что это функция. С другой стороны, мы использовали function constructor
для создания MyFunc2
, он становится экземпляром Function constructor
. Вот почему instanceof
также преобразуется в true
.
Что безопаснее использовать?
Как мы видим, в обоих случаях оператор typeof
может успешно утверждать, что здесь мы имеем дело с функцией, это более безопасно, чем instanceof
. instanceof
завершится ошибкой в случае function declaration
, поскольку function declarations
не является экземпляром Function constructor
.
Рекомендации:
Как Гэри Рафферти < / em>. Лучше всего использовать как typeof, так и instanceof вместе.
function isFunction(functionItem) {
return typeof(functionItem) == 'function' || functionItem instanceof Function;
}
isFunction(MyFunc) // invoke it by passing our test function as parameter
Чтобы быть очень точным, следует использовать instanceof, когда значение создается с помощью конструктора (обычно настраиваемые типы), например,
var d = new String("abc")
тогда как typeof для проверки значений, созданных только присваиваниями, например,
var d = "abc"
Согласно документации MDN о typeof, объекты экземпляры, созданные с помощью ключевого слова new, имеют тип 'object':
typeof 'bla' === 'string';
// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
Хотя документация по instanceof указывает, что:
const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true
Итак, если кто-то хочет проверить, например, что что-то является строкой, независимо от того, как она была создана, самым безопасным подходом было бы использование instanceof
.
Object.prototype.toString
ecma-international .org / ecma-262 / 6.0 / - person rab   schedule 28.06.2015.constructor
. - person Muhammad Umer   schedule 02.08.2015