国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript的繼承實現小結

2019-11-19 16:39:05
字體:
來源:轉載
供稿:網友

最近在忙前端的工作,因為之前做.net和php的開發比較多,前端開發喜歡把庫拿來就用,幾次事實證明,不懂原理,連改代碼也改不好,所以還是下定決心研究下JavaScript的幾個技術難點。

0x1.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這樣一個比較浪的語言,沒有一個很嚴格的繼承機制,而是采用以下幾種方式來模擬。

0x2.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類型的構造函數。

0x3.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

 以上就是本文的全部內容了,希望大家能夠喜歡

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 钟山县| 永胜县| 塔河县| 宝丰县| 西乡县| 墨竹工卡县| 西乌| 抚宁县| 博兴县| 新乡县| 正镶白旗| 定西市| 阿巴嘎旗| 历史| 云霄县| 洛扎县| 松潘县| 鄱阳县| 莆田市| 高密市| 沭阳县| 高淳县| 融水| 弋阳县| 克山县| 安泽县| 崇州市| 西吉县| 宝清县| 黄石市| 南通市| 临泉县| 石景山区| 林甸县| 青冈县| 台南市| 沾益县| 鄂托克前旗| 鄂伦春自治旗| 皮山县| 正定县|