亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

javascript基礎--對象(Object)繼承

2024-04-27 15:06:06
字體:
來源:轉載
供稿:網友

引言

上一節《javascript基礎–對象(Object)封裝》講了如何造人,這一節將會總結怎么理清人與人之間的血緣關系,即繼承關系。對象繼承簡單地分為兩類,構造函數繼承和非構造函數繼承。所謂構造函數繼承就是利用this綁定對象的模式創建的對象之間的繼承關系;而非構造函數繼承就是利用對象字面量創建的對象之間的繼承關系。上代碼:

//Person父對象利用this綁定,子對象Tom,Linda也同樣采用這種模式創建function Person(name,sex){ this.name = name; this.sex = sex;}Person.PRototype.say = function(){ console.log(this.name +' is ' + this.sex);}//創建的Tom,Linda去繼承Person父對象,此種繼承成為構造函數繼承//Person采用對象字面量創建,子對象Tom,Linda也同樣采用這種模式創建var Person = { Pname: 'Person', Psex: 'Person sex is male or female', say: function(){ console.log('haha'); }}//創建的Tom,Linda去繼承Person父對象,此種繼承成為非構造函數繼承

1.構造函數繼承

首先確定父對象,即引言內的父對象,copy下來

function Person(name,sex){ this.name = name; this.sex = sex;}Person.prototype.say = function(){ console.log(this.name +' is ' + this.sex);}

我們的任務是創建Tom和Linda去繼承Person,我們先創建子對象模型

//Tom構造函數function Tom(name,sex){}Tom.prototype = {}var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){}Linda.prototype = {}var L = new Linda('Linda','female');

分析:父對象Person中屬性和方法分為兩部分,name和sex屬性是在構造函數Person上,而say方法是在Person.prototype上。所以要繼承Person所有屬性和方法,分為兩步,即繼承構造函數上的屬性和繼承原型對象上的方法。

2.構造函數繼承–對象冒充

對象冒充,是利用call或者apply方法,將父對象的屬性和方法綁定在子對象上,從而完成構造函數上屬性和方法的繼承,但是person原型對象上的say方法不會繼承。這里簡單介紹一下call和apply

//call定義A.call(B,Object);//釋義:調用A對象的方法,以B對象替換當前的A對象,其中參數是Object//apply定義A.apply(B,array);//釋義:調用A對象的方法,以B對象替換當前的A對象,其中參數必須是Array類型//so call和apply區別就在參數的形式上不同

現在來完善Tom和Linda構造函數

//Tom構造函數function Tom(name,sex){ Person.apply(this,arguments);}Tom.prototype = {}var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){ Person.apply(this,arguments);}Linda.prototype = {}var L = new Linda('Linda','female');

測試:

//可見Tom和Linda成功繼承了Person構造函數上的屬性,Person原型對象屬性怎么繼承呢?T.name;//'Tom'T.sex;//'male'T.say;//undefinedL.name;//'Linda'L.sex;//'female'L.say;//undefined

3.構造函數繼承–原型繼承

原型繼承,顧名思義肯定要在子對象原型上做文章,首先想到的是直接繼承Person.protype,就像這樣

//Tom構造函數function Tom(name,sex){ Person.apply(this,arguments);}Tom.prototype = Person.prototype;var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){ Person.apply(this,arguments);}Linda.prototype = Person.prototype;var L = new Linda('Linda','female');

測試:

//say被繼承了,完了??沒完T.say();//Tom is maleL.say();//Linda is female

我們為Tom原型對象上添加一個run方法,Linda原型對象上不添加,期望結果是T.run返回function,L.run返回undefined

Tom.prototype.run = function(){ console.log('Tom running');}//測試T.run();//'Tom running'L.run();//'Tom running'Person.prototype.run();//'Tom running'//可見修改Tom的原型對象也同樣修改了Person.prototype

原因是,prototype是一個地址,子對象原型繼承的是地址,而非數值。在C語言中,指針就是這樣一個概念。那怎么避免呢?既然地址不行,那就用值,不就ok了。所以讓子對象原型繼承父對象實例是一種方式。

