Чтобы прояснить ситуацию, вам нужно знать два факта:
- Оператор instanceof проверяет, присутствует ли свойство прототипа *1007* конструктора где-либо в цепочке прототипов объекта. В большинстве случаев это означает, что объект был создан с помощью этого конструктора или его потомка. Но также и прототип может быть установлен явно методом
Object.setPrototypeOf()
(ECMAScript 2015) или свойством __proto__
(старые браузеры, не рекомендуется). Однако изменение прототипа объекта не рекомендуется из-за проблем с производительностью.
Таким образом instanceof применим только к объектам. В большинстве случаев вы не используете конструкторы для создания строк или чисел. Вы можете. Но вы почти никогда не делаете.
Также instanceof не может проверить, какой именно конструктор использовался для создания объекта, но вернет true, даже если объект является производным от класса, который проверяется. В большинстве случаев это желаемое поведение, но иногда это не так. Так что вам нужно держать это в уме.
Другая проблема заключается в том, что разные области имеют разные среды выполнения. Это означает, что они имеют разные встроенные модули (разные глобальные объекты, разные конструкторы и т. Д.). Это может привести к неожиданным результатам.
Например, [] instanceof window.frames[0].Array
вернет false
, потому что Array.prototype !== window.frames[0].Array
и массивы наследуют от первого.
Кроме того, его нельзя использовать для неопределенного значения, потому что у него нет прототипа.
- Оператор typeof проверяет, принадлежит ли значение одному из шести основных типов : " число ", " строка ", " логическое"," объект"," функция"или" undefined". Где строка «объект» принадлежит всем объектам (кроме функций, которые являются объектами, но имеют собственное значение в операторе typeof), а также «нулевым» значением и массивами (для «нулевого» это ошибка, но эта ошибка очень старая так что стало стандартом). Он не зависит от конструкторов и может использоваться, даже если значение не определено. Но это не дает никаких подробностей об объектах. Так что, если вам это нужно, перейдите к 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: ( Символ , typeof ).