iT邦幫忙

0

Javascript 進階 7-1 屬性特徵是什麼?

  • 分享至 

  • xImage
  •  

這章要來探討物件的屬性

前幾個章節有針對物件的原形、物件的本身還有函式做了一些解析。

那麼就由這章來解析物件屬性的特徵,也會解釋原生的原形以及我們自己定義的原形有甚麼不一樣的地方喔!

以及框架是如何利用物件屬性的特徵來開發出特別的功能!

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

如上,印出來之後可以得到下面的結果

https://ithelp.ithome.com.tw/upload/images/20200423/20121770ZCympxHgsg.png

就可以看到 person 這個物件裡面的屬性 a、b、c以及對應的值,還有物件的原形連結到哪裡。

我們都知道,修改物件裡面屬性的值可以是 person.a = 4 或是 person['a'] = 4,這兩種方法都可以。

那麼今天就要教大家另外一種進階的方法,叫做 Object.defineProperty

這個方法除了可以調整屬性的值(value)之外,還可以調整屬性的特徵喔!

而上述的兩種方法都只能調整屬性的其中一個特徵,也就是屬性對應的值(value)。

讓我們接著看~屬性到底有那些特徵的?

  1. 值(value) => 對應的值是甚麼
  2. 可否寫入(writable) => 可否進行屬性質的修改
  3. 可否被刪除(configurable) => 可否可以用 delete 刪除屬性
  4. 可否被列舉(enumerable) => 可否利用 for...in 迴圈 將物件屬性列舉出來,可以限制特定的屬性是否被列舉出來

那我們就實際來看看要怎麼運用 Object.defineProperty!


Object.defineProperty(物件的變數,或是物件本人, 要修改的屬性名稱(字串), {
    writable: 布林值,
    configurable: 布林值,
    value: 要修改或是賦予甚麼值,
    enumerable: 布林值
});

Object.defineProperty(person, 'a', {
    writable: true,
    configurable: true,
    value: 4,
    enumerable: true
});

也不一定每次每個屬性特徵都要列出來,也可以只修改一種

Object.defineProperty(person, 'a', {
    configurable: false,
});

那我們實際來操作看看

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: true,
    configurable: true,
    value: 4,
    enumerable: true
});

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770GFhnoC3jhn.png

我們會發現,雖然一開始 a 的值還是 1 ,但是展開以後還是4,所以他會顯示已經變化過後的值。

那我們再來修改其他的屬性看看!

Object.defineProperty(person, 'a', {
    configurable: false,
});

那我們實際來操作看看

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

console.log(person);

我們把 writable 改成 false,代表我們沒有辦法再重新修改 a 屬性的 value 。

https://ithelp.ithome.com.tw/upload/images/20200423/2012177099mjSbflg3.png

所以我們利用 Object.defineProperty 把 a 的屬性改成 4 之後,並且把 writable 改成 false。

後面的 person.a = 5; 就沒辦法再進行修改的動作了!

但其實這樣的狀況會是一個靜默的錯誤喔!

也就是在非嚴格模式下(Sloppy mode),不會顯示錯誤紅字,但是如果切換到嚴格模式的話,就會有錯誤訊息產生。

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

(function () {
    'use strict';
    person.a = 5;
})();

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770UOjvt74iXL.png

同時也會導致最後面的 console.log 不會執行喔!

所以在嚴格模式的時候要特別注意。

那接著我們針對 b 的屬性來試試看不同的屬性操作

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

// (function () {
//     'use strict';
//     person.a = 5;
// })();

Object.defineProperty(person, 'b', {
    configurable: false,
});

delete person.a;
delete person.b;

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770aHHgcjFSmM.png

這邊有看到嗎? 在我設定 b 的 configurable 屬性為 false 後,b的屬性就無法被 delete 語法給刪除,但a就成功被刪除嚕~!

那介紹最後一個 enumerable 的屬性套用在屬性 c 身上,並且我們先不刪除 a 屬性,透過for in 的迴圈顯示物件person的屬性名稱:

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