//Tom構造函數function Tom(name,sex){ Person.apply(this,arguments);}//想想封裝函數的原型鏈,任何一個prototype對象都有一個constructor屬性,指向它的構造函數。如果沒有"Tom.prototype = new Person();"這一行,Tom.prototype.constructor是指向Tom的;加了這一行以后,Tom.prototype.constructor指向Person。所以我們必須手動糾正Tom.prototype = new Person();Tom.prototype.constructor = Tom;var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){ Person.apply(this,arguments);}//同理Linda.prototype = new Person();Linda.prototype.constructor = Linda;var L = new Linda('Linda','female');Tom.prototype.run = function(){ console.log('Tom running');}

測試:

//測試結果表明,我們成功了T.say();//'Tom is male'L.say();//'Linda is female'T.run();//'Tom running'L.run();//undefinedPerson.prototype.run();//undefined

除了利用繼承值以外,還有別的方法嗎?肯定有,那就是利用空對象作為中介,讓子對象的原型繼承空對象,空對象繼承父對象原型,這樣間接實現繼承,而且避免了直接繼承prototype的缺點,給子對象添加自身額外的方法時只會改變空對象,而不會改變父對象,這樣就達到和繼承值一樣的目的。

var Empty = function(){};Empty.prototype = Person.prototype;Tom.prototype = new Empty();Tom.prototype.constructor = Tom;

將此方法進行封裝成extend方法

function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; //為了保證繼承函數的完整性,增添一個通向父對象原型的接口 Child.uber = Parent.prototype;}

現在將Tom和Linda構造函數改變

//Tom構造函數function Tom(name,sex){ Person.apply(this,arguments);}//調用extend函數extend(Tom,Person);var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){ Person.apply(this,arguments);}//同理extend(Linda,Person);var L = new Linda('Linda','female');Tom.prototype.run = function(){ console.log('Tom running');}

測試:

//成功了T.name;//'Tom'T.say();//'Tom is male'T.run;//functionL.name;//'Linda'L.say();//'Linda is female'L.run;//undefinedPerson.prototype.run;//undefined

4.構造函數繼承–拷貝繼承

上面講了為了繼承原型上的屬性和方法,我們使用了原型繼承。這里有一個新思路,就是拷貝繼承,即將父對象原型上的屬性和方法直接拷貝到子對象上,從而實現繼承。這樣也避免了改變子對象原型的時候不會改變父對象原型,因為拷貝的是值而不是地址。

function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } //為了保證繼承函數的完整性,增添一個通向父對象原型的接口 c.uber = p;}

現在改變Tom,Linda構造函數

//Tom構造函數function Tom(name,sex){ Person.apply(this,arguments);}//調用extend2函數extend2(Tom,Person);var T = new Tom('Tom','male');//Linda構造函數function Linda(name,sex){ Person.apply(this,arguments);}//同理extend2(Linda,Person);var L = new Linda('Linda','female');Tom.prototype.run = function(){ console.log('Tom running');}

測試,不出意外,結果一樣

//意料之中,成功了T.name;//'Tom'T.say();//'Tom is male'T.run;//functionL.name;//'Linda'L.say();//'Linda is female'L.run;//undefinedPerson.prototype.run;//undefined

5.非構造函數繼承

還是先確定父對象,即引言內的父對象,copy下來

var Person = { Pname: 'Person', Psex: 'Person sex is male or female', say: function(){ console.log('haha'); }}

我們的任務是創建Tom和Linda去繼承Person,我們先創建子對象模型

var Tom = {};var Linda = {};

分析:這里要注意,這兩個對象都是普通對象,不是構造函數,無法使用構造函數方法實現”繼承”。

6.非構造函數繼承–object()方法

json格式的發明人Douglas Crockford,提出了一個object()函數

function object(o){ function F(){}; F.prototype = o; return new F();}

添加Tom和Linda對象私有方法

Tom = object(Person);Tom.name = 'Tom';Linda = object(Person);Linda.name = 'Linda';

