Object.create淺析

Object.created是ES5出生的,官方給的介紹是 Object.create()方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__ 對於__proto__的解釋請戳 這裏 簡單理解,Object.created是一個繼承方法,**返回一個新對象,帶着指定的原型對象和屬性。**例如:java

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 異常。app

此處對Object.defineProperties()很少加贅述,介紹一個概念和用法不該該引入其餘難以理解的部分和概念,Object.defineProperties()後續我可能會追加一篇文章專門介紹ui

常見用法

咱們平時經常使用的就是使用一個參數的狀況,能夠實現簡單的繼承,例如上面的例子,包含一個參數,直接將某一個對象看成原型對象,使新的對象去繼承。this

包含第二個參數的用法

包含第二個參數的用法可能在大多數場景下用的比較少,尤爲是業務代碼中會比較少的用到。可是深刻探究第二個參數的用法以後,能夠給咱們帶來不少便利: 舉例spa

  1. 建立一個原型爲null的空對象
let o
o = Object.create(null)
//獲得的結果是這個對象No properties
複製代碼
  1. 建立一個空對象的原理
o = {};
// 以字面量方式建立的空對象就至關於:
o = Object.create(Object.prototype);
複製代碼
  1. 多個參數
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
複製代碼
  1. 建立一個可寫的,可枚舉的,可配置的屬性
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引入新的面向對象的繼承模型。prototype

因此最終咱們寫的代碼底層仍然是基於原型來進行繼承的。雖然ES6裏面涉及到的關鍵字,例如:super、constructor、extends、static和java中類裏面涉及到的關鍵字相同,可是其實是徹底不一樣的,不能用看待java中類的眼光去看待JavaScript中的'Class',可是針對Class的用法和基於prototype實現的繼承或聲明一個'類'在底層實際上是相同的。MDN文檔後面並無polyfill相關的代碼,我我的的想法是在必定程度上,polyfill是沒有必要的存在,這兩種寫法涉及到的底層是相同的,只不過區別在於使用的瀏覽器是否能正確識別Class一系列的關鍵字而已。 若是有興趣還能夠去試一下用typeof 操做符看一下class聲明的「類」的具體類型3d

class.png

原本是想說一下Object.create的用法和咱們平時沒注意到的點……結果扯到了ES6中的class上~ 下個周打算寫一下symbol的使用🌚code

相關文章
相關標籤/搜索