// (function () {
//     'use strict';
//     person.a = 5;
// })();

Object.defineProperty(person, 'b', {
    configurable: false,
});

// delete person.a;
delete person.b;

// Object.defineProperty(person, 'c', {
//     enumerable: false,
// });

for (var key in person) {
    console.log('列舉: ' + key);
}

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770ks8aWW2Nkn.png

最後我們再把註解拿掉

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

// (function () {
//     'use strict';
//     person.a = 5;
// })();

Object.defineProperty(person, 'b', {
    configurable: false,
});

delete person.a;
delete person.b;

Object.defineProperty(person, 'c', {
    enumerable: false,
});

for (var key in person) {
    console.log('列舉: ' + key);
}

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770jSZR5TpbTo.png

你就可以看到, a 因為被刪掉了無法被列舉,b 可以被列舉但不能寫入,c 還在但不能被列舉。

所以被列舉出來的只有 b 屬性。

以上就是關於Object.defineProperty的用法,以及4個屬性特徵的介紹!

那麼除了修改以外,其實Object.defineProperty也可以做到新增的動作喔!

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

// (function () {
//     'use strict';
//     person.a = 5;
// })();

Object.defineProperty(person, 'b', {
    configurable: false,
});

delete person.a;
delete person.b;

Object.defineProperty(person, 'c', {
    enumerable: false,
});

for (var key in person) {
    console.log('列舉: ' + key);
}

Object.defineProperty(person, 'd', {
    writable: false,
    value: {},
});

person.d = 6;

console.log(person);

在這邊我們新增了屬性 'd' 到 person這個物件裡面,並且給予不可寫入的特徵,他的值我們給予空物件。

當然 person.d = 6; 就又會是一個 靜默錯誤 並且不能夠進行修改。

但是當我們今天是針對它裡面的值做額外的設定的話,還是有辦法賦予到內層物件的值喔!

var person = {
    a: 1,
    b: 2,
    c: 3
};

console.log(person);

Object.defineProperty(person, 'a', {
    writable: false,
    configurable: true,
    value: 4,
    enumerable: true
});

person.a = 5;

// (function () {
//     'use strict';
//     person.a = 5;
// })();

Object.defineProperty(person, 'b', {
    configurable: false,
});

delete person.a;
delete person.b;

Object.defineProperty(person, 'c', {
    enumerable: false,
});

for (var key in person) {
    console.log('列舉: ' + key);
}

Object.defineProperty(person, 'd', {
    writable: false,
    value: {},
});

person.d = 6;

person.d.a = 6;

console.log(person);

https://ithelp.ithome.com.tw/upload/images/20200423/20121770eIbukBeQ3y.png

這也是特別要注意的點,就是以上這4個物件的特徵,都是屬於淺層的控制,深層的控制則需要另外再進行設定喔!

最後在介紹,因為剛剛我們都是一個一個屬性設定,有些人會覺得這樣很麻煩,我設定一個屬性就要寫一長串,這裡就要介紹同時設定很多屬性的方法,那就是Object.defineProperties!

用這個方法就可以同時設定很多的屬性嚕!

Object.defineProperties(物件變數或物件本人, {
    物件屬性名稱1: {
        特徵1: xx
        特徵2: xx
        特徵3: xx
        特徵4: xx

    },
    物件屬性名稱2: {
        特徵1: xx
        特徵2: xx
        特徵3: xx
        特徵4: xx

    },...
});

Object.defineProperties(person, {
    a: {
        writable: false,
        configurable: true,
        value: 4,
        enumerable: true
    },
    b: {
        configurable: false,
    },
    c: {
        enumerable: false,
    },
    d : {
        writable: false,
        value: {}
    }
});

下面的就是依照這篇文章剛剛練習的內容一次進行設定的寫法,大家也可以試試看設定不同的屬性喔!

那麼沒問題的話就往下一篇文章邁進~汪汪!


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言