摘要:原型模式與基于原型繼承的對象系統(tǒng)原型模式不單是一種設(shè)計模式,也被稱為一種編程范型。寫一個函數(shù)實現(xiàn)的功能獲取構(gòu)造器,也就是創(chuàng)建一個新對象,并將原型指向構(gòu)造器的原型。
原型模式與基于原型繼承的 JavaScript 對象系統(tǒng)
原型模式不單是一種設(shè)計模式,也被稱為一種編程范型。原型模式又一個重要的特性就是,當對象無法響應某個請求時,就會把該請求委托給它的原型。
使用克隆的原型模式從設(shè)計模式的角度講,原型模式是用于創(chuàng)建對象的一種模式,如果我們想要創(chuàng)建一個對象,一種方法是先指定它的類型,然后通過類來創(chuàng)建這個對象。原型模式選擇了另一種方式,不再關(guān)心對象的類型,而是找到一個對象,然后通過克隆來創(chuàng)建一個一摸一樣的對象。
但原型模式的真正目的并非在于需要得到一個一摸一樣的對象,而是提供一種便捷的方式去創(chuàng)建某個類型的對象,克隆只是創(chuàng)建這個對象的過程和手段。
ECMAScript 5 提供了Object.create來克隆一個對象,嚴格來說是創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__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);
手動實現(xiàn) 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 運算符
運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象的實例。new 關(guān)鍵字會進行如下的操作:
創(chuàng)建一個空的簡單 JavaScript 對象(即{});
鏈接該對象(即設(shè)置該對象的構(gòu)造函數(shù))到另一個對象 ;
將步驟 1 新創(chuàng)建的對象作為 this 的上下文 ;
如果該函數(shù)沒有返回對象,則返回 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
強調(diào)一下,在 JavaScript 中沒有類的概念。這里的 Person 并不是類,而是函數(shù)構(gòu)造器。當使用 new 運算符調(diào)用函數(shù)時,此時的函數(shù)就是一個構(gòu)造器。用 new 運算符來創(chuàng)建對象的過程,是通過克隆 Object.prototype 來得到新的對象(但實際上并不是每次都真正地克隆了一個新的對象),再進行一些其他的額外操作的過程。
寫一個函數(shù)實現(xiàn) new 的功能:
const _new = function() { const Constructor = [].shift.call(arguments); // 獲取構(gòu)造器,也就是 Person const obj = Object.create(Constructor.prototype); // 創(chuàng)建一個新對象,并將原型(__proto__) 指向構(gòu)造器的原型 (Constructor.prototype)。 const ret = Constructor.apply(obj, arguments); // 將新建的對象作為this的上下文執(zhí)行構(gòu)造器 return typeof ret === "object" ? ret : obj; // 如果構(gòu)造器沒有返回對象則返回新建的對象 }; 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; } // 注意!下面執(zhí)行后沒有 Bar.prototype.constructor 了 // 如果你需要這個屬性的話可能需要手動修復一下它 Child.prototype = Object.create(Parent.prototype); // 多態(tài) 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設(shè)計模式與開發(fā)實踐 (圖靈原創(chuàng)) (Chinese Edition)
你不知道的JavaScript(上卷)
MDN Web 文檔
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106769.html
摘要:首先,需要來理清一些基礎(chǔ)的計算機編程概念編程哲學與設(shè)計模式計算機編程理念源自于對現(xiàn)實抽象的哲學思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因為絕大多數(shù)人沒有想要深刻理解這個機制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計算機編程相關(guān)的基礎(chǔ)知識。對于這樣的開發(fā)者來說 J...
摘要:于是就有了構(gòu)造函數(shù)和原型模式混合模式組合使用構(gòu)造函數(shù)模式和原型模式創(chuàng)建自定義類型最常見的方式,就是組合模式。 創(chuàng)建對象 JS有六種數(shù)據(jù)數(shù)據(jù)類型,其中五種屬于基本數(shù)據(jù)類型:Null、Boolean、undefined、String、Number。而其它值都是對象。數(shù)組是對象,函數(shù)是對象,正則表達式是對象。對象也是對象。 來看一下對象的定義: 無序?qū)傩缘募希鋵傩钥梢园局?、對象、?..
摘要:創(chuàng)建構(gòu)造函數(shù)后,其原型對象默認只會取得屬性至于其他的方法都是從繼承來的。上圖展示了構(gòu)造函數(shù)的原型對象和現(xiàn)有的兩個實例之間的關(guān)系。所有原生的引用類型都在其構(gòu)造函數(shù)的原型上定義了方法。 第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級程序設(shè)計-第6章》之理解對象讀《javaScript高級程序設(shè)計-第6章》之繼承 工廠模式 所謂的工廠模式就是,把創(chuàng)建具體對象的過程抽象...
摘要:就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個對象實例的原型對象。構(gòu)造函數(shù)模式可以創(chuàng)建自定義引用類型,可以像創(chuàng)建內(nèi)置對象實例一樣使用操作符。 數(shù)據(jù)類型: 簡單數(shù)據(jù)類型:Undefined、Null、String、Number、Boolean、Symbol 復雜數(shù)據(jù)類型:Object // Undefined:聲明,但未初始化 // Null:空對象指針 typeof操作符(檢測基本數(shù)據(jù)類型): ...
摘要:實例中的指針僅指向原型,而不指向構(gòu)造函數(shù)。調(diào)用構(gòu)造函數(shù)時會為實例添加一個指向最初原型的或者而把原型修改為另外一個對象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。 面向?qū)ο蟮某绦蛟O(shè)計 ECMA-262定義對象:無序?qū)傩缘募希鋵傩钥梢园局?,對象或者函?shù)。普通理解:對象是一組沒有特定順序的值。對象的每個屬性或方法都有一個名字,而每個名字都映射一個值。 每個對象都是基于一個引用類型創(chuàng)建...
摘要:將構(gòu)造函數(shù)的作用域賦值給新對象因此指向了新對象執(zhí)行構(gòu)造函數(shù)的代碼為這個新對象添加屬性返回對象最初是用來標識對象類型的。但提到檢測對象類型,還是使用將構(gòu)造函數(shù)當作函數(shù)構(gòu)造函數(shù)與其他函數(shù)唯一區(qū)別。 創(chuàng)建對象 雖然Object構(gòu)造函數(shù)與對象字面量都能創(chuàng)建單個對象, 但這些方式都有明顯的缺點: 使用同一個接口創(chuàng)建很多對象, 會產(chǎn)生大量重復代碼。 var obj = {}; //對象字面量 va...
閱讀 1366·2021-09-24 10:26
閱讀 3681·2021-09-06 15:02
閱讀 638·2019-08-30 14:18
閱讀 590·2019-08-30 12:44
閱讀 3130·2019-08-30 10:48
閱讀 1954·2019-08-29 13:09
閱讀 2010·2019-08-29 11:30
閱讀 2296·2019-08-26 13:36