Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Почему некорректно работает оператор instanseof? (https://javascript.ru/forum/misc/75056-pochemu-nekorrektno-rabotaet-operator-instanseof.html)

FunnyCat 29.08.2018 17:11

Почему некорректно работает оператор instanseof?
 
Добрый день! Где можно увидеть как досконально работает оператор instanceof.

Вот пример, цепочки прототипов ("иерархия животных"). Несмотря на то, что тип Dog вообще не играет роли для типа Cat, оператор instanceof утверждает, что объект (cat1), созданный с помощью функции-конструктора Cat также является типом Dog??? (Если прототип собаки будет создаваться с помощью прототипа функции-конструктора из цепочки прототипов кота - то есть, например, так: Dog.prototype = Mammal.prototype). Но если же прототипом функции конструктора Dog будет являться конкретный новый объект Mammal (млекопитающее), созданный через оператор new, то есть так: Dog.prototype = new Mammal(), то объект cat1, уже не будет типом Dog. В чём причина??? Как работает этот оператор - instanceof?

var Animal = function(){
      this.run = function(){
        console.log("I am running or swimming...");
      };
    }
    
    var Mammal = function(){
      this.run = function(){
        console.log("I am running!");
      };
      this.voice = function(){
        console.log("...");
      };
    };
    Mammal.prototype = new Animal();
    
    var Cat = function(){
      this.voice = function(){
        console.log("Meow!!!");
      };
      
    };
    Cat.prototype = new Mammal();
    
    var DomesticCat = function(){
      this.height = "80";
      this.weight = "30";
    }
    DomesticCat.prototype = new Cat();
    
    var Dog = function(){
      this.height = "100";
      this.weight = "50";
      this.play_with_cat = function(){
        console.log("I am playing!");
      };
    }
    Dog.prototype = Mammal.prototype;

// если будет использоваться создание объекта через оператор new Mammal(), то выражение (cat1 instanseof Dog)
// результирует в false
    
    var cat1 = new DomesticCat();
    var dog1 = new Dog();
    
    console.log(cat1 instanceof Dog); // true
    console.log(dog1 instanceof Cat); // false

Aetae 29.08.2018 17:24

Возможно тебе поможет эта тема: https://javascript.ru/forum/misc/750...rototipov.html

Но вообще если Dog.prototype = Mammal.prototype, то Dog и Mammal одно и то же для instanceof.

FunnyCat 29.08.2018 17:42

Цитата:

Сообщение от Aetae (Сообщение 493609)
Возможно тебе поможет эта тема: https://javascript.ru/forum/misc/750...rototipov.html

Но вообще если Dog.prototype = Mammal.prototype, то Dog и Mammal одно и то же для instanceof.

Я читал ту ветку форума уже. Тут вопрос немного другой. Почему instanceof так поступает?

Вот что выдаёт консоль: заменяет в цепочке Mammal на Dog? Но я же вывожу объект cat!!! (созданный с помощью оператора new DomesticCat()). С чем связан такой трюк?

DomesticCat {height: "80", weight: "30"}
			height:"80"
			weight:"30"
			__proto__: Cat
				voice: ƒ ()
				__proto__: Dog
					constructor: ƒ ()
					run: ƒ ()
					voice: ƒ ()
					__proto__: Animal
						constructor: ƒ ()
						run: ƒ ()
						__proto__: Object

Aetae 29.08.2018 18:05

Потому что родитель объекта возможно определить только по __proto__. В __proto__ созданного объекта попадает prototype функции его сконструировавшей. Если у двух функций один и тот же prototype, определить какой именно из них он был создан принципиально невозможно.

Dog и Mammal имеют прототипом один и тот же объект(не копию, заметьте, а именно один и тот же, ибо объекты передаются по ссылке), потому невозможно отличить объект созданный Dog от объекта созданного Mammal. Потому new Dog точно также instanceof Mammal, как new Mammal - instanceof Dog.
А поскольку DomesticCat наследник Cat, и Cat наследник Mammal, то DomesticCat instanceof Mammal и, соответственно, instanceof Dog.


Часовой пояс GMT +3, время: 10:45.