Что такое оператор instanceof в JavaScript?
на instanceof
ключевое слово в JavaScript может быть довольно запутанным, когда он впервые столкнулся с, как люди склонны думать, что JavaScript не является объектно-ориентированным языком программирования.
- что это?
- какие проблемы он решает?
- когда это уместно, а когда нет?
10 ответов
instanceof
операнд левой стороны (LHS) является фактическим объектом, тестируемым на операнд правой стороны (RHS), который является фактическим конструктором класса. Основное определение:
Checks the current object and returns true if the object
is of the specified object type.
вот некоторые примеры и вот пример, взятый непосредственно из сайт разработчика Mozilla:
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)
одна вещь стоит упомянуть instanceof
возвращает true, если объект наследует от прототип класса:
var p = new Person("Jon");
p instanceof Person
что это p instanceof Person
- это верно, поскольку p
наследует от Person.prototype
.
по запросу OP
я добавил небольшой пример с некоторых пример кода и объяснение.
когда вы объявляете переменную, вы даете ему определенного типа.
например:
int i;
float f;
Customer c;
выше показаны некоторые переменные, а именно i
, f
и c
. Типы integer
, float
и определенный пользователем Customer
тип данных. Такие типы, как выше, могут быть для любого языка, а не только JavaScript. Однако с помощью JavaScript при объявлении переменной вы явно не определяете тип,var x
, x может быть номером / строкой / пользовательским типом данных. Ну и что!--5--> проверяет ли он объект, чтобы увидеть, имеет ли он тип, указанный выше, принимая Customer
объект мы могли бы сделать:
var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!
выше мы видели, что c
был объявлен с типом Customer
. Мы обновили его и проверили, имеет ли он тип Customer
или нет. Конечно, он возвращает true. Тогда все еще используя Customer
объект мы проверяем, если это String
. Нет, определенно не String
мы обновляемых в Customer
объект не
есть важный аспект instanceof, который, похоже, не охватывается ни одним из комментариев до сих пор: наследование. Переменная, оцениваемая с помощью instanceof, может возвращать true для нескольких "типов" из-за прототипного наследования.
например, давайте определим тип и подтип:
function Foo(){ //a Foo constructor
//assign some props
return this;
}
function SubFoo(){ //a SubFoo constructor
Foo.call( this ); //inherit static props
//assign some new props
return this;
}
SubFoo.prototype = new Foo(); // Inherit prototype
теперь, когда у нас есть несколько "классов", давайте сделаем несколько экземпляров и узнаем, что они являются экземплярами:
var
foo = new Foo()
, subfoo = new SubFoo()
;
alert(
"Q: Is foo an instance of Foo? "
+ "A: " + ( foo instanceof Foo )
); // -> true
alert(
"Q: Is foo an instance of SubFoo? "
+ "A: " + ( foo instanceof SubFoo )
); // -> false
alert(
"Q: Is subfoo an instance of Foo? "
+ "A: " + ( subfoo instanceof Foo )
); // -> true
alert(
"Q: Is subfoo an instance of SubFoo? "
+ "A: " + ( subfoo instanceof SubFoo )
); // -> true
alert(
"Q: Is subfoo an instance of Object? "
+ "A: " + ( subfoo instanceof Object )
); // -> true
видишь последнюю строчку? Все "новые" вызовы функции возвращают объект, который наследуется от объекта. Это справедливо даже при использовании стенографии создания объектов:
alert(
"Q: Is {} an instance of Object? "
+ "A: " + ( {} instanceof Object )
); // -> true
а как насчет самих определений "класса"? Что это за примеры?
alert(
"Q: Is Foo an instance of Object? "
+ "A:" + ( Foo instanceof Object)
); // -> true
alert(
"Q: Is Foo an instance of Function? "
+ "A:" + ( Foo instanceof Function)
); // -> true
Я чувствую, что понимание того, что любой объект может быть экземпляром нескольких типов, важно, так как вы мой (неправильно) предполагаете, что вы могли бы различать, скажем, и объект и функцию с помощью instanceof
. Как это последнее пример наглядно показывает функцию и объект.
это также важно, если вы используете какие-либо шаблоны наследования и хотите подтвердить потомство объекта методами, отличными от duck-typing.
надеюсь, что это поможет кому-нибудь исследовать instanceof
.
другие ответы здесь верны, но они не попадают в как instanceof
на самом деле работает, что может представлять интерес для некоторых языковых юристов.
каждый объект в JavaScript имеет прототип, доступный через __proto__
собственность. Функции также имеют prototype
свойство, которое является начальным __proto__
для любых объектов, созданных ими. При создании функции ей присваивается уникальный объект для prototype
. The instanceof
оператор использует эту уникальность, чтобы дать вам ответ. Вот что!--2--> может выглядеть, если вы написали его как функцию.
function instance_of(V, F) {
var O = F.prototype;
V = V.__proto__;
while (true) {
if (V === null)
return false;
if (O === V)
return true;
V = V.__proto__;
}
}
это в основном перефразирование ECMA-262 edition 5.1 (также известный как ES5), раздел 15.3.5.3.
обратите внимание, что вы можете переназначить любой объект функции prototype
свойство, и вы можете переназначить объект __proto__
свойство после его создания. Это даст вам некоторые интересные результаты:
function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();
f instanceof F; // returns true
f instanceof G; // returns true
g instanceof F; // returns true
g instanceof G; // returns true
F.prototype = {};
f instanceof F; // returns false
g.__proto__ = {};
g instanceof G; // returns false
Я думаю, стоит отметить, что instanceof определяется использованием ключевого слова " new " при объявлении объекта. В примере из JonH;
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
что он не сказал;
var color1 = String("green");
color1 instanceof String; // returns false
указание " new " фактически скопировало конечное состояние функции строкового конструктора в color1 var, а не просто установило его в возвращаемое значение. Я думаю, что это лучше показывает, что делает новое ключевое слово;
function Test(name){
this.test = function(){
return 'This will only work through the "new" keyword.';
}
return name;
}
var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.
var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'
использование " new " присваивает значение "это" внутри функции объявленному var, не используя его, присваивает вместо этого возвращаемое значение.
и вы можете использовать его для обработки ошибок и отладка, как это:
try{
somefunction();
}
catch(error){
if (error instanceof TypeError) {
// Handle type Error
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle all other error types
}
}
//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
this.numWheels = numWheels;
}
//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);
на вопрос "когда это уместно, а когда нет?"мои 2 цента:
instanceof
редко полезно в производственном коде, но полезно в тестах, где вы хотите утверждать, что ваш код возвращает / создает объекты правильных типов. Будучи явным о видах объектов, которые ваш код возвращает / создает, ваши тесты становятся более мощным инструментом для понимания и документирования вашего кода.
instanceof
- это просто синтаксический сахар для isPrototypeOf
:
function Ctor() {}
var o = new Ctor();
o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true
o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent
instanceof
просто зависит от прототипа конструктора объекта.
конструктор-это обычная функция. Строго говоря, это объект функции, так как все является объектом в Javascript. И этот объект функции имеет прототип, потому что каждая функция имеет прототип.
прототип-это обычный объект, который находится в цепочке прототипов другого объекта. Это означает, что пребывание в цепочке прототипов другого объекта делает объект прототипом:
function f() {} // ordinary function
var o = {}, // ordinary object
p;
f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now
o.isPrototypeOf(p); // true
p instanceof f; // true
The instanceof
оператор следует избегать, потому что он подделывает классы, которые не существуют в Javascript. Несмотря на class
ключевое слово не в ES2015 либо, так как class
снова просто синтаксический сахар для...но это уже другая история.
что это?
Javascript-это прототипный язык, который означает, что он использует прототипы для "наследования". the instanceof
оператор проверяет, является ли функция конструктора prototype
propertype присутствует в __proto__
цепи объекта. Это означает, что он будет делать следующее (предполагая, что testObj является объектом функции):
obj instanceof testObj;
- Проверьте, равен ли прототип объекта прототипу конструктора:
obj.__proto__ === testObj.prototype
>> если этот istrue
instanceof
вернутсяtrue
. - поднимется вверх по цепи прототипа. Например:
obj.__proto__.__proto__ === testObj.prototype
>> если этоtrue
instanceof
вернутсяtrue
. - повторит Шаг 2, пока не будет проверен полный прототип объекта. Если нигде в цепочке прототипов объекта не сопоставляется с
testObj.prototype
затемinstanceof
оператор вернетfalse
.
пример:
function Person(name) {
this.name = name;
}
var me = new Person('Willem');
console.log(me instanceof Person); // true
// because: me.__proto__ === Person.prototype // evaluates true
console.log(me instanceof Object); // true
// because: me.__proto__.__proto__ === Object.prototype // evaluates true
console.log(me instanceof Array); // false
// because: Array is nowhere on the prototype chain
что проблемы это решает?
он решил проблему удобной проверки того, является ли объект производным от определенного прототипа. Например, когда функция получает объект, который может иметь различные прототипы. Затем, перед использованием методов из цепочки прототипов, мы можем использовать instanceof
оператор, чтобы проверить, находятся ли эти методы на объекте.
пример:
function Person1 (name) {
this.name = name;
}
function Person2 (name) {
this.name = name;
}
Person1.prototype.talkP1 = function () {
console.log('Person 1 talking');
}
Person2.prototype.talkP2 = function () {
console.log('Person 2 talking');
}
function talk (person) {
if (person instanceof Person1) {
person.talkP1();
}
if (person instanceof Person2) {
person.talkP2();
}
}
const pers1 = new Person1 ('p1');
const pers2 = new Person2 ('p2');
talk(pers1);
talk(pers2);
здесь
Я только что нашел реальное приложение и теперь буду использовать его чаще, я думаю.
если вы используете события jQuery, иногда вы хотите написать более общую функцию, которая также может быть вызвана напрямую (без события). Вы можете использовать instanceof
чтобы проверить, является ли первый параметр вашей функции экземпляром jQuery.Event
и реагировать соответствующим образом.
var myFunction = function (el) {
if (el instanceof $.Event)
// event specific code
else
// generic code
};
$('button').click(recalc); // Will execute event specific code
recalc('myParameter'); // Will execute generic code
в моем случае функция, необходимая для вычисления чего-то либо для всех (через событие щелчка по кнопке), либо только для одного конкретный элемент. Код, который я использовал:
var recalc = function (el) {
el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
// calculate...
};