首頁  >  文章  >  web前端  >  JavaScript中困難:prototype與建構子綁定實例詳解

JavaScript中困難:prototype與建構子綁定實例詳解

伊谢尔伦
伊谢尔伦原創
2017-07-20 15:37:561550瀏覽

JavaScript的物件與建構子

## 定義一個JavaScript物件可以這麼定義


var a = {
	x : 1,
	y : 2,
	add : function () {
		return this.x + this.y;
	},
	mul : function () {
		return this.x * this.y;
	}
}

這樣,你就定義了一個變數a,這個變數除了有x和y兩個公有成員外,還有兩個add和mul兩個函數(公有方法)。但是這樣的定義方法的缺點有2條:

1.批量生成物件很不方便,如果你var b=a;那麼你每次修改b的成員,都會同時改掉a的成員,因為JavaScript的引用機制

2.如果每次產生物件需要自訂一些成員,都要寫出對應的賦值運算,增加程式碼行數。

所以,在定義一個JavaScript物件之前,我們可以先定義一個建構子。


function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

然後,定義一個物件


#

a = new A(1, 2);

上面這句程式碼看起來簡單,但要跟C++等物件導向的語言做個區分,A並不是嚴格意義上「類別」的概念,因為JavaScript是沒有類別的,只是呼叫了建構子而已。

現在問題來了,我們要怎麼實現繼承? C++把封裝,繼承,多型這三個物件導向的特徵實現得清清楚楚。但是對於JavaScript這樣一個比較浪的語言,沒有一個很嚴格的繼承機制,而是用以下幾種方式來模擬。

JavaScript的prototype

為了能夠講清後面的apply或call函數,這裡先引入prototype。 prototype是只有Function才有的。

要用好繼承,首先要明白為什麼要設計繼承這個東西?無非就是「把公共的部分」提取出來,實現程式碼重複使用。

所以在JavaScript裡,也是把公共部分放在Function的prototype裡。

我們來比較兩個用prototype來實作繼承的例子


function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

function B(x,y){
	
}

B.prototype=new A(1,2);

console.log(new B(3,4).add());  //3

這個例子中,子類別的prototype指向一個A類別物件

我們再實作一個B繼承A的例子:


function A() {
	
}

A.prototype = {
	x : 1,
	y : 2,
	add : function () {
		return this.x + this.y;
	},
	mul : function () {
		return this.x * this.y;
	}
}
A.prototype.constructor=A;

function B(){
	
}

B.prototype=A.prototype;
B.prototype.constructor=B;

B的prototype物件引用了A的prototype對象,因為是引用,所以如果修改了B的prototype對象,A的prototype對像也隨之修改,因為本質上他們都指向一塊記憶體。所以每次改動B類型的prototype都要手動將constructor改回,防止錯亂。相較於兩個例子,上一個例子因為沒有引用,所以不會發生這個問題。

建立一個B類型的物件


b=new B();

b物件具有A類型的一切成員


console.log(b.add());  //3

因為每個prototype物件都有兩個重要成員:constructor和_proto_,constructor本質上是一個函數指針,所以B.prototype=A.prototype執行後,覆蓋掉了constructor,所以後面要讓constructor重新指向B型別的構造函數。

JavaScript的建構子綁定

在定義完一個A類型的建構函式後,再定義一個B類型,然後在B型別建構函式內部,“嵌入執行”A類型的建構函數。


function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

function B(x, y, z) {
	A.apply(this, arguments);
	this.z = z;
}

console.log(new B(1,2,3));

apply函式和call函式基本上一樣,可以在B型別建構函式內部執行A型別建構函式。同時也可以繼承A的所有成員。

顯示結果:

這裡給個公式:在B建構函式裡寫A.apply(this),可以讓B建構出來的物件可以擁有A構造函數裡的所有成員。

談到apply和call,還可以實作多重繼承


function IA(){
	this.walk=function(){
		console.log("walk");
	}
}

function IB(){
	this.run=function(){
		console.log("run");
	}
}

function Person(){
	IA.apply(this);
	IB.apply(this);
}

var p=new Person();
p.walk();  //walk    
p.run();  //run

以上是JavaScript中困難:prototype與建構子綁定實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn