iT邦幫忙

1

Javascript 進階 7-3 屬性列舉與原型的關係

這篇文章會結合屬性列舉的特徵以及原型的關係做介紹

function Person () { }

Person.prototype.name = '人類';

var casper = new Person();
casper.a = undefined;

console.log(casper);

首先先來看看上面的程式碼~

我們先撰寫了 Person 的建構函式,並且在這個建構函式的原型上給予 name 的屬性對應到的值是 人類

再來我們宣告 casper 這個變數為 Person 的實體(instance),同時給予 casper a 的屬性,對應的是 undefined 的值。

這時候我們來看看 casper 會印出甚麼。

https://ithelp.ithome.com.tw/upload/images/20200428/20121770wBqZofz5Lx.png

可以看到 a 屬性在 Person 之下,同時 name 屬性在 __proto__ 之下,同時這兩個的屬性顏色都跟其他屬性的方法不一樣,同為較深的紫色。

我們先加入下列的程式碼來看看不同的結果~

console.log(casper.hasOwnProperty('a'));
console.log(casper.hasOwnProperty('b'));
console.log(casper.hasOwnProperty('name'));

https://ithelp.ithome.com.tw/upload/images/20200428/20121770ifOrmcKK8J.png

我們利用 hasOwnProperty 這個方法來查看,該物件是否有我們所要找的屬性。

結果分別是

=> 有 a 屬性,當然,我們剛剛有加。
=> 沒有 b 屬性,因為從頭到尾都沒有。
=> 沒有 name 屬性,因為 name 並不屬於 casper 這個物件的,但是如果要用casper.name的話,還是取的到值。

hasOwnProperty 這個方法就只能找當下的物件屬性,不屬於該物件的屬性的話就會回傳false。

那接下來呢我們就來用列舉的方式看看,會列出那些屬性。

for (var key in casper) {
    console.log(key);
}

https://ithelp.ithome.com.tw/upload/images/20200428/20121770INVWRVyeNo.png

列舉出來的有 a 屬性,當然~

但連 name 也有?為甚麼呢?我們來看看這兩個屬性的特徵:

console.log(Object.getOwnPropertyDescriptor(casper, 'a'));
console.log(Object.getOwnPropertyDescriptor(casper.__proto__, 'name'));

https://ithelp.ithome.com.tw/upload/images/20200428/20121770ZuuyZDwNWk.png

這就跟剛剛的深紫色有關,也就是說深紫色的屬性是我們手動加上去,但其實他屬性的特徵中,enumerable 會顯示為 true。

這個時候,如果我們不想讓 name 的屬性被列舉的話,只要利用 Object.defineProperty 修改就可以嚕~

function Person () { }

Person.prototype.name = '人類';

Object.defineProperty(Person.prototype, 'name', {
    enumerable: false
});

var casper = new Person();
casper.a = undefined;

console.log(casper);

console.log(casper.hasOwnProperty('a'));
console.log(casper.hasOwnProperty('b'));
console.log(casper.hasOwnProperty('name'));

for (var key in casper) {
    console.log(key);
}

console.log(Object.getOwnPropertyDescriptor(casper, 'a'));
console.log(Object.getOwnPropertyDescriptor(casper.__proto__, 'name'));

https://ithelp.ithome.com.tw/upload/images/20200429/20121770j3ahcNhvZl.png

之後就可以發現 name 屬性並沒有出現在列舉的結果中,並且 enumerable 也改成 false 了!

好~到這裡就是我們自己新增的屬性以及原生的屬性有甚麼不同處的介紹~

但是有時候我們並不清楚那些屬性是自訂又沒有設定 enumerable 為 false,同時又必須知道哪些是屬於這個物件的屬性的時候,for in 的迴圈就可以修改成這樣~

for (var key in casper) {
    if (casper.hasOwnProperty(key)) {

    }
}

搭配 hasOwnProperty 的話就可以過濾掉不是屬於該物件的屬性嚕!

如果沒有問題的話就繼續往下一篇文章邁進吧! 汪汪~


尚未有邦友留言

立即登入留言