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

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

JavaScript 原型繼承

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

簡介

繼承是面向對象語言的一個重要的特性和概念。許多的面向對象語言中都支持兩種繼承方式:接口繼承和實現繼承。

javaScript 僅支持實現繼承,主要是靠原型鏈來實現。

原型: Javascript 的所有函授都有一個PRototype屬性,這個屬性引用了一個對象,即原型對象,也簡稱原型。 注:在JavaScript中對象可以分為函數對象普通對象。只用函數對象包含prototype屬性。凡是通過 new Function() 創建的對象都是函數對象,其他的都是普通對象。

原型鏈:由于原型對象本身也是對象,它也有自己的原型。而它自己的原型對象又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈。 JavaScritp引擎在訪問對象的屬性時,如果在對象本身中沒有找到,則會去原型鏈中查找。如果找到,直接返回值;如果整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈一般實現為一個鏈表,這樣就可以按照一定的順序來查找。

構造函數:當任意一個普通函數用于創建一類對象時,它就被稱作構造函數,或構造器。構造函數必須滿子以下幾點: 1、在函數內部對新對象(this)的屬性進行設置,通常是添加屬性和方法。 2、構造函數可以包含返回語句(不推薦),但返回值必須是this,或者其它非對象類型的值。

關系: 1、構造函數通過 new 來創建實例對象;構造函數包含一個原型對象(prototype); 2、原型對象包含一個指向構造函數的指針(constructor); 3、實例對象包含一個指向原型對象的內部指針(_ _ proto _ _); 4、圖一: 這里寫圖片描述 5、圖二: 這里寫圖片描述

通過圖二來驗證圖一: 1、構造函數 A,通過 new 創建了實例對象 B。A.prototype 為 Object{}(原型對象); 2、Object{}(原型對象)的 constructor 指向構造函數 function A(); 3、B. _ _ proto _ _指向Object{}(原型對象)

原型鏈

圖三: 這里寫圖片描述 注:每個函數都是Function函數創建的對象,所以每個函數也有一個 _ _ proto _ _ 屬性指向Function函數的原型。這里需要指出的是,真正形成原型鏈的是每個對象的 _ _ proto _ _ 屬性,而不是函數的prototype屬性,這是很重要的。

圖四: 這里寫圖片描述 我們通過圖四來驗證圖三的正確性:

構造函數 A 創建了實例對象 B;B 的原型對象為 Object;Object.prototype 的原型對象指向 null;函數 A 的原型對象為 Function ;Function.prototype 的原型對象為 Object; 完全符合圖三。

綜圖所述

所有的對象都有 _ _ proto _ _ 屬性,該屬性對應該對象的原型.所有的函數對象都有prototype屬性,該屬性的值會被賦值給該函數創建的對象的 _ _ proto _ _ 屬性.所有的原型對象都有constructor屬性,該屬性對應創建所有指向該原型的實例的構造函數.函數對象和原型對象通過prototype和constructor屬性進行相互關聯.

繼承

1、基本模式:

var Parent = function() { this.name = 'parent';};Parent.prototype.getName = function() { return this.name;};Parent.prototype.obj = { a: 1};var Child = function() { this.name = 'child';};Child.prototype = new Parent();var parent = new Parent();var child = new Child();console.log(parent.getName()); //parentconsole.log(child.getName()); //child

這種是最簡單實現原型繼承的方法,直接把父類的對象賦值給子類構造函數的原型,這樣子類的對象就可以訪問到父類以及父類構造函數的prototype中的屬性。

圖五:這里寫圖片描述 如圖五可知:child -> Parent -> Function -> Object -> null

注:這種方法的優點很明顯,實現十分簡單,不需要任何特殊的操作;同時缺點也很明顯,如果子類需要做跟父類構造函數中相同的初始化動作,那么就得在子類構造函數中再重復一遍父類中的操作。如果初始化工作不斷增加,這種方式是很不方便的。

2、使用構造函數

