JavaScript擴展原型鏈淺析

前言

上文對原型和原型鏈做了一些簡單的概念介紹和解析,本文將淺析一些原型鏈的擴展。

javaScript原型和原型鏈
//lewyon.xyz/prototype.html

擴展原型鏈

使用new操作符

利用原型是對象的特性,實例化對象的時候,繼承多個構造函數的屬性和方法

兼容性:支援目前以及所有可想像到的瀏覽器 (IE5.5 都可以使用)

function parent1() {}

parent1.prototype = {
  parentName: "parent1",
};

function parent2() {}

let child = new parent1();

child.childName = "child";

parent2.prototype = child;

let newChild = new parent2();

console.log(newChild.parentName); // parent1

console.log(newChild.childName); // child

使用Object.create

Object.create

Object.create() 方法創建一個新對象,使用現有的對象來提供新創建的對象的 proto

兼容性:支援當前所有非微軟版本或者 IE9 以上版本的瀏覽器

/**
 *
 * Object.create(proto,[propertiesObject])
 *
 * @params proto 新創建對象的原型對象。
 * 如果proto參數不是 null 或非原始包裝對象,則拋出一個 TypeError 異常,可以使用try和catch捕獲拋出的異常
 *
 * @params propertiesObject   可選參數 ,數據類型:對象
 *
 * */
const parent1 = {
  name: "parent1",
  do: function () {
    console.log(this.name);
  },
};
const child = Object.create(parent1);
child.name = "child"; // child添加自身的屬性name
child.do(); // child

/**
 *
 *
 *
 *---------------------------------------------------------------------------------------
 *
 *
 * */
function parent2() {}
parent2.prototype = {
  name: "parent2",
};
function parent3() {}
let child = Object.create(parent2.prototype);
child.childName = "child";
parent3.prototype = child;
let newChild = new parent3();
console.log(newChild.name); // parent2
console.log(newChild.childName); // child


使用setPrototypeOf

兼容性:不支援 IE8 以下的版本。


/**
 * Object.setPrototypeOf(obj, prototype)
 *
 * @params obj   要設置其原型的對象。
 *
 * @params  prototype
 *
 * 該對象的新原型 (一個對象 或 null)
 * 如果要設置原型的對象的 [[Prototype]] 被修改成不可擴展 (通過 Object.isExtensible()查看),就會拋出 TypeError 異常。
 * 如果 prototype 參數的數據類型不是 對象或者 null  (例如,數字,字元串,boolean,或者 undefined),那麼方法就不會執行。
 * 否則,該方法將 obj 的 [[Prototype]] 修改為新的值。
 *
 * Object.setPrototypeOf() 是 ECMAScript 6中新增的方法,相對於操作對象的原型鏈Object.prototype.__proto__來說,更適合拿來修改對象的原型
 *
 *
 * */

function parent1() {}
parent1.prototype = {
  name: "parent1",
};
function parent2() {}
let Obj = {
  ObjName: "Obj",
};
Object.setPrototypeOf(Obj, parent1.prototype);
parent2.prototype = Obj;
let newChild = new parent2();
console.log(newChild.name); // parent1
console.log(newChild.ObjName); // Obj
 

使用__proto__直接在原型鏈上操作,

使用__proto__操作,如果設置的屬性和方法較多,會產生性能問題,因此不太推薦使用__proto__

兼容性:IE10 及以下的瀏覽器版本。

/**
 * 
 * 直接在原型鏈上操作,如果設置的屬性和方法較多,會產生性能問題
 * 
 * */ 
var obj = {
  __proto__: {
    protoName1: "protoName1",
    __proto__: {
      protoName2: "protoName2",
      __proto__: Object.prototype,
    },
  },
};
console.log(obj.protoName1); // protoName1
console.log(obj.protoName2); // protoName1

小結

  • 在使用原型鏈編寫組件的過程中,我們需要考慮到原型鏈的性能問題。
  • 實例化對象過程中,會向上查找原型鏈的方法和屬性,在書寫的過程中,需要注意構造函數和對象的自帶的方法,確認是否會被覆蓋和重寫。

以上就是js中擴展原型鏈的簡單解析,有任何問題歡迎留言,後續的文章整理然後作為補充。

文章部落格地址:JavaScript擴展原型鏈淺析

源碼地址

歡迎關注公眾號:程式設計師布歐,不定期更新一些文章

創作不易,轉載請註明出處和作者。