Obiekty - instanceof i hasOwnProperty

instanceof

W poprzednich rozdziałach tworzyliśmy dwa typy obiektów - pojdedyncze "nie zrzeszone" oraz te należące do jakiejś grupy - budowane na bazie konstruktora.
Jeżeli byśmy chcieli sprawdzić jakiego "typu" jest dany obiekt, wystarczy użyć operatora instanceof:


    function Animal(name, age) {
        this.name = name;
        this.age = age;
        this.type = 'animal';
    }

    Animal.prototype.eat = function() {
        return this.name + " właśnie je";
    }

    function Dog(name, age) {
        Animal.call(this, name, age);
        this.name = name;
        this.type = "dog";
    }

    Dog.prototype = Object.create(Animal.prototype);
    Dog.prototype.constructor = Dog;

    Dog.prototype.eat = function() {
        const text = Animal.prototype.eat.call(this); //tamta funkcja nie ma parametrów
        return text + " kości";
    }

    Dog.prototype.bark = function() {
        return "Wof! Wof!";
    }

    const dog = new Dog("dog", 8);
    const animal = new Animal("Animal", 10);

    const ob = {
        name : "Marcin"
    }

    console.log(dog instanceof Dog); //true
    console.log(dog instanceof Animal); //true
    console.log(dog instanceof Object); //true
    console.log(animal instanceof Animal); //true
    console.log(animal instanceof Object); //true

    console.log(ob instanceof Dog); //false
    console.log(ob instanceof Animal); //false

Czemu obiekty dog i animal są instancjami Object? Z tego względu, że Animal i Dog dziedziczą po Object. Ale już nasz obiekt literałowy ob nie ma żadnego powiązania z obiektami typu Animal czy Dog więc instanceof zwraca false.

W razie czego gdybyś chciał sprawdzić czy obiekt dog jest typu Dog, wtedy wystarczy spradzić jego konstruktor:


dog.contructor === Dog;

hasOwnProperty

Jeżeli chcemy sprawdzić, czy dana instancja obiektu ma konkretną właściwość lub metodę, użyjemy metody ob.hasOwnProperty(method):


const ob = {
    name : "Marcin",
    print : function() {}
}

console.log(ob.hasOwnProperty("print")); //true
console.log(ob.hasOwnProperty("name")); //true
console.log(ob.hasOwnProperty("surname")); //false

Metoda lub właściwość musi zawierać się w danej instancji:


const MyObj = function(name) {
    this.name = name,
    this.sayName = function() {}
}
MyObj.prototype.print = function() {
    ...
}

console.log(ob.hasOwnProperty("name")); //true
console.log(ob.hasOwnProperty("sayName")); //true
console.log(ob.hasOwnProperty("print")); //false

Do czego to może się przydać?

Przde wszystkim do sprawdzenia, czy dana właściwość istnieje w danej instancji:


const myObj = {
}
console.log(ob['toString']); //pokaże kod funkcji dziedziczonej z prototypu Object

console.log("toString" in myObj); //true
console.log(myObj.hasOwnProperty("toString")); // false

W praktyce bardzo często będziesz robił pętle po obiektach i będziesz chciał mieć pewność, że w takiej pętli nie pokaże się coś spoza danego obiektu:


const MyObj = function() {
    this.data = null;
}
MyObj.prototype.name = "Marcin";
MyObj.prototype.print = function() {
    console.log(this.name);
}

const ob = new MyObj();
ob.data = {
    "2015-10-10" : { name: "Wycieczka za miasto", where: "Puszcza"},
    "2015-11-10" : { name: "Zakupy w markecie", where: "Market"},
    "2015-12-09" : { name: "Sprawy w szkole", where: "Szkola"}
}

for (let i in ob) { //i to kolejne klucze czyli daty
    console.log(ob[i]) //wypisze także "Marcin" i funkcje print
}

for (let i in ob) {
    if (ob.hasOwnProperty(i)) {
        console.log(ob[i]) //wypisze tylko obiekty z właściwości data
    }
}

Ogólnie więc jeżeli będziesz robił pętlę po pobranych danych (np JSON) które są w formie obiektu, zawsze dodawaj sprawdzenie hasOwnProperty:


for (var i in result.data) {
    if (result.data.hasOwnProperty(i)) {
        console.log(result.data[i])
    }
}