function class1() { } function class2() { } class2.prototype = class1.prototype; class2.moreProperty1 = " /> 国产精品18久久久久网站 ,QVOD在线播放,亚洲AV怡红院AV男人的天堂

天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

javascript 面向?qū)ο缶幊袒A(chǔ):繼承

我們看到這里繼承的概念是多么的直白,“拷貝一個類的prototype 到另外一個類”,好,Code is cheap,看代碼:

function class1() { }
function class2() { }
class2.prototype = class1.prototype;
class2.moreProperty1 = " class 2 additional string " ;
class2.moreMethod1 = function () { alert( " class 2 additional method " ); }
/*
這樣,首先是class2具有了和class1 一樣的prototype,不考慮構(gòu)造函數(shù),兩個類是等價的。
隨后,又通過prototype給class2賦予了兩個額外的方法。所以class2是在class1的基礎(chǔ)上
增加了屬性和方法,這就實現(xiàn)了類的繼承。
*/

function test() {
var obj = new class2();
// JavaScript提供了instanceof 操作符來判斷一個對象是否是某個類的實例
alert(obj instanceof class2); // true
alert(obj instanceof class1); // ?
}

運行代碼,結(jié)果是不是在我們的意料之中?表面上看,上面的實現(xiàn)完全可行,js也可以正確的理解和實現(xiàn)這種繼承關(guān)系,obj同時是class1和 class2的實例,但實質(zhì)上則不然(我們學(xué)習(xí)的目的是要知其然更要知其所以然)。js的這種理解實際上是基于一種很簡單的策略,看下面的代碼,先使用 prototype讓class2 繼承于class1,再在class2 中重復(fù)定義method 方法:

// 定義class1
function class1() {
// 構(gòu)造函數(shù)
}
// 定義class1 的成員
class1.prototype = {
m1: function () { // 方法1
alert( " class1 method1 " );
}
}
// 定義class2
function class2() {
// 構(gòu)造函數(shù)
}
// 讓class2 繼承于class1
class2.prototype = class1.prototype;

// 給class2 重復(fù)定義方法method
class2.prototype.method = function () {
alert( " whose method2? class1 or class2 " );
}
// 創(chuàng)建兩個類的實例
var obj1 = new class1();
var obj2 = new class2();

function test() {
// 分別調(diào)用兩個對象的method 方法
obj1.method();
obj2.method();
}

從代碼執(zhí)行結(jié)果看,method方法在class1,2中運行的結(jié)果是相同的。

由此可見,當(dāng)對class2 進行prototype 的改變時,class1的prototype也隨之改變,即使對class2 的prototype 增減一些成員,class1的成員也隨之改變。所以class1 和class2 僅僅是構(gòu)造函數(shù)不同的兩個類,它們保持著相同的成員定義。說到這里,相信讀者已經(jīng)發(fā)現(xiàn)了其中的奧妙:class1 和class2 的prototype 是完全相同的,是對同一個對象的引用。其實從這條賦值語句就可以看出來:
//讓class2 繼承于class1
class2.prototype=class1.prototype;
在js中,除了基本的數(shù)據(jù)類型(數(shù)字、字符串、布爾類型等),所有的賦值以及函數(shù)參數(shù)都是引用傳遞,而不是值傳遞。所以上面的語句僅僅是讓class2 的prototype 對象引用class1 的prototype,造成了類成員定義始終保持一致的效果。從這里也看到了instanceof 操作符的執(zhí)行機制,它就是判斷一個對象是否是一個prototype 的實例,因為這里的obj1 和obj2 都是對應(yīng)于同一個prototype,所以它們instanceof 的結(jié)果都是相同的。由此可見,使用prototype 引用拷貝實現(xiàn)繼承不是一種正確的辦法。但在要求不嚴(yán)格的情況下,卻也是一種合理的方法,唯一的約束是不允許類成員的覆蓋定義(這里其實也是js的靈活性的體現(xiàn))。其實,我們完全可以利用反射機制和prototype 來實現(xiàn)js正確的類繼承:

function class1() {
// 構(gòu)造函數(shù)
}
class1.prototype = {
method: function () {
alert( " method1 " );
},
method2: function () {
alert( " method2 " );
}
}
function class2() {
// 構(gòu)造函數(shù)
}

// 讓class2 繼承于class1
for ( var p in class1.prototype) {
class2.prototype[p] = class1.prototype[p]; // 利用反射機制和prototype實現(xiàn)繼承
}

// 覆蓋定義class1中的method 方法
class2.prototype.method = function () {
alert( " class2 new method1 " );
}


// 創(chuàng)建兩個類的實例
var obj1 = new class1();
var obj2 = new class2();

function test() {
// 分別調(diào)用兩個對象的method 方法
obj1.method();
obj2.method();
// 分別調(diào)用兩個對象的method2 方法
obj1.method2();
obj2.method2();
}

從運行結(jié)果可見,obj2中重復(fù)定義的method 已經(jīng)覆蓋了繼承的method方法,同時method2 方法未受影響。而且obj1中的method 方法仍然保持了原有的定義。這樣,就實現(xiàn)了正確意義的類的繼承。為了方便開發(fā),可以為每個類添加一個共有的方法,用以實現(xiàn)類的繼承:

// 為類添加靜態(tài)方法inherit表示繼承于某類
Function.prototype.inherit = function (baseClass) {
for ( var p in baseClass.prototype) {
this .prototype[p] = baseClass.prototype[p];
}
}

function class1() {
// 構(gòu)造函數(shù)
}
class1.prototype = {
method: function () {
alert( " method1 " );
},
method2: function () {
alert( " method2 " );
}
}
function class2() {
// 構(gòu)造函數(shù)
}

// 讓class2 繼承于class1
// for (var p in class1.prototype) {
// class2.prototype[p] = class1.prototype[p]; // 利用反射機制和prototype實現(xiàn)繼承
// }

class2.inherit(class1); // 等價于上面注釋掉的那一個for循環(huán)

// 覆蓋定義class1中的method 方法
class2.prototype.method = function () {
alert( " class2 new method1 " );
}


// 創(chuàng)建兩個類的實例
var obj1 = new class1();
var obj2 = new class2();

function test() {
// 分別調(diào)用兩個對象的method 方法
obj1.method();
obj2.method();
// 分別調(diào)用兩個對象的method2 方法
obj1.method2();
obj2.method2();
}

上面的代碼使邏輯變的更加清楚,也更容易理解。通過這種方法實現(xiàn)的繼承,有一個缺點,就是在class2 中添加類成員定義時,不能給prototype 直接賦值,而只能對其屬性進行賦值,例如不能為:
class2.prototype={
//成員定義
}
而只能為:
class2.prototype.propertyName=someValue;
class2.prototype.methodName=function(){
//語句
}

由此可見,這樣實現(xiàn)繼承仍然要以犧牲一定的代碼可讀性為代價。有沒有“不僅基類可以用對象直接賦值給property,而且在派生類中也可以同樣實現(xiàn),使代碼邏輯更加清晰,也更能體現(xiàn)面向?qū)ο蟮恼Z言特點”的js繼承方式?引號里的說法是多么的誘人啊,繼續(xù)學(xué)習(xí)去了。

JavaScript技術(shù)javascript 面向?qū)ο缶幊袒A(chǔ):繼承,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 精品欧美小视频在线观看 | 国内精品欧美久久精品 | www.黄色| 亚洲人交性视频 | 嫩草电影网嫩草影院 | 打开双腿狠狠蹂躏蜜桃臀 | 99精品国产AV一区二区麻豆 | 午夜久久影院 | 久久精品国产亚洲AV未满十八 | 热热久久超碰精品中文字幕 | 美女被男人撕衣舔胸 | 成人欧美一区二区三区白人 | 魔乳 堕乳漫画acg产卵 | 天天综合亚洲综合网站 | 臀精插宫NP文| 国产午夜精品福利久久 | 精品人妻一区二区三区视频53 | 两个女人互添下身高潮自视频 | 精品动漫国产亚洲AV在线观看 | 草699一码二码三码四码 | 拉菲娱乐主管高工资q39709 | 久久无码人妻AV精品一区 | 久久99综合国产精品亚洲首页 | 国产午夜久久影院 | 老熟风间由美AV在线一区二区 | WWW国产亚洲精品久久 | 国产精品久久久久久久久免费下载 | 暖暖视频在线观看高清... | 国产一区2区 | 久久青青热| 国产在线精品国自产拍影院午夜 | 亚洲一区自拍高清亚洲精品 | 亚洲国产精品久久精品成人网站 | 国产午夜精品AV一区二区麻豆 | 国产毛多水多高潮高清 | 综合色就爱涩涩涩综合婷婷 | 网友自拍成人在线视频 | 狠狠色狠狠色综合曰曰 | 亚洲精品久久久久69影院 | 久久亚洲精品专区蓝色区 | 国产99青草全福视在线 |