Object.created是ES5出生的,官方給的介紹是
Object.create()方法建立一個新物件,使用現有的物件來提供新建立的物件的__proto__
對於__proto__
的解釋請戳 這裡
簡單理解,Object.created是一個繼承方法,**返回一個新物件,帶著指定的原型物件和屬性。**例如:
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten
me.printIntroduction();
// "My name is Matthew. Am I human? true"
複製程式碼
語法
官方特地介紹了語法:
Object.create(proto, [propertiesObject])
引數:
proto
:新建立物件的原型物件。propertiesObject
:可選。如果沒有指定為undefined
,則是要新增到新建立物件的可列舉屬性(即其自身定義的屬性,而不是其原型鏈上的列舉屬性)物件的屬性描述符以及相應的屬性名稱。這些屬性對應Object.defineProperties()
的第二個引數。如果propertiesObject
引數不是null
或一個物件,則丟擲一個TypeError
異常。
此處對Object.defineProperties()不多加贅述,介紹一個概念和用法不應該引入其他難以理解的部分和概念,Object.defineProperties()後續我可能會追加一篇文章專門介紹
常見用法
我們平時常用的就是使用一個引數的情況,可以實現簡單的繼承,例如上面的例子,包含一個引數,直接將某一個物件當作原型物件,使新的物件去繼承。
包含第二個引數的用法
包含第二個引數的用法可能在大多數場景下用的比較少,尤其是業務程式碼中會比較少的用到。但是深入探究第二個引數的用法之後,可以給我們帶來很多便利: 舉例
- 建立一個原型為null的空物件
let o
o = Object.create(null)
//得到的結果是這個物件No properties
複製程式碼
- 建立一個空物件的原理
o = {};
// 以字面量方式建立的空物件就相當於:
o = Object.create(Object.prototype);
複製程式碼
- 多個引數
o = Object.create(Object.prototype, {
// foo會成為所建立物件的資料屬性
foo: {
writable:true,
configurable:true,
value: "hello"
},
// bar會成為所建立物件的訪問器屬性
bar: {
configurable: false,
get: function() { return 10 },
set: function(value) {
console.log("Setting `o.bar` to", value);
}
}
});
複製程式碼
4. 建立一個以另一個空物件為原型,且擁有一個屬性的物件
o = Object.create({}, { p: { value: 42 } })
// 省略了的屬性特性預設為false,所以屬性p是不可寫,不可列舉,不可配置的:
o.p = 24
o.p
//42
o.q = 12
for (var prop in o) {
console.log(prop)
}
//"q"
delete o.p
//false
複製程式碼
- 建立一個可寫的,可列舉的,可配置的屬性
o2 = Object.create({}, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
});
複製程式碼
現在做有關繼承相關的操作,大家更習慣用ES6的`Class xx extends xxx`來實現繼承,在ES6出現之前,用的大多是call,apply,bind和Object.create;但是MDN上明確說了Class的語法:
ECMAScript 2015 中引入的 JavaScript 類實質上是 JavaScript 現有的基於原型的繼承的語法糖。類語法不會為JavaScript引入新的物件導向的繼承模型。
所以最終我們寫的程式碼底層仍然是基於原型來進行繼承的。雖然ES6裡面涉及到的關鍵字,例如:super、constructor、extends、static和java中類裡面涉及到的關鍵字相同,但是實際上是完全不同的,不能用看待java中類的眼光去看待JavaScript中的'Class',但是針對Class的用法和基於prototype實現的繼承或宣告一個'類'在底層其實是相同的。MDN文件後面並沒有polyfill相關的程式碼,我個人的想法是在一定程度上,polyfill是沒有必要的存在,這兩種寫法涉及到的底層是相同的,只不過區別在於使用的瀏覽器是否能正確識別Class一系列的關鍵字而已。 如果有興趣還可以去試一下用typeof 操作符看一下class宣告的“類”的具體型別
本來是想說一下Object.create的用法和我們平時沒注意到的點……結果扯到了ES6中的class上~ 下個周打算寫一下symbol的使用?