var Parent = function(name) { this.name = name || 'parent';};Parent.prototype.getName = function() { return this.name;};Parent.prototype.obj = { a: 1};var Child = function(name) { // 在子類構造函數中通過apply調用父類的構造函數來進行相同的初始化工作。 // 這樣不管父類中做了多少初始化工作,子類也可以執行同樣的初始化工作 Parent.apply(this, arguments);};// Child.prototype = new Parent() ;// 使用這種方式父類構造函數被執行了兩次,一次是在子類構造函數中,一次在賦值子類原型時,這是很多余的。// 所以我們還需要做一個改進Child.prototype = Parent.prototype;var parent = new Parent('myParent');var child = new Child('myChild');console.log(parent.getName()); //myParentconsole.log(child.getName()); //myChild

圖六:這里寫圖片描述 根據圖六得知,此時的原型鏈為:child/parent -> Object -> null

注:上面借用構造函數模式最后改進的版本還是存在問題,它把父類的原型直接賦值給子類的原型,這就會造成一個問題,就是如果對子類的原型做了修改,那么這個修改同時也會影響到父類的原型,進而影響父類對象,這個肯定不是大家所希望看到的。

3、臨時構造函數模式(圣杯模式)

var Parent = function(name) { this.name = name || 'parent';};Parent.prototype.getName = function() { return this.name;};Parent.prototype.obj = { a: 1};var Child = function(name) { Parent.apply(this, arguments);};var F = function() {};F.prototype = Parent.prototype;Child.prototype = new F();var parent = new Parent('myParent');var child = new Child('myChild');console.log(parent.getName()); //myParentconsole.log(child.getName()); //myChild

圖七:這里寫圖片描述 如上圖:此時的原型鏈為:child -> parent -> Object -> null

4、再次改進

console.log(child.obj.a) ; //1console.log(parent.obj.a) ; //1child.obj.a = 2 ;console.log(child.obj.a) ; //2console.log(parent.obj.a) ; //2

我們在圣杯模式下添加上述代碼。查看結果會發現,當我們改變child.obj.a的值的時候,parent對應的也會改變。 出現這個情況是因為當訪問child.obj.a的時候,我們會沿著原型鏈一直找到父類的prototype中,然后找到了obj屬性,然后對obj.a進行修改。 改進方式:對父類原型進行拷貝然后再賦值給子類原型,這樣當子類修改原型中的屬性時就只是修改父類原型的一個拷貝,并不會影響到父類原型。

var deepClone = function(source, target) { source = source || {}; target = target || {}; var toStr = Object.prototype.toString, arrStr = '[object array]'; for (var i in source) { if (source.hasOwnProperty(i)) { var item = source[i]; if (typeof item === 'object') { target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {}; deepClone(item, target[i]); } else { target[i] = item; } } } return target;};var Parent = function(name) { this.name = name || 'parent';};Parent.prototype.getName = function() { return this.name;};Parent.prototype.obj = { a: 1};var Child = function(name) { Parent.apply(this, arguments);};Child.prototype = deepClone(Parent.prototype);var parent = new Parent('myParent');var child = new Child('myChild');console.log(child.obj.a); //1console.log(parent.obj.a); //1child.obj.a = 2;console.log(child.obj.a); //2console.log(parent.obj.a); //1

總結:

說了這么多,其實Javascript中實現繼承是十分靈活多樣的,并沒有一種最好的方法,需要根據不同的需求實現不同方式的繼承,最重要的是要理解Javascript中實現繼承的原理,也就是原型和原型鏈的問題,只要理解了這些,自己實現繼承就可以游刃有余。

參考來源: 再談Javascript原型繼承:https://segmentfault.com/a/1190000000766541


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩va亚洲va欧洲va国产| 一区二区亚洲精品国产| 国产亚洲一区二区在线| 国产精品久久久久久久久免费看| 亚洲人成电影网| 美日韩精品视频免费看| 亚洲精品国精品久久99热| 欧美精品video| 亚洲精品视频网上网址在线观看| 国产精品pans私拍| 亚洲精品电影在线观看| 亚洲aⅴ男人的天堂在线观看| 欧美激情视频一区| 7777精品久久久久久| 国产aaa精品| 国产a级全部精品| 日韩av在线一区二区| 亚洲精品视频免费| 精品久久久久久久中文字幕| 91干在线观看| 欧美在线视频观看| 亚洲自拍欧美另类| 欧美日韩国产综合新一区| 伊人成人开心激情综合网| 精品日韩中文字幕| 韩国日本不卡在线| 成人中文字幕+乱码+中文字幕| 欧美亚洲国产日本| 欧美午夜激情小视频| 久久久久99精品久久久久| 日韩在线资源网| 久久精品青青大伊人av| 亚洲电影av在线| 亚洲精品98久久久久久中文字幕| 欧美一级淫片丝袜脚交| 国产免费亚洲高清| 91九色国产社区在线观看| 欧美日韩国产在线播放| 欧美性感美女h网站在线观看免费| 亚洲高清一区二| 在线观看欧美日韩国产| 欧美日韩激情视频8区| 欧美一区亚洲一区| 久久久av亚洲男天堂| 精品亚洲一区二区三区在线观看| 日韩经典第一页| 国产一区二区在线播放| 国产精品激情av在线播放| 久久久在线观看| 成人性生交大片免费看视频直播| 国产亚洲欧美视频| 国产精品视频久久久久| 91在线免费视频| 亚洲国产精品视频在线观看| 日韩一区二区福利| 国产精选久久久久久| 亚洲欧洲第一视频| 日韩少妇与小伙激情| 欧美裸身视频免费观看| 欧美一级片在线播放| 97精品视频在线| www.亚洲人.com| 国产精品久久久久久久久粉嫩av| 久久激情视频免费观看| 国产精品扒开腿做爽爽爽视频| 日韩在线国产精品| 伦理中文字幕亚洲| 北条麻妃99精品青青久久| 亚洲精品按摩视频| 欧美成人免费全部观看天天性色| 91精品中国老女人| 久久免费视频网站| 亚洲www在线观看| 亚洲国产精品中文| 久久精品成人一区二区三区| 自拍偷拍亚洲一区| 97婷婷涩涩精品一区| 亚洲国产成人在线播放| 亚洲精品美女网站| 成人动漫网站在线观看| 午夜精品久久久久久99热| 久久精品亚洲94久久精品| 亚洲永久免费观看| 97久久国产精品| 亚洲在线免费视频| 91精品国产91久久久久福利| 久久在线免费视频| 色噜噜狠狠狠综合曰曰曰88av| 国产精品一区久久久| 国产日韩欧美日韩大片| 精品一区二区电影| 国产一区二区三区高清在线观看| 欧美激情女人20p| 国产精品青青在线观看爽香蕉| 日韩在线免费视频| 亚洲国产精品福利| 日韩美女av在线免费观看| 久久精品成人欧美大片古装| 91在线免费看网站| 国产视频精品免费播放| 国产精品一二三在线| 精品久久国产精品| 成人97在线观看视频| 国产亚洲精品久久久久动| 亚洲色图美腿丝袜| 亚洲在线免费观看| 久久久久久12| 一区三区二区视频| 欧美性做爰毛片| 欧美亚洲国产日韩2020| 国产日韩精品入口| 日韩理论片久久| 亚洲性av网站| 国产在线一区二区三区| 欧美日韩国产成人| 中文字幕av一区中文字幕天堂| 国产午夜精品一区二区三区| 久久精品99国产精品酒店日本| 欧美视频第一页| 国产精品揄拍500视频| 中文字幕日韩精品在线| 亚洲激情视频在线| 九九热r在线视频精品| 久久99久久99精品中文字幕| 亚洲欧美日韩国产中文专区| 国产精品欧美亚洲777777| 77777少妇光屁股久久一区| 久久精品视频va| 国产精品久久久av| 91精品国产自产91精品| 黄网动漫久久久| 日韩电影视频免费| 亚洲成人在线视频播放| 欧亚精品在线观看| 国产精品免费一区| 久久免费少妇高潮久久精品99| 久久视频国产精品免费视频在线| 欧美日韩一区二区在线| 色www亚洲国产张柏芝| 亚洲男人天堂网| 亚洲天堂第二页| 久久国产色av| 成人午夜在线视频一区| 久久精品国产亚洲精品2020| 国产成人精彩在线视频九色| 亚洲色图50p| 91av成人在线| 亚洲色图狂野欧美| 亚洲男人av在线| 成人97在线观看视频| 日韩在线一区二区三区免费视频| 都市激情亚洲色图| 国产美女精品免费电影| 亚洲国产小视频在线观看| 国产91成人在在线播放| 日韩天堂在线视频| 在线丨暗呦小u女国产精品| 欧美亚洲在线播放| 日韩福利伦理影院免费| 亚洲自拍小视频| 午夜精品蜜臀一区二区三区免费| 日韩电影第一页| 欧美最猛黑人xxxx黑人猛叫黄| 欧亚精品中文字幕|