測試:

Tom.Pname;//'Person'Tom.Psex;//'Person sex is male or female'Tom.say;//functionTom.name;//'Tom'Linda.Pname;//'Person'Linda.Psex;//'Person sex is male or female'Linda.say;//functionLinda.name;//'Linda'

7.非構造函數繼承–淺拷貝

和構造函數的實現思路一樣,拷貝也是實現繼承的一種方式

function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } //為了保證繼承函數的完整性,增添一個通向父對象的接口 c.uber = p; return c;}

改變Tom, Linda對象

Tom = extendCopy(Person);Tom.name = 'Tom';Linda = extendCopy(Person);Linda.name = 'Linda';

測試:

//同樣成功了Tom.Pname;//'Person'Tom.Psex;//'Person sex is male or female'Tom.say;//functionTom.name;//'Tom'Linda.Pname;//'Person'Linda.Psex;//'Person sex is male or female'Linda.say;//functionLinda.name;//'Linda'

為什么叫做淺拷貝呢,現在假設父對象中有一個屬性是數組或者對象,為父對象增加一個屬性color數組

Person.color = [yellow,white,black];//Tom繼承PersonTom = extendCopy(Person);//測試Tom.color;//[yellow,white,black]//現在我們為Tom.colorTom.color.push('blue');//測試Tom.color;//[yellow,white,black,blue]Person.color;//[yellow,white,black,blue]//???為什么改變子對象,父對象也跟著改變了呢?//原因是數組或對象是地址,相當于拷貝了地址,所以會出現這種情況。為了避免這種情況,也就有了深拷貝

8.非構造函數繼承–深拷貝

深拷貝是在前拷貝的基礎上增添了對父對象屬性的判斷,判斷是否為地址,如果是,則遞歸拷貝函數

function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c;}

改變Tom和Linda對象

Tom = deepCopy(Person,Tom);Tom.name = 'Tom';Linda = deepCopy(Person,Tom);Linda.name = 'Linda';

測試:

Person.color = [yellow,white,black];//Tom繼承PersonTom = extendCopy(Person);//測試Tom.color;//[yellow,white,black]//現在我們為Tom.colorTom.color.push('blue');//測試Tom.color;//[yellow,white,black,blue]//父對象沒有改變Person.color;//[yellow,white,black]

jQuery使用的深拷貝

結束語

