首頁 > 軟體

JS建立物件常用設計模式工廠建構函式及原型

2022-07-08 14:06:38

引言

很多工友們都說:設計模式根本用不到,然而它其實時刻就在我們身邊,像王國維所說:眾裡尋他千百度,驀然回首,那人正在燈火闌珊處。

工廠模式

什麼是工廠模式?其實就字面意思,在現實社會生活中,市場通過不同工廠加工成不同的產品。

轉化成 JS 程式碼就是這樣的:

// 汽車工廠
function carFactory(brand, price, district) {
	 let o = new Object();
	 o.brand= brand;
	 o.price= price;
	 o.district= district;
	 o.performance= function() {
		 console.log(this.brand);
	 };
	 return o;
}
// 生產汽車
let car1 = carFactory("Benz", 50, "china");
let car2= carFactory("Honda", 30, "usa");
// 糖果工廠
function candyFactory(name, size, color) {
	 let o = new Object();
	 o.name= name;
	 o.size= size;
	 o.color= color;
	 o.performance= function() {
		 console.log(this.name);
	 };
	 return o;
}
// 生產糖果
let candy1= candyFactory("Oreo", "small", "white");
let candy2= candyFactory("quduoduo", "middle", "black");

有汽車工廠,糖果工廠等等,我們通過工廠函數,建立了特定物件。

工廠模式是一種眾所周知的設計模式,廣泛應用於軟體工程領域,用於抽象建立特定物件的過程。

建構函式模式

建構函式是用於建立特定型別物件的,可以自定義建構函式,以函數的形式為自己的物件型別定義屬性和方法。

比如前面的例子,就可以該寫為:

// 構造汽車的建構函式
function Car(brand, price, district) {
	 this.brand= brand;
	 this.price= price;
	 this.district= district;
	 this.performance= function() {
		 console.log(this.brand);
	 };
}
// 構造汽車
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");

與工廠模式的區別是,建構函式模式:

  • 沒有顯式地建立物件;
  • 屬性和方法直接賦值給了 this;
  • 沒有 return;

建構函式首字母通常是大寫;

這裡涉及到一個重要的考點:即使用 new 會發生什麼?

官方解答:

(1) 在記憶體中建立一個新物件。 (2) 這個新物件內部的[[Prototype]](隱式原型)特性被賦值為建構函式的 prototype (顯示原型)屬性。 (3) 建構函式內部的 this 被賦值為這個新物件(即 this 指向新物件)。 (4) 執行建構函式內部的程式碼(給新物件新增屬性)。 (5) 如果建構函式返回非空物件,則返回該物件;否則,返回剛建立的新物件。

這個,就是“原型鏈”的構造過程!!

car1.__proto__===Car.prototype // true
car1 instanceof Car // true
  • 建構函式的問題

建構函式的主要問題在於,其定義的方法會在每個範例上都建立一遍。

什麼意思?用程式碼來解釋:

// 構造汽車的建構函式
function Car(brand, price, district) {
	 this.brand= brand;
	 this.price= price;
	 this.district= district;
	 this.performance= function() {
	 };
}
// 構造汽車
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");
car1.performance == car2.performance // false

即使是同樣的方法,也不相等,因為每次執行 new 的時候,範例的方法都是重新建立的;

原型模式

原型模式可以解決建構函式模式“重複建立方法”的問題。

// 原型建立
function Car(brand, price, district) {
	 Car.prototype.brand= brand;
	 Car.prototype.price= price;
	 Car.prototype.district= district;
	 Car.prototype.performance= function() {
	 };
}
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");
car1.performance === car2.performance // true

這裡不妨再重溫一下原型鏈的指向關係:

car1.__proto__===Car.prototype // true
Car.__proto__===Function.prototype // true
Function.prototype.__proto__===Object.prototype //true
Car.prototype.__proto__===Object.prototype //true
Object.prototype.__proto__===null // true

原型模式弱化了向建構函式傳遞初始化引數的能力,會導致所有範例預設都取得相同的屬性值。

function Person() {}
Person.prototype = {
 constructor: Person,
 friends: "A",
 sayName() {
 }
}; 
let person1 = new Person();
let person2 = new Person();
person1.friends="B";
person1.friends // 'B'
person2.friends // 'A'
function PersonArr() {}
PersonArr.prototype = {
 constructor: PersonArr,
 friends:["A"],
 sayName() {
 }
}; 
let person1 = new PersonArr();
let person2 = new PersonArr();
person1.friends.push("B");
person1.friends // ["A","B"]
person2.friends // ["A","B"]

原型上的所有屬性是在範例間共用的,這對函數來說比較合適。對原始值的屬性 也還好,但對於參照值的屬性,則會產生混亂!!

結語

工廠模式、建構函式模式、原型模式,這三者沒有誰好誰壞,使用時,更多的是講究一個 —— 適合!只有清楚它們的原理,才能遊刃有餘。

更多關於JS建立物件設計模式的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com