ÐпеÑаÑÐ¾Ñ instanceof позволÑÐµÑ Ð¿ÑовеÑиÑÑ, пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ Ð»Ð¸ обÑÐµÐºÑ ÑÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð¼Ñ ÐºÐ»Ð°ÑÑÑ, Ñ ÑÑÑÑом наÑледованиÑ.
Ð¢Ð°ÐºÐ°Ñ Ð¿ÑовеÑка Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾ÑÑебоваÑÑÑÑ Ð²Ð¾ Ð¼Ð½Ð¾Ð³Ð¸Ñ ÑлÑÑаÑÑ . ÐдеÑÑ Ð¼Ñ Ð¸ÑполÑзÑем ÐµÑ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ð¼Ð¾ÑÑной ÑÑнкÑии, коÑоÑÐ°Ñ Ð¸Ð½ÑеÑпÑеÑиÑÑÐµÑ Ð°ÑгÑменÑÑ Ð¿Ð¾-ÑÐ°Ð·Ð½Ð¾Ð¼Ñ Ð² завиÑимоÑÑи Ð¾Ñ Ð¸Ñ Ñипа.
ÐпеÑаÑÐ¾Ñ instanceof
СинÑакÑиÑ:
obj instanceof Class
ÐпеÑаÑÐ¾Ñ Ð²ÐµÑнÑÑ true, еÑли obj пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ ÐºÐ»Ð°ÑÑÑ Class или наÑледÑÑÑÐµÐ¼Ñ Ð¾Ñ Ð½ÐµÐ³Ð¾.
ÐапÑимеÑ:
class Rabbit {}
let rabbit = new Rabbit();
// ÑÑо обÑÐµÐºÑ ÐºÐ»Ð°ÑÑа Rabbit?
alert( rabbit instanceof Rabbit ); // true
Также ÑÑо ÑабоÑÐ°ÐµÑ Ñ ÑÑнкÑиÑми-конÑÑÑÑкÑоÑами:
// вмеÑÑо клаÑÑа
function Rabbit() {}
alert( new Rabbit() instanceof Rabbit ); // true
â¦Ð Ð´Ð»Ñ Ð²ÑÑÑоеннÑÑ
клаÑÑов, ÑакиÑ
как Array:
let arr = [1, 2, 3];
alert( arr instanceof Array ); // true
alert( arr instanceof Object ); // true
ÐожалÑйÑÑа, обÑаÑиÑе внимание, ÑÑо arr Ñакже пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ ÐºÐ»Ð°ÑÑÑ Object, поÑÐ¾Ð¼Ñ ÑÑо Array наÑледÑÐµÑ Ð¾Ñ Object.
ÐбÑÑно опеÑаÑÐ¾Ñ instanceof пÑоÑмаÑÑÐ¸Ð²Ð°ÐµÑ Ð´Ð»Ñ Ð¿ÑовеÑки ÑепоÑÐºÑ Ð¿ÑоÑоÑипов. Ðо ÑÑо поведение Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾ пÑи помоÑи ÑÑаÑиÑеÑкого меÑода Symbol.hasInstance.
ÐлгоÑиÑм ÑабоÑÑ obj instanceof Class ÑабоÑÐ°ÐµÑ Ð¿ÑимеÑно Ñак:
-
ÐÑли имееÑÑÑ ÑÑаÑиÑеÑкий меÑод
Symbol.hasInstance, Ñогда вÑзваÑÑ ÐµÐ³Ð¾:Class[Symbol.hasInstance](obj). Ðн должен веÑнÑÑÑ Ð»Ð¸Ð±Ð¾true, либоfalse, и ÑÑо конеÑ. ÐÑо как Ñаз и еÑÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ ÑÑÑной наÑÑÑойкиinstanceof.ÐÑимеÑ:
// пÑовеÑка instanceof бÑÐ´ÐµÑ Ð¿Ð¾Ð»Ð°Ð³Ð°ÑÑ, // ÑÑо вÑÑ Ñо ÑвойÑÑвом canEat - живоÑное Animal class Animal { static [Symbol.hasInstance](obj) { if (obj.canEat) return true; } } let obj = { canEat: true }; alert(obj instanceof Animal); // true: вÑзван Animal[Symbol.hasInstance](obj) -
ÐолÑÑÐ°Ñ ÑаÑÑÑ ÐºÐ»Ð°ÑÑов не Ð¸Ð¼ÐµÐµÑ Ð¼ÐµÑода
Symbol.hasInstance. Ð ÑÑом ÑлÑÑае иÑполÑзÑеÑÑÑ ÑÑандаÑÑÐ½Ð°Ñ Ð»Ð¾Ð³Ð¸ÐºÐ°: пÑовеÑÑеÑÑÑ, Ñавен лиClass.prototypeÐ¾Ð´Ð½Ð¾Ð¼Ñ Ð¸Ð· пÑоÑоÑипов в пÑоÑоÑипной ÑепоÑкеobj.ÐÑÑгими Ñловами, ÑÑавниваеÑÑÑ:
obj.__proto__ === Class.prototype? obj.__proto__.__proto__ === Class.prototype? obj.__proto__.__proto__.__proto__ === Class.prototype? ... // еÑли какой-Ñо из оÑвеÑов true - возвÑаÑиÑÑ true // еÑли доÑли до конÑа ÑепоÑки - falseРпÑимеÑе вÑÑе
rabbit.__proto__ === Rabbit.prototype, Ñак ÑÑо ÑезÑлÑÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑен немедленно.Ð ÑлÑÑае Ñ Ð½Ð°Ñледованием, Ñовпадение бÑÐ´ÐµÑ Ð½Ð° вÑоÑом Ñаге:
class Animal {} class Rabbit extends Animal {} let rabbit = new Rabbit(); alert(rabbit instanceof Animal); // true // rabbit.__proto__ === Animal.prototype (Ð½ÐµÑ ÑовпадениÑ) // rabbit.__proto__.__proto__ === Animal.prototype (Ñовпадение!)
ÐÐ¾Ñ Ð¸Ð»Ð»ÑÑÑÑаÑÐ¸Ñ Ñого как rabbit instanceof Animal ÑÑавниваеÑÑÑ Ñ Animal.prototype:
ÐÑÑаÑи, еÑÑÑ Ð¼ÐµÑод objA.isPrototypeOf(objB), коÑоÑÑй возвÑаÑÐ°ÐµÑ true, еÑли обÑÐµÐºÑ objA еÑÑÑ Ð³Ð´Ðµ-Ñо в пÑоÑоÑипной ÑепоÑке обÑекÑа objB. Так ÑÑо obj instanceof Class можно пеÑеÑÑазиÑоваÑÑ ÐºÐ°Ðº Class.prototype.isPrototypeOf(obj).
Ðабавно, но Ñам конÑÑÑÑкÑÐ¾Ñ Class не ÑÑаÑÑвÑÐµÑ Ð² пÑоÑеÑÑе пÑовеÑки! Ðажна ÑолÑко ÑепоÑка пÑоÑоÑипов Class.prototype.
ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑиводиÑÑ Ðº инÑеÑеÑнÑм поÑледÑÑвиÑм пÑи изменении ÑвойÑÑва prototype поÑле ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑекÑа.
Ðак, напÑимеÑ, ÑÑÑ:
function Rabbit() {}
let rabbit = new Rabbit();
// заменÑем пÑоÑоÑип
Rabbit.prototype = {};
// ...болÑÑе не rabbit!
alert( rabbit instanceof Rabbit ); // false
ÐонÑÑ: Object.prototype.toString возвÑаÑÐ°ÐµÑ Ñип
ÐÑ Ñже знаем, ÑÑо обÑÑнÑе обÑекÑÑ Ð¿ÑеобÑазÑÑÑÑÑ Ðº ÑÑÑоке как [object Object]:
let obj = {};
alert(obj); // [object Object]
alert(obj.toString()); // Ñо же Ñамое
Так ÑабоÑÐ°ÐµÑ ÑеализаÑÐ¸Ñ Ð¼ÐµÑода toString. Ðо Ñ toString имеÑÑÑÑ ÑкÑÑÑÑе возможноÑÑи, коÑоÑÑе делаÑÑ Ð¼ÐµÑод гоÑаздо более моÑнÑм. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ ÐµÐ³Ð¾ как ÑаÑÑиÑеннÑÑ Ð²ÐµÑÑÐ¸Ñ typeof и как алÑÑеÑнаÑÐ¸Ð²Ñ instanceof.
ÐвÑÑÐ¸Ñ ÑÑÑанно? Так и еÑÑÑ. ÐавайÑе Ñазвеем миÑÑикÑ.
СоглаÑно ÑпеÑиÑикаÑии вÑÑÑоеннÑй меÑод toString Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð·Ð°Ð¸Ð¼ÑÑвован Ñ Ð¾Ð±ÑекÑа и вÑзван в конÑекÑÑе лÑбого дÑÑгого знаÑениÑ. Ð ÑезÑлÑÑÐ°Ñ Ð·Ð°Ð²Ð¸ÑÐ¸Ñ Ð¾Ñ Ñипа ÑÑого знаÑениÑ.
- ÐÐ»Ñ ÑиÑла ÑÑо бÑдеÑ
[object Number] - ÐÐ»Ñ Ð±Ñлева Ñипа ÑÑо бÑдеÑ
[object Boolean] - ÐлÑ
null:[object Null] - ÐлÑ
undefined:[object Undefined] - ÐÐ»Ñ Ð¼Ð°ÑÑивов:
[object Array] - â¦Ð¸ Ñ.д. (поведение наÑÑÑаиваеÑÑÑ).
ÐавайÑе пÑодемонÑÑÑиÑÑем:
// ÑкопиÑÑем меÑод toString в пеÑеменнÑÑ Ð´Ð»Ñ ÑдобÑÑва
let objectToString = Object.prototype.toString;
// какой ÑÑо Ñип?
let arr = [];
alert( objectToString.call(arr) ); // [object Array]
РпÑимеÑе Ð¼Ñ Ð¸ÑполÑзовали call, как опиÑано в главе ÐекоÑаÑоÑÑ Ð¸ пеÑеадÑеÑаÑÐ¸Ñ Ð²Ñзова, call/apply, ÑÑÐ¾Ð±Ñ Ð²ÑполниÑÑ ÑÑнкÑÐ¸Ñ objectToString в конÑекÑÑе this=arr.
ÐнÑÑÑи, алгоÑиÑм меÑода toString анализиÑÑÐµÑ ÐºÐ¾Ð½ÑекÑÑ Ð²Ñзова this и возвÑаÑÐ°ÐµÑ ÑооÑвеÑÑÑвÑÑÑий ÑезÑлÑÑаÑ. ÐолÑÑе пÑимеÑов:
let s = Object.prototype.toString;
alert( s.call(123) ); // [object Number]
alert( s.call(null) ); // [object Null]
alert( s.call(alert) ); // [object Function]
Symbol.toStringTag
Ðоведение меÑода обÑекÑов toString можно наÑÑÑаиваÑÑ, иÑполÑзÑÑ ÑпеÑиалÑное ÑвойÑÑво обÑекÑа Symbol.toStringTag.
ÐапÑимеÑ:
let user = {
[Symbol.toStringTag]: "User"
};
alert( {}.toString.call(user) ); // [object User]
Такое ÑвойÑÑво еÑÑÑ Ñ Ð±Ð¾Ð»ÑÑей ÑаÑÑи обÑекÑов, ÑпеÑиÑиÑнÑÑ Ð´Ð»Ñ Ð¾Ð¿ÑеделÑннÑÑ Ð¾ÐºÑÑжений. ÐÐ¾Ñ Ð½ÐµÑколÑко пÑимеÑов Ð´Ð»Ñ Ð±ÑаÑзеÑа:
// toStringTag Ð´Ð»Ñ Ð±ÑаÑзеÑного обÑекÑа и клаÑÑа
alert( window[Symbol.toStringTag]); // window
alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest
alert( {}.toString.call(window) ); // [object Window]
alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest]
Ðак Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе видеÑÑ, ÑезÑлÑÑÐ°Ñ â ÑÑо знаÑение Symbol.toStringTag (еÑли он имееÑÑÑ) обÑÑнÑÑое в [object ...].
РиÑоге Ð¼Ñ Ð¿Ð¾Ð»ÑÑили «typeof на ÑÑеÑÐ¾Ð¸Ð´Ð°Ñ Â», коÑоÑÑй не ÑолÑко ÑабоÑÐ°ÐµÑ Ñ Ð¿ÑимиÑивнÑми Ñипами даннÑÑ , но Ñакже и Ñо вÑÑÑоеннÑми обÑекÑами, и даже Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½Ð°ÑÑÑоен.
Ðожно иÑполÑзоваÑÑ {}.toString.call вмеÑÑо instanceof Ð´Ð»Ñ Ð²ÑÑÑоеннÑÑ
обÑекÑов, когда Ð¼Ñ Ñ
оÑим полÑÑиÑÑ Ñип в виде ÑÑÑоки, а не пÑоÑÑо ÑделаÑÑ Ð¿ÑовеÑкÑ.
ÐÑого
ÐавайÑе обобÑим, какие меÑÐ¾Ð´Ñ Ð´Ð»Ñ Ð¿ÑовеÑки Ñипа Ð¼Ñ Ð·Ð½Ð°ÐµÐ¼:
| ÑабоÑÐ°ÐµÑ Ð´Ð»Ñ | возвÑаÑÐ°ÐµÑ | |
|---|---|---|
typeof |
пÑимиÑивов | ÑÑÑока |
{}.toString |
пÑимиÑивов, вÑÑÑоеннÑÑ
обÑекÑов, обÑекÑов Ñ Symbol.toStringTag |
ÑÑÑока |
instanceof |
обÑекÑов | true/false |
Ðак Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ видеÑÑ, ÑеÑ
ниÑеÑки {}.toString «более пÑодвинÑÑ», Ñем typeof.
РопеÑаÑÐ¾Ñ instanceof â оÑлиÑнÑй вÑбоÑ, когда Ð¼Ñ ÑабоÑаем Ñ Ð¸ÐµÑаÑÑ
ией клаÑÑов и Ñ
оÑим делаÑÑ Ð¿ÑовеÑки Ñ ÑÑÑÑом наÑледованиÑ.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)