Оператор instanceof
мурасты эске алуу менен объекттин көрсөтүлгөн класска таандык экендигин текшерүүгө мүмкүндүк берет.
Мындай текшерүү көп учурларда талап кылынышы мүмкүн. Бул жерде биз аргументтерди түрүнө жараша ар кандай чечмелеген полиморфтук функцияны түзүү үчүн колдонобуз.
instanceof оператор
Синтаксис:
@A@obj instanceof Class@A@
Оператор класска таандык болсо true
же класстан мураска калса кайтып келет.obj
Class
Мисалы:
@A@class Rabbit {}
let rabbit = new Rabbit();
// это объект класса Rabbit?
alert( rabbit instanceof Rabbit ); // true@A@
Ал ошондой эле конструктор функциялары менен иштейт:
@A@// вместо класса
function Rabbit() {}
alert( new Rabbit() instanceof Rabbit ); // true@A@
…Жана камтылган класстар үчүн Array
:
@A@let arr = [1, 2, 3];
alert( arr instanceof Array ); // true
alert( arr instanceof Object ); // true@A@
Сураныч, бул arr
класска таандык экенин эске алыңыз Object
, анткени Array
ал класстан мураска алат Object
.
Адатта, оператор instanceof
текшерүү үчүн прототиби чынжыр аркылуу карайт. Бирок бул жүрүм-турумду статикалык ыкма менен өзгөртүүгө болот Symbol.hasInstance
.
Алгоритм obj instanceof Class
төмөнкүдөй иштейт:
-
Эгерде статикалык ыкма бар болсо
Symbol.hasInstance
, анда аны чакырыңыз:Class[Symbol.hasInstance](obj)
.true
Бул же , же кайтарылышы керекfalse
, ушуну менен бүттү. Бул жөн гана кол менен орнотуу мүмкүнчүлүгүinstanceof
.Мисал:
@A@// проверка 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)@A@
-
Көпчүлүк класстарда жок
Symbol.hasInstance
.Class.prototype
Бул учурда стандарттык логика колдонулат: анын прототип чынжырындагы прототиптердин бирине барабар экендиги текшерилетobj
.Башка сөз менен айтканда, ал салыштырат:
@A@obj.__proto__ === Class.prototype? obj.__proto__.__proto__ === Class.prototype? obj.__proto__.__proto__.__proto__ === Class.prototype? ... // если какой-то из ответов true - возвратить true // если дошли до конца цепочки - false@A@
Жогорудагы мисалда
rabbit.__proto__ === Rabbit.prototype
, натыйжа ошол замат алынат.Мурастык учурда дал келүү экинчи этапта болот:
@A@class Animal {} class Rabbit extends Animal {} let rabbit = new Rabbit(); alert(rabbit instanceof Animal); // true // rabbit.__proto__ === Animal.prototype (нет совпадения) // rabbit.__proto__.__proto__ === Animal.prototype (совпадение!)@A@
Бул жерде анын кантип rabbit instanceof Animal
салыштырылат Animal.prototype
:
Айтмакчы, objA.isPrototypeOf(objB) ыкмасы бар , ал true
объект objA
объекттин прототипинин чынжырында бир жерде болсо, кайтарып берет objB
. Ошентип, obj instanceof Class
аны кайра деп айтууга болот Class.prototype.isPrototypeOf(obj)
.
Бул күлкүлүү, бирок конструктор өзү Class
валидация процессине катышпайт! Прототип чынжыр гана маанилүү Class.prototype
.
prototype
Бул объект түзүлгөндөн кийин мүлктү өзгөртүүдө кызыктуу кесепеттерге алып келиши мүмкүн .
Мисалы, бул жерде:
@A@function Rabbit() {}
let rabbit = new Rabbit();
// заменяем прототип
Rabbit.prototype = {};
// ...больше не rabbit!
alert( rabbit instanceof Rabbit ); // false@A
Бонус: Object.prototype.toString түрүн кайтарат
Кадимки объекттер төмөнкүдөй сапка айландырылаарын билебиз [object Object]
:
@A@let obj = {};
alert(obj); // [object Object]
alert(obj.toString()); // то же самое@A@
Бул ыкманы ишке ашыруу кандай иштейт toString
. Бирок toString
ыкманы алда канча күчтүү кылган жашыруун өзгөчөлүктөр бар. Биз аны кеңейтилген версия typeof
жана альтернатива катары колдоно алабыз instanceof
.
Кызык угулат? Бул чыныгы. Мистиканы жок кылалы.
Спецификацияга ылайык , орнотулган ыкма toString
объекттен карызга алынышы мүмкүн жана башка баалуулуктардын контекстинде чакырылышы мүмкүн. Ал эми натыйжа бул баалуулуктун түрүнө жараша болот.
- Сан үчүн бул болмок
[object Number]
- Буль үчүн бул болмок
[object Boolean]
- үчүн
null
:[object Null]
- үчүн
undefined
:[object Undefined]
- Массивдер үчүн:
[object Array]
- …жана башкалар. (Жүрүм-турум ыңгайлаштырылган).
демонстрация кылалы:
@A@// скопируем метод toString в переменную для удобства
let objectToString = Object.prototype.toString;
// какой это тип?
let arr = [];
alert( objectToString.call(arr) ); // [object Array]@A@
Мисалда биз контекстте функцияны аткаруу үчүн Декораторлор жана Чалууларды багыттоо, чалуу/колдонуу бөлүмүндө сүрөттөлгөндөй call колдондук .objectToString
this=arr
Ички ыкманын алгоритми toString
чалуу контекстин талдап this
, тиешелүү натыйжаны берет. Көбүрөөк мисалдар:
@A@let s = Object.prototype.toString;
alert( s.call(123) ); // [object Number]
alert( s.call(null) ); // [object Null]
alert( s.call(alert) ); // [object Function]@A@
Symbol.toStringTag
Объекттин методунун жүрүм-турумун toString
объекттин атайын касиетин колдонуу менен ыңгайлаштырууга болот Symbol.toStringTag
.
Мисалы:
@A@let user = {
[Symbol.toStringTag]: "User"
};
alert( {}.toString.call(user) ); // [object User]@A
Көпчүлүк айлана-чөйрөгө тиешелүү объекттер бул касиетке ээ. Бул жерде кээ бир браузер мисалдары:
@A@// 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]@A@
Symbol.toStringTag
Көрүнүп тургандай, натыйжада оролгон маани (эгер бар болсо) [object ...]
.
Жыйынтыгында "стероиддик типтеги тип" болуп саналат, ал жөн гана примитивдүү маалымат түрлөрү менен иштебестен, орнотулган объекттер менен да иштейт жана ал тургай, ыңгайлаштырылышы мүмкүн.
Типти сап катары алгыбыз келгенде, анын {}.toString.call
ордуна орнотулган объекттер үчүн колдонсо болот , жөн гана текшерүү эмес.instanceof
Бардыгы
Келгиле, биз биле турган текшерүү ыкмаларын кыскача карап көрөлү:
иштөө үчүн | кайтып келет | |
---|---|---|
typeof |
примитивдер | линия |
{}.toString |
примитивдер, орнотулган объекттер, объектилер мененSymbol.toStringTag |
линия |
instanceof |
объектилер | чын/жалган |
Көрүнүп тургандай, техникалык жактан {}.toString
караганда typeof
.
instanceof
Биз класс иерархиялары менен иштегенде жана мурасты эске алуу менен текшерүүлөрдү жүргүзгүбүз келгенде оператор эң сонун тандоо.
Tasks
Эмне үчүн instanceof
төмөндөгү мисал кайтып келет true
? a
колдонуу менен жаралбаганын көрүп жатабыз B()
.
@A@function A() {}
function B() {}
A.prototype = B.prototype = {};
let a = new A();
alert( a instanceof B ); // true@A@