摘要:原型模式與基于原型繼承的對象系統原型模式不單是一種設計模式,也被稱為一種編程范型。寫一個函數實現的功能獲取構造器,也就是創建一個新對象,并將原型指向構造器的原型。
原型模式與基于原型繼承的 JavaScript 對象系統
原型模式不單是一種設計模式,也被稱為一種編程范型。原型模式又一個重要的特性就是,當對象無法響應某個請求時,就會把該請求委托給它的原型。
使用克隆的原型模式從設計模式的角度講,原型模式是用于創建對象的一種模式,如果我們想要創建一個對象,一種方法是先指定它的類型,然后通過類來創建這個對象。原型模式選擇了另一種方式,不再關心對象的類型,而是找到一個對象,然后通過克隆來創建一個一摸一樣的對象。
但原型模式的真正目的并非在于需要得到一個一摸一樣的對象,而是提供一種便捷的方式去創建某個類型的對象,克隆只是創建這個對象的過程和手段。
ECMAScript 5 提供了Object.create來克隆一個對象,嚴格來說是創建一個新對象,使用現有的對象來提供新創建的對象的__proto__。
const Coder = function() { this.name = "Ashin"; this.age = 18; this.gender = "male"; }; const cloneCoder = Object.create(Coder); console.log(cloneCoder); console.log(cloneCoder.name); console.log(cloneCoder.age); console.log(cloneCoder.gender);
手動實現 Object.create:
const objCreate = function(obj) { const F = function() {}; F.prototype = obj; return new F(); }; const cloneCoder = objCreate(Coder); console.log(cloneCoder); console.log(cloneCoder.name); console.log(cloneCoder.age); console.log(cloneCoder.gender);
Object.prototype
事實上,JavaScript 中的根對象是 Object.prototype 對象,它是一個空對象。我們在 JavaScript 遇到的每個對象,都是從 Object.prototype 對象克隆而來的, Object.prototype 對象就是它們的原型。
const o1 = new Object(); const o2 = {}; // 用 ES5 提供的 Object.getPrototypeOf 來查看兩個對象的原型 console.log(Object.getPrototypeOf(o1) === Object.prototype); // true console.log(Object.getPrototypeOf(o2) === Object.prototype); // truenew 運算符
運算符創建一個用戶定義的對象類型的實例或具有構造函數的內置對象的實例。new 關鍵字會進行如下的操作:
創建一個空的簡單 JavaScript 對象(即{});
鏈接該對象(即設置該對象的構造函數)到另一個對象 ;
將步驟 1 新創建的對象作為 this 的上下文 ;
如果該函數沒有返回對象,則返回 this。
先看一段代碼:
function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; }; const p = new Person("Ashin"); console.log(p); // Person {name: "Ashin"} console.log(p.name); // Ashin console.log(p.getName()); // Ashin console.log(Object.getPrototypeOf(p) === Person.prototype); // true
強調一下,在 JavaScript 中沒有類的概念。這里的 Person 并不是類,而是函數構造器。當使用 new 運算符調用函數時,此時的函數就是一個構造器。用 new 運算符來創建對象的過程,是通過克隆 Object.prototype 來得到新的對象(但實際上并不是每次都真正地克隆了一個新的對象),再進行一些其他的額外操作的過程。
寫一個函數實現 new 的功能:
const _new = function() { const Constructor = [].shift.call(arguments); // 獲取構造器,也就是 Person const obj = Object.create(Constructor.prototype); // 創建一個新對象,并將原型(__proto__) 指向構造器的原型 (Constructor.prototype)。 const ret = Constructor.apply(obj, arguments); // 將新建的對象作為this的上下文執行構造器 return typeof ret === "object" ? ret : obj; // 如果構造器沒有返回對象則返回新建的對象 }; const p2 = _new(Person, "Ashin"); console.log(p2); // Person {name: "Ashin"} console.log(p2.name); // Ashin console.log(p2.getName()); // Ashin console.log(Object.getPrototypeOf(p2) === Person.prototype); // true(原型)繼承
先來看一段典型的“原型風格”:
function Parent(name) { this.name = name; } Parent.prototype.showInfo = function() { console.log(this.name); } function Child(name, age) { Parent.call(this, name); this.age = age; } // 注意!下面執行后沒有 Bar.prototype.constructor 了 // 如果你需要這個屬性的話可能需要手動修復一下它 Child.prototype = Object.create(Parent.prototype); // 多態 Child.prototype.showInfo = function() { Parent.prototype.showInfo.call(this); console.log(this.age); } Child.prototype.dance = function() { console.log(this.name + " dance"); } var tom = new Child("Tom", 10); tom.showInfo() tom.dance() console.log(tom)參考
曾探. JavaScript設計模式與開發實踐 (圖靈原創) (Chinese Edition)
你不知道的JavaScript(上卷)
MDN Web 文檔
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106769.html
摘要:首先,需要來理清一些基礎的計算機編程概念編程哲學與設計模式計算機編程理念源自于對現實抽象的哲學思考,面向對象編程是其一種思維方式,與它并駕齊驅的是另外兩種思路過程式和函數式編程。 JavaScript 中的原型機制一直以來都被眾多開發者(包括本人)低估甚至忽視了,這是因為絕大多數人沒有想要深刻理解這個機制的內涵,以及越來越多的開發者缺乏計算機編程相關的基礎知識。對于這樣的開發者來說 J...
摘要:于是就有了構造函數和原型模式混合模式組合使用構造函數模式和原型模式創建自定義類型最常見的方式,就是組合模式。 創建對象 JS有六種數據數據類型,其中五種屬于基本數據類型:Null、Boolean、undefined、String、Number。而其它值都是對象。數組是對象,函數是對象,正則表達式是對象。對象也是對象。 來看一下對象的定義: 無序屬性的集合,其屬性可以包含基本值、對象、或...
摘要:創建構造函數后,其原型對象默認只會取得屬性至于其他的方法都是從繼承來的。上圖展示了構造函數的原型對象和現有的兩個實例之間的關系。所有原生的引用類型都在其構造函數的原型上定義了方法。 第6章我一共寫了3篇總結,下面是相關鏈接:讀《javaScript高級程序設計-第6章》之理解對象讀《javaScript高級程序設計-第6章》之繼承 工廠模式 所謂的工廠模式就是,把創建具體對象的過程抽象...
摘要:就是通過調用構造函數而創建的那個對象實例的原型對象。構造函數模式可以創建自定義引用類型,可以像創建內置對象實例一樣使用操作符。 數據類型: 簡單數據類型:Undefined、Null、String、Number、Boolean、Symbol 復雜數據類型:Object // Undefined:聲明,但未初始化 // Null:空對象指針 typeof操作符(檢測基本數據類型): ...
摘要:實例中的指針僅指向原型,而不指向構造函數。調用構造函數時會為實例添加一個指向最初原型的或者而把原型修改為另外一個對象就等于切斷了構造函數與最初原型之間的聯系。 面向對象的程序設計 ECMA-262定義對象:無序屬性的集合,其屬性可以包含基本值,對象或者函數。普通理解:對象是一組沒有特定順序的值。對象的每個屬性或方法都有一個名字,而每個名字都映射一個值。 每個對象都是基于一個引用類型創建...
閱讀 1360·2021-09-24 10:26
閱讀 3674·2021-09-06 15:02
閱讀 628·2019-08-30 14:18
閱讀 586·2019-08-30 12:44
閱讀 3127·2019-08-30 10:48
閱讀 1950·2019-08-29 13:09
閱讀 2003·2019-08-29 11:30
閱讀 2288·2019-08-26 13:36