昨天我們介紹了六大屬性描述器,今天來介紹有哪幾種方式可以定義他們?
其實分為兩種方式:
建立物件的時候定義:
Object.create()
物件已建立完之後定義:
Object.defineProperty()
Object.definedProperties()
Object.create()
的用法:Object.create(proto, propertiesObject)
建立但不定義屬性描述器:
const jade = {
name: "Jade",
age: 28,
school: "TNUA",
greet: function () {
return `here is greet by ${this.name}`;
},
};
const ann = Object.create(jade);
console.log(ann) // {} 所以是空物件
這一步只是讓 ann物件 跟 jade物件的 prototype 綁在一起而已 ,都還沒有設置他的 property ,所以現在ann裡面什麼也沒有,當然會是空物件。
我們再繼續設定下去,並且來看name的屬性描述器是什麼:
ann.name = "ann";
console.log(Object.getOwnPropertyDescriptor(ann, "name"));
// { value: 'ann', writable: true, enumerable: true, configurable: true }
console.log(ann);
// { name: 'ann' }
所以只要我直接用字面宣告的話,屬性描述器就會都是true。
當然這些也都可以在一開始建立時做到。
記得要先大括號因為屬性描述器也算是一個 object
const ann = Object.create(jade, {
name: {
value: "ann",
writable: true,
enumerable: true,
configurable: true
},
age: {
value: 20,
writable: true,
enumerable: true,
configurable: true
},
});
console.log(ann)
//
{ name: 'ann', age: 20 }
可是如果創建時定義只有寫最基本的value的話,其他就會被認定是false。
const ann = Object.create(jade, {
name: {
value: "ann",
},
age: {
value: 20,
},
});
console.log(Object.getOwnPropertyDescriptor(ann, "name"));
//
{
value: 'ann',
writable: false,
enumerable: false,
configurable: false
}
// 全部都是false
所以要定義就全部一起定義。
另外如果想要創建一個沒有物件原型的物件的話,可以把Object.create()的第一個參數放null
,就會是個沒有物件原型的物件了。
一般的則是長這樣,是會擁有Object的prototype的
Object.defineProperty()
定義屬性描述器只有寫value,其他屬性描述沒有特別去寫的預設值都會是 false用法:
Object.defineProperty(obj, prop, descriptor)
建立:
const person = {};
// 沒有寫其他屬性特徵
Object.defineProperty(person, "name", {
value: "Jade",
});
console.log(person); // ! {} 是空的!
console.log(person.name); // Jade 但還是有?!
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// 因為沒有設定就都是false
{
value: 'Jade',
writable: false,
enumerable: false,
configurable: false
}
為什麼一開始是空物件是因為 enumerable: false
,不過其實name還是有value的!
Object.create()
感覺有點像const jade = {}
const ann = Object.defineProperties(jade, {
name: {
value: "ann",
writable: true,
enumerable: true,
configurable: true
},
age: {
value: 20,
writable: true,
enumerable: true,
configurable: true
},
})
console.log(ann);
// { name: 'ann', age: 20 }
做到上面那格時突然覺得這兩個根本超像,Object.create()
也可以一次新增好多property啊!
但仔細想想就會感覺到他們本身就很不同:
Object.create()
是用來建立要繼承物件的新物件Object.defineProperties()
是建立新物件一起定義屬性描述器,但沒有任何繼承實際演練差異:Object.create()
需要一個變數去接,他無法直接改變物件
const jade = {};
const ann = Object.create(jade, {
name: {
value: "jade",
enumerable: true,
writable: false,
configurable: false,
},
city: {
value: "Taipei",
enumerable: true,
writable: false,
configurable: false,
},
});
console.log(ann);
// { name: 'jade', city: 'Taipei' }
如果沒有用變數去接的話就不會有任何改變
const jade = {};
Object.create(jade, {
name: {
value: "jade",
enumerable: true,
writable: false,
configurable: false,
},
city: {
value: "Taipei",
enumerable: true,
writable: false,
configurable: false,
},
});
console.log(jade);
// {}
可是以上只要改成defineProperties()
的話就會直接改變到原本的物件
const jade = {};
Object.defineProperties(jade, {
name: {
value: "jade",
enumerable: true,
writable: false,
configurable: false,
},
city: {
value: "Taipei",
enumerable: true,
writable: false,
configurable: false,
},
});
console.log(jade);
// { name: 'jade', city: 'Taipei' }
今天先這樣囉,明天見~
參考資料:008 深入瞭解JavaScript核心:函式、物件、原型鏈 (下)