對象的繼承到這里就結束了,其實也蠻簡單的。針對兩種情況,構造函數繼承其實就是對象冒充,原型,拷貝三種方式;非構造函數就是object()和淺深拷貝。只要深入理解,記憶起來還是蠻easy


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品亚洲永久免费精品| 久久综合久久88| 中文字幕久热精品在线视频| 欧美贵妇videos办公室| 最好看的2019的中文字幕视频| 久久亚洲精品网站| 国产精品一区二区三区免费视频| 日韩第一页在线| 国产精品美女免费看| 日韩电影网在线| 欧美视频在线看| 久久91超碰青草是什么| 精品国内亚洲在观看18黄| 日韩精品日韩在线观看| 亚洲男人天天操| 日韩精品视频免费在线观看| 大桥未久av一区二区三区| 日韩视频在线免费| 美女福利精品视频| 成人欧美一区二区三区黑人| 欧美二区在线播放| 久久精品影视伊人网| 亚洲aa在线观看| 亚洲欧美中文字幕在线一区| 亚洲娇小xxxx欧美娇小| 国产69精品久久久| 欧美成人午夜免费视在线看片| 久久综合网hezyo| 亚洲欧美国产一本综合首页| 97在线视频免费看| 久久99亚洲热视| 国产成人综合久久| 亚洲精品国产拍免费91在线| 亚洲性线免费观看视频成熟| 2019中文字幕免费视频| 综合久久五月天| 日韩电视剧免费观看网站| 中文字幕日韩电影| 久久久精品国产一区二区| 国产精欧美一区二区三区| 欧美美最猛性xxxxxx| 亚洲va欧美va在线观看| 日韩欧美在线视频日韩欧美在线视频| 亚洲欧美一区二区精品久久久| 中文在线资源观看视频网站免费不卡| 91最新在线免费观看| 国产精品永久免费视频| 久久久国产精品x99av| 黑人精品xxx一区一二区| 91国内产香蕉| 97香蕉久久夜色精品国产| 欧美精品一区在线播放| 欧美国产第一页| 亚洲aⅴ男人的天堂在线观看| 亚洲精品美女在线观看| 成人午夜激情网| 国产精品一区二区三区成人| 亚洲久久久久久久久久久| 国产欧美日韩中文字幕在线| 欧美日韩日本国产| 国产精品日韩在线播放| 欧美巨大黑人极品精男| 欧美黑人一区二区三区| 亚洲一区中文字幕在线观看| 国产美女高潮久久白浆| 欧美在线中文字幕| 欧美成年人网站| 欧美成人免费视频| 亚洲精品美女久久久| 久久香蕉频线观| 美女啪啪无遮挡免费久久网站| 久久免费成人精品视频| 亚洲高清一二三区| 日本一区二三区好的精华液| 中文字幕精品av| 日韩精品在线私人| 欧美激情区在线播放| 欧美自拍视频在线| 欧美日韩一区二区三区| 国产精品入口福利| 国产日韩专区在线| 国产日韩在线观看av| 国产精品99久久久久久久久久久久| 欧美精品一区二区三区国产精品| 韩国精品美女www爽爽爽视频| 欧美亚洲在线视频| 国产深夜精品福利| 欧美另类老肥妇| 国产精品高清在线观看| 久久久精品中文字幕| 91日本在线视频| 国内免费精品永久在线视频| 国产精自产拍久久久久久蜜| 成人两性免费视频| 日韩av黄色在线观看| 国产欧美日韩免费看aⅴ视频| 日本精品性网站在线观看| 久久精品视频免费播放| 久久久女人电视剧免费播放下载| 国产精品久久久久福利| 久久91超碰青草是什么| 中文字幕久久亚洲| 91大神福利视频在线| 国产午夜精品免费一区二区三区| 欧美激情精品久久久久| 欧美裸体xxxxx| 欧美国产日韩视频| 久久69精品久久久久久国产越南| 日韩成人在线观看| 国产中文字幕日韩| 欧美日韩在线免费| 国产一区二区三区高清在线观看| 亚洲国产毛片完整版| 另类少妇人与禽zozz0性伦| 精品国内产的精品视频在线观看| 亚洲毛片在线看| 亚洲欧美精品在线| 国产丝袜一区二区三区| 精品五月天久久| 欧美乱人伦中文字幕在线| 国产精品久久久久久av福利软件| 日韩av在线影院| 大量国产精品视频| 亚洲二区在线播放视频| 国产91精品久| 国产成人精品国内自产拍免费看| 色综合久久88色综合天天看泰| 精品中文字幕在线| 欧美性猛交xxxx| 国产精品久久精品| 国模私拍视频一区| 欧美激情网站在线观看| xx视频.9999.com| 欧美日在线观看| 中文国产成人精品久久一| 亚洲欧美精品伊人久久| 久久久99免费视频| 日韩女在线观看| 日韩禁在线播放| 日韩av黄色在线观看| 成人福利视频在线观看| 国产婷婷色综合av蜜臀av| 欧美一级片在线播放| 成人在线小视频| 欧美一区在线直播| 亚洲一区二区三区香蕉| 欧美性开放视频| 伊人伊成久久人综合网小说| 欧美性猛交xxxx偷拍洗澡| 欧美激情啊啊啊| 亚洲黄色片网站| 最近2019年中文视频免费在线观看| 亚洲a区在线视频| 亚洲欧美国产制服动漫| 亚洲视频在线播放| 欧美大片在线看| 在线色欧美三级视频| 亚洲国产成人av在线| 欧美理论电影在线播放| 亚洲综合视频1区| 国产精品日韩在线| 成人在线中文字幕| 日韩在线观看网址| 日韩av中文字幕在线播放|