В чем разница между typeof и instanceof и когда следует использовать один по сравнению с другим?

В моем конкретном случае:

callback instanceof Function

or

typeof callback == "function"

это вообще имеет значение, какая разница?

Дополнительный ресурс:

JavaScript-Garden typeof vs instanceof


person farinspace    schedule 22.05.2009    source источник
comment
Я нашел свой ответ здесь как простое в использовании решение.   -  person CrandellWS    schedule 27.04.2014
comment
Есть еще один способ проверить тип с помощью Object.prototype.toString ecma-international .org / ecma-262 / 6.0 /   -  person rab    schedule 28.06.2015
comment
просто используйте вместо этого свойство .constructor.   -  person Muhammad Umer    schedule 02.08.2015
comment
Если вас интересует производительность, см. Мой ответ ниже. typeof работает быстрее там, где применимы оба (а именно, объекты).   -  person Martin Peter    schedule 28.08.2015


Ответы (25)


Используйте 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
person Szymon Wygnański    schedule 08.07.2011
comment
Этот ответ проясняет, почему instaceof не следует использовать для примитивных типов. Совершенно очевидно, что у вас нет выбора, когда дело доходит до настраиваемых типов, а также преимуществ для «объектных» типов. Но что заставляет функции объединяться с простыми встроенными типами? Мне кажется странным, как функция ведет себя как объект, но ее тип - это «функция», что делает возможным использование «typeof». Но почему вы отговариваете от этого instanceof? - person Assimilater; 29.07.2014
comment
Не уверен, есть ли адекватный ответ @Assimilater. Факт в том, что typeof последовательно сообщает вам, является ли что-то функцией или нет. Однако я не могу придумать примеров, когда instanceof дал бы вам неправильный ответ. - person froginvasion; 30.07.2014
comment
@Assimilater, вы также можете использовать instanceof с функциями, однако я считаю эти 3 правила очень простыми для запоминания, и да, функции являются исключением :) - person Szymon Wygnański; 03.05.2015
comment
еще одна хитрость - ›'example string' instanceof String; // ложь, но новая строка ('пример строки') instanceof String; //правда - person Luke; 13.11.2015
comment
@Luke вообще плохая идея использовать новую строку вроде этой. который создает строковый объект, а не строковый примитив. см. здесь раздел developer.mozilla.org/en-US / docs / Web / JavaScript / Reference / - person Colin D; 29.01.2016
comment
Use instanceof for complex built in types - это все еще подвержено ошибкам. Лучше использовать ES5 Array.isArray() et al. или рекомендуемые прокладки. - person OrangeDog; 04.05.2016
comment
Вы в основном правы, но, например, строку можно создать как минимум двумя способами: const a = 'string'; const b = new String('string'); Проверка того, что b instanceof String вернет истинное значение typeof, будет работать строковый литерал, instanceof, если он создан с помощью конструктора - person Chris Panayotoff; 23.01.2020
comment
Я все еще в замешательстве. Почему 'example string' instanceof String неверно? Как это не экземпляр строки? - person David Klempfner; 17.05.2021
comment
Неважно. В этом предложении сказано все: instanceof of возвращает true, если объект создан из данного конструктора, и false в противном случае. - levelup.gitconnected.com/ - person David Klempfner; 17.05.2021
comment
@DavidKlempfner это потому, что строка, созданная таким образом: «примерная строка» не является объектом типа String, а является примитивным значением, которое является строкой. Если вы хотите создать строковый объект, вам нужно явно использовать new String('example string') (однако никогда не делайте этого). - person Szymon Wygnański; 18.05.2021

Оба схожи по функциональности, потому что оба возвращают информацию о типе, однако я лично предпочитаю instanceof, потому что он сравнивает фактические типы, а не строки. Сравнение типов менее подвержено человеческим ошибкам и технически быстрее, поскольку сравнивает указатели в памяти, а не сравнивает целые строки.

person Soviut    schedule 22.05.2009
comment
С другой стороны, я думаю, что у этого были бы странные проблемы в настройках с несколькими окнами (любой iframe). - person alamar; 22.05.2009
comment
В этом случае вам придется иметь дело с правильным пространством имен и доменами. - person Soviut; 22.05.2009
comment
есть некоторые ситуации, когда instanceof не будет работать должным образом, а typeof работает хорошо ... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/ - person farinspace; 22.05.2009
comment
instanceof работает с объектами в одном окне. Если вы используете iframe / frame или всплывающие окна, каждый (i) фрейм / окно имеет свой собственный объект функции, и instanceof завершится ошибкой, если вы попытаетесь сравнить объект из другого (i) кадра / окна. typeof будет работать во всех случаях, поскольку он возвращает строковую функцию. - person some; 23.05.2009
comment
jsperf.com/typeof-function-vs-instanceof/3 Я попробовал Chrome и FF3.X, типовой подход быстрее. - person Morgan Cheng; 14.06.2011
comment
Это просто неправда. Они не идентичны. Они не работают во всех одних и тех же ситуациях, особенно в разных виртуальных машинах JavaScript и браузерах. - person Justin Force; 22.11.2011
comment
Я имел в виду, что их функциональность схожа в том, что они оба возвращают информацию о типе, но один возвращает ее как определение типа, а другой возвращает строку. - person Soviut; 24.11.2011
comment
В вашем ответе говорится, что оба они по сути идентичны с точки зрения функциональности. С уважением, это явная ложь. Как указано и объяснено в моем ответе, ни один из вариантов не работает во всех ситуациях, особенно в разных браузерах. Лучше использовать оба с || оператор. - person Justin Force; 30.11.2011
comment
В исходном вопросе ничего не говорилось о браузерах; кто знает, может ОП пишет скрипт на Node. - person Soviut; 21.04.2012
comment
@ soviut - если вы включите реализации ECMAScript в целом, то их сходство будет еще более незначительным. Это очень разные тесты. Если намерение состоит в том, чтобы определить, является ли что-то вызываемой собственной функцией, я бы каждый раз использовал typeof. - person RobG; 24.05.2012
comment
Многие реализации JS (я знаю, что в V8 есть, но не уверен в других реализациях) имеют typeof something === "type" специальный корпус, поэтому реального сравнения строк нет. - person Konrad Borowski; 20.07.2013
comment
Не совсем. Оператор instanceof перемещается вверх по цепочке прототипов в поисках прототипа конструктора [mdn.io/instanceof]. Таким образом, он позволяет проверить, является ли что-то экземпляром подкласса. - person omninonsense; 21.12.2013
comment
Этот ответ неверен, см. Ответ, который я добавил, когда объект создается следующим образом: Object.create(Function), ваш код сломается, если вы используете instanceof вместо typeof. - person vitaly-t; 20.07.2016
comment
@ некоторые правы, что вам нужно обоснование. Упомянутая здесь проблема обрамления - одна из них. Другой заключается в том, что вы можете сломать 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"

Так что на самом деле, на мой взгляд, это будет зависеть от того, какие типы возможных данных вы проверяете.

person Kenneth J    schedule 20.01.2010
comment
+1 также обратите внимание, что instanceof не может сравниваться с примитивными типами, typeof может. - person Tino; 18.03.2011
comment
В Chrome 29.0.1541.0 dev undefined instanceof Object возвращает false и не генерирует исключение. Я не знаю, насколько недавно это изменение, но оно делает instanceof более привлекательным. - person Cypress Frankenfeld; 26.06.2013
comment
undefined instanceof Object не генерирует исключение, потому что, а, undefined определено. Константа существует в пространстве имен. Если переменная не существует (например, из-за опечатки), instanceof выдаст исключение. С другой стороны, использование typeof для несуществующей переменной дает undefined. - person cleong; 28.03.2015

Чтобы прояснить ситуацию, вам нужно знать два факта:

  1. Оператор instanceof проверяет, отображается ли свойство прототипа конструктора где-либо в цепочке прототипов объекта. В большинстве случаев это означает, что объект был создан с помощью этого конструктора или одного из его потомков. Но также прототип может быть явно установлен методом Object.setPrototypeOf() (ECMAScript 2015) или свойством __proto__ (старые браузеры, не рекомендуется). Однако изменять прототип объекта не рекомендуется из-за проблем с производительностью.

Таким образом instanceof применим только к объектам. В большинстве случаев вы не используете конструкторы для создания строк или чисел. Вы можете. Но вы почти никогда этого не делаете.

Также instanceof не может проверить, какой именно конструктор использовался для создания объекта, но вернет true, даже если объект является производным от проверяемого класса. В большинстве случаев это желаемое поведение, но иногда это не так. Так что вам нужно помнить об этом.

Другая проблема заключается в том, что разные области видимости имеют разные среды выполнения. Это означает, что они имеют разные встроенные функции (разные глобальные объекты, разные конструкторы и т. Д.). Это может привести к неожиданным результатам.

Например, [] instanceof window.frames[0].Array вернет false, потому что Array.prototype !== window.frames[0].Array и массивы наследуются от первого.
Кроме того, его нельзя использовать для неопределенного значения, потому что у него нет прототипа.

  1. Оператор typeof проверяет, принадлежит ли значение одному из шести основных типов: «число», «строка», «логическое», «объект», «функция» или «неопределенное». Где строка «объект» принадлежит всем объектам (кроме функций, которые являются объектами, но имеют собственное значение в операторе typeof), а также значение «null» и массивы (для «null» это ошибка, но эта ошибка настолько старая , так что он стал стандартом). Он не полагается на конструкторы и может использоваться, даже если значение не определено. Но он не дает никаких подробностей об объектах. Так что, если вам это нужно, перейдите к instanceof.

Теперь поговорим об одной хитрости. Что, если вы используете конструктор для создания примитивного типа?

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).

person Vladimir Liubimov    schedule 29.01.2016
comment
if an object is created by a given constructor Это неверно. o instanceof C вернет истину, если o наследуется от C.prototype. Вы упомянули об этом позже в своем ответе, но это не очень ясно. - person oyenamit; 13.03.2018
comment
неверно ... из книги: github.com/getify/You-Dont-Know- JS экземпляр Foo; // true Оператор instanceof принимает простой объект в качестве левого операнда и функцию в качестве правого операнда. На вопрос instanceof отвечает: появляется ли когда-либо во всей цепочке [[Prototype]] элемента a объект, на который произвольно указывает Foo.prototype? - person Deen John; 25.04.2018
comment
Я отредактировал ответ, чтобы точнее. Благодарю за комментарии. - person Vladimir Liubimov; 07.08.2018
comment
Также было добавлено объяснение проблемы с упаковкой / распаковкой. - person Vladimir Liubimov; 07.08.2018

Я обнаружил действительно интересное (читаемое как «ужасное») поведение в Safari 5 и Internet Explorer 9. Я с большим успехом использовал это в Chrome и Firefox.

if (typeof this === 'string') {
    doStuffWith(this);
}

Затем я тестирую в IE9, и он вообще не работает. Большой сюрприз. Но в Safari это прерывисто! Итак, я начал отладку и обнаружил, что 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

Так что с этого момента я буду использовать оба.

person Justin Force    schedule 22.11.2011

Другие существенные практические отличия:

// 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
person Amjad Farajallah    schedule 20.01.2011

instanceof также работает, когда callback является подтипом Function, я думаю

person newacct    schedule 22.05.2009

instanceof в Javascript может быть нестабильным - я считаю, что основные фреймворки стараются избегать его использования. Разные окна - это один из способов, которым он может сломаться - я считаю, что иерархия классов также может сбить его с толку.

Есть лучшие способы проверить, является ли объект определенным встроенным типом (обычно это именно то, что вам нужно). Создавайте служебные функции и используйте их:

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}

И так далее.

person levik    schedule 22.05.2009
comment
Если вы не знали: typeof не требует скобок, поскольку это ключевое слово, а не функция. И IMHO вы должны использовать === вместо ==. - person some; 23.05.2009
comment
@some Вы правы насчет typeof, но в этом случае нет необходимости в ===, он нужен только тогда, когда сравниваемое значение может быть равным, не имея того же типа. Здесь не может. - person Nicole; 04.03.2010
comment
@some возвращает ли typeof что-нибудь кроме строки? - person Kenneth J; 21.05.2010
comment
Таким образом, isArray будет неправильным, скажем, для объекта стека с методом push и атрибутом числовой длины. При каких обстоятельствах (instanceof Array) будет неправильным? - person Chris Noe; 09.11.2010
comment
@ChrisNoe Проблема возникает с объектами, которые используются в нескольких фреймах: groups.google.com/forum / #! msg / comp.lang.javascript / XTWYCOwC96I / - person ; 09.12.2013
comment
Вы должны использовать EcmaScript 5 Array.isArray вместо того, чтобы пытаться создать свою собственную. - person Alex Henrie; 20.02.2015

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)
person Omnimike    schedule 03.02.2012

Я бы рекомендовал использовать прототип callback.isFunction().

Они поняли разницу, и вы можете рассчитывать на их причину.

Думаю, в других JS-фреймворках тоже есть такие вещи.

Я полагаю, instanceOf не будет работать с функциями, определенными в других окнах. Их функция отличается от вашей window.Function.

person alamar    schedule 22.05.2009

При проверке функции всегда нужно использовать 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 для проверки функции.

person vitaly-t    schedule 19.07.2016
comment
Я могу возразить, что это typeof неверно - f - это все следующее: Object (объект) и Function (функция). За исключением меня, имеет смысл использовать instanceof, потому что, зная, что это функция, я знаю, что это также объект, поскольку все функции являются объектами в ECMAScript. Обратное неверно - зная из typeof, что f действительно object, я понятия не имею, что это тоже функция. - person amn; 28.05.2018
comment
@amn Для меня это сломанный экземпляр Function. Он получает такие атрибуты, как 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
person Martin Peter    schedule 28.08.2015
comment
typeof subject == array должен возвращать false. Тип субъекта - объект. - person Shardul; 05.02.2017
comment
почему typeof быстрее? Javascript интернирует буквальные строки? - person Gregory Magarshak; 30.04.2017
comment
Причина в следующем: 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)

Типизированный массив instanceof против конструктора - в 1,5 раза быстрее в Chrome 64.0.3282.167 (64-разрядная версия, Windows)

Firefox 59.0b10 (64-разрядная версия, Windows)

Типизированный массив instanceof против конструктора - в 30 раз быстрее в 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)

String / Number typeof vs constructor - в 1,26 раза быстрее в Chrome 64.0.3282.167 (64-разрядная версия, Windows)

Firefox 59.0b10 (64-разрядная версия, Windows)

ПРИМЕЧАНИЕ. Порядок перечисления функций переключается между изображениями!

String / Number typeof против конструктора - на 0,78 раза медленнее в Firefox 59.0b10 (64-разрядная версия, Windows)

person Job    schedule 20.02.2018

Существенная практическая разница:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Не спрашивайте меня, почему.

person Barney    schedule 20.08.2010
comment
Потому что здесь str - это строковый примитив, а не строковый объект. То же самое касается числовых примитивов и логических примитивов, они не являются экземплярами их созданных аналогов, объектов String, Number и Boolean. JavaScript автоматически преобразует эти три примитива в объекты, когда это необходимо (например, используя метод в цепочке прототипов объекта). С другой стороны, instanceof лучше подходит для проверки массивов, так как typeof [] == "object" // true. - person Andy E; 03.10.2010

Используйте instanceof, потому что если вы измените имя класса, вы получите ошибку компилятора.

person Robert    schedule 22.05.2009

не нужно загромождать кучу приведенных выше примеров, просто помните две точки зрения:

  1. typeof var; - унарный оператор, который возвращает исходный тип или корневой тип переменной. так что он будет возвращать примитивные типы (string, number, bigint, boolean, undefined и symbol) или object тип.

  2. в случае объекта более высокого уровня, такого как встроенные объекты (String, Number, Boolean, Array ..) или сложных или настраиваемых объектов, все они относятся к корневому типу object, но тип экземпляра, построенный на их основе, может быть разным (например, ООП концепция наследования классов), здесь a instanceof A - бинарный оператор - вам поможет, он пройдёт по цепочке прототипов, чтобы проверить, появляется ли конструктор правого операнда (A) или нет.

поэтому всякий раз, когда вы хотите проверить «корневой тип» или работать с примитивной переменной - используйте «typeof», иначе используйте «instanceof».

null - это особый случай, который кажется примитивным, но на самом деле это особый случай для объекта. Вместо этого используйте a === null для проверки нуля.

с другой стороны, function также является особым случаем, который является встроенным объектом, но typeof возвращает function

как видите, instanceof должен пройти через цепочку прототипов, а typeof просто проверьте корневой тип один раз, чтобы легко понять, почему typeof быстрее, чем instanceof

person Lam Phan    schedule 25.03.2020

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/

person Sandeep Amarnath    schedule 02.05.2021

Исходя из строгого OO воспитания, я бы пошел на

callback instanceof Function

Строки подвержены либо моей неправильной орфографии, либо другим опечаткам. К тому же я чувствую, что он читается лучше.

person Keplerf1    schedule 22.05.2009

Несмотря на то, что 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
person Suprido    schedule 23.05.2016

Еще один случай: вы можете сопоставить только с instanceof - он возвращает true или false. С typeof вы можете получить тип предоставленного чего-нибудь

person Jarosław Wlazło    schedule 02.06.2016

имея в виду производительность, вам лучше использовать typeof с типичным оборудованием, если вы создаете скрипт с циклом из 10 миллионов итераций, инструкция: typeof str == 'string' займет 9 мс, а 'string' instanceof String займет 19 мс

person Khalid Rafik    schedule 16.09.2017

Конечно, имеет значение ........!

Давайте рассмотрим это на примерах. В нашем примере мы объявим функцию двумя разными способами.

Мы будем использовать как 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
person AL-zami    schedule 04.01.2018
comment
мы будем благодарны за любую конструктивную критику в отношении этого ответа. - person AL-zami; 04.01.2018

Чтобы быть очень точным, следует использовать instanceof, когда значение создается с помощью конструктора (обычно настраиваемые типы), например,

var d = new String("abc")

тогда как typeof для проверки значений, созданных только присваиваниями, например,

var d = "abc"
person Sambhav    schedule 13.12.2019

Согласно документации 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.

person Laszlo Sarvold    schedule 05.05.2020

person    schedule
comment
Что делать, могу ли я получить UA (navigator.userAgent)? - person xgqfrms; 07.09.2016