成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

JavaScript繼承的實現方法有哪些

JavaScript繼承的實現方法:1、利用構造原型模式;2、使用動態原型,根據面向對象的設計原則,類型的所有成員應該都被封裝在類結構體內;3、使用工廠模式;4、使用類繼承,即在子類中調用父類構造函數。

JavaScript繼承的實現方法有哪些

本教程操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。

JavaScript 是以對象為基礎,以函數為模型,以原型為繼承的面向對象開發模式。本節將詳細介紹定義 JavaScript 類型的方法,以及實現繼承的常用模式。

構造原型

直接使用 prototype 原型設計類的繼承存在兩個問題。

由于構造函數事先聲明,而原型屬性在類結構聲明之后才被定義,因此無法通過構造函數向原型動態傳遞參數。這樣實例化對象都是一個模樣,沒有個性。要改變原型屬性值,則所有實例都會受到干擾。

當原型屬性的值為引用類型數據時,如果在一個對象實例中修改該屬性值,將會影響所有的實例。

示例1

簡單定義 Book 類型,然后實例化。

function Book () {};  //聲明構造函數 Book.prototype.o = {x : 1, y : 2};  //構造函數的原型屬性o是一個對象 var book1 = new Book ();  //實例化對象book1 var book2 = new Book ();  //實例化對象book2 console.log(book1.o.x);  //返回1 console.log(book2.o.x);  //返回1 book2.o.x = 3;  //修改實例化對象book2中的屬性x的值 console.log(book1.o.x);  //返回3 console.log(book2.o.x);  //返回3

由于原型屬性 o 為一個引用型的值,所以所有實例的屬性 o 的值都是同一個對象的引用,一旦 o 的值發生變化,將會影響所有實例。

構造原型正是為了解決原型模式而誕生的一種混合設計模式,它把構造函數模式與原型模式混合使用,從而避免了上述問題的發生。

實現方法:對于可能會相互影響的原型屬性,并且希望動態傳遞參數的屬性,可以把它們獨立出來使用構造函數模式進行設計。對于不需要個性設計、具有共性的方法或屬性,則可以使用原型模式來設計。

示例2

遵循上述設計原則,把其中兩個屬性設計為構造函數模式,設計方法為原型模式。

function Book (title, pages) {  //構造函數模式設計     this.title = title;     this.pages = pages; } Book.prototype.what = function () {  //原型模式設計     console.log(this.title + this.pages); }; var book1 = new Book("JavaScript 程序設計", 160); var book2 = new Book("C語言程序設計", 240); console.log(book1.title); console.log(book2.title);

構造原型模式是 ECMAScript 定義類的推薦標準。一般建議使用構造函數模式定義所有屬性,使用原型模式定義所有方法。這樣所有方法都只創建一次,而每個實例都能夠根據需要設置屬性值。這也是使用最廣的一種設計模式。

動態原型

根據面向對象的設計原則,類型的所有成員應該都被封裝在類結構體內。例如:

function Book (title, pages) {  //構造函數模式設計     this.title = title;     this.pages = pages;     Book.prototype.what = function () {  //原型模式設計,位于類的內部         console.log(this.title + this.pages);     }; }

但當每次實例化時,類 Book 中包含的原型方法就會被重復創建,生成大量的原型方法,浪費系統資源??梢允褂?if 判斷原型方法是否存在,如果存在就不再創建該方法,否則就創建方法。

function Book (title, pages) {     this.title = title;     this.pages = pages;     if (typeof Book.isLock == "undefined") {  //創建原型方法的鎖,如果不存在則創建         Book.prototype.what = function () {             console.log(this.title + this.pages);         };         Book.isLock = true;  //創建原型方法后,把鎖鎖上,避免重復創建     } } var book1 = new Book("JavaScript 程序設計", 160); var book2 = new Book("C語言程序設計", 240); console.log(book1.title); console.log(book2.title);

typeof Book.isLock 表達式能夠檢測該屬性值的類型,如果返回為 undefined 字符串,則不存在該屬性值,說明沒有創建原型方法,并允許創建原型方法,設置該屬性的值為 true,這樣就不用重復創建原型方法。這里使用類名 Book,而沒有使用 this,這是因為原型是屬于類本身的,而不是對象實例的。

動態原型模式與構造原型模式在性能上是等價的,用戶可以自由選擇,不過構造原型模式應用比較廣泛。

工廠模式

工廠模式是定義類型的最基本方法,也是 JavaScript 最常用的一種開發模式。它把對象實例化簡單封裝在一個函數中,然后通過調用函數,實現快速、批量生產實例對象。

示例1

下面示例設計一個 Car 類型:包含汽車顏色、驅動輪數、百公里油耗 3 個屬性,同時定義一個方法,用來顯示汽車顏色。

function Car (color, drive, oil) {  //汽車類     var _car =  new Object();  //臨時對象         _car.color = color;  //初始化顏色         _car.drive = drive;  //初始化驅動輪數         _car.oil = oil;  //初始化百公里油耗         _car.showColor = function () {  //方法,提示汽車顏色             console.log(this.color);         };         return _car;  //返回實例 } var car1 = Car("red", 4, 8); var car2 = Car("blue", 2, 6); car1.showColor();  //輸出“red” car2.showColor();  //輸出“blue”

上面代碼是一個簡單的工廠模式類型,使用 Car 類可以快速創建多個汽車實例,它們的結構相同,但是屬性不同,可以初始化不同的顏色、驅動輪數和百公里油耗。

示例2

在類型中,方法就是一種行為或操作,它能夠根據初始化參數完成特定任務,具有共性。因此,可以考慮把方法置于 Car() 函數外面,避免每次實例化時都要創建一次函數,讓每個實例共享同一個函數。

function showColor () {  //公共方法,提示汽車顏色     console.log(this.color); }; function Car (color, drive, oil) {  //汽車類     var _car = new Object();  //臨時對象         _car.color = color;  //初始化顏色         _car.drive = drive;  //初始化驅動輪數         _car.oil = oil;  //初始化百公里油耗         _car.showColor = showColor;  //引用外部函數     return _car;  //返回實例 }

在上面這段重寫的代碼中,在函數 Car() 之前定義了函數 showColor()。在 Car() 內部,通過引用外部 showColor() 函數,避免了每次實例化時都要創建一個新的函數。從功能上講,這樣解決了重復創建函數的問題;但是從語義上講,該函數不太像是對象的方法。

類繼承

類繼承的設計方法:在子類中調用父類構造函數。

在 JavaScript 中實現類繼承,需要注意以下 3 個技術問題。

在子類中,使用 apply 調用父類,把子類構造函數的參數傳遞給父類父類構造函數。讓子類繼承父類的私有屬性,即 Parent.apply(this, arguments); 代碼行。

在父類和子類之間建立原型鏈,即 Sub.prototype = new Parent(); 代碼行。通過這種方式保證父類和子類是原型鏈上的上下級關系,即子類的 prototype 指向父類的一個實例。

恢復子類的原型對象的構造函數,即 Sub.prototype.constructor=Sub;語句行。當改動 prototype 原型時,就會破壞原來的 constructor 指針,所以必須重置 constructor。

示例1

下面示例演示了一個三重繼承的案例,包括基類、父類和子類,它們逐級繼承。

//基類Base function Base (x) {  //構造函數Base     this.get = function () {  //私有方法,獲取參數值         return x;     } } Base.prototype.has = function () {  //原型方法,判斷get()方法返回值是否為0     return ! (this.get() == 0); } //父類Parent function Parent () {  //構造函數Parent     var a = [];  //私有數組a     a = Array.apply(a, arguments);  //把參數轉換為數組     Base.call(this, a.length);  //調用Base類,并把參數數組長度傳遞給它     this.add = function () {  //私有方法,把參數數組補加到數組a中并返回         return a.push.apply(a, arguments)     }     this.geta = function () {  //私有方法,返回數組a         return a;     } } Parent.prototype = new Base();  //設置Parent原型為Base的實例,建立原型鏈 Parent.prototype.constructor = Parent;  //恢復Parent類原型對象的構造器 Parent.prototype.str = function (){  //原型方法,把數組轉換為字符串并返回     return this.geta().toString(); } //子類Sub function Sub () {  //構造函數     Parent.apply(this, arguments);  //調用Parent類,并把參數數組長度傳遞給它     this.sort = function () {  //私有方法,以字符順序對數組進行排序         var a = this.geta();  //獲取數組的值         a.sort.apply(a, arguments);  //調用數組排序方法 sort()對數組進行排序     } } Sub.prototype = new Parent();  //設置Sub原型為Parent實例,建立原型鏈 Sub.prototype.constructor = Sub;  //恢復Sub類原型對象的構造器 //父類Parent的實例繼承類Base的成員 var parent = new Parent (1, 2, 3, 4);  //實例化Parent類 console.log(parent.get());  //返回4,調用Base類的方法get() console.log(parent.has());  //返回true,調用Base類的方法has() //子類Sub的實例繼承類Parent和類Base的成員 var sub = new Sub (30, 10, 20, 40);  //實例化Sub類 sub.add(6, 5);  //調用Parent類方法add(),補加數組 console.log(sub.geta());  //返回數組30,10,20,40,6,5 sub.sort();  //排序數組 console.log(sub.geta());  //返回數組10,20,30,40,5,6 console.log(sub.get());  //返回4,調用Base類的方法get() console.log(sub.has());  //返回true,調用Base類的方法has() console.log(sub.str());  //返回10,20,30,40,5,6

【設計思路】

設計子類 Sub 繼承父類 Parent,而父類 Parent 又繼承基類 Base。Base、Parent、Sub 三個類之間的繼承關系是通過在子類中調用的構造函數來維護的。

例如,在 Sub 類中,Parent.apply(this, arguments); 能夠在子類中調用父類,并把子類的參數傳遞給父類,從而使子類擁有父類的所有屬性。

同理,在父類中,Base.call(this, a.length); 把父類的參數長度作為值傳遞給基類,并進行調用,從而實現父類擁有基類的所有成員。

從繼承關系上看,父類繼承了基類的私有方法 get(),為了確保能夠繼承基類的原型方法,還需要為它們建立原型鏈,從而實現原型對象的繼承關系,方法是添加語句行 Parent.prototype=new Base();。

同理,在子類中添加語句 Sub.prototype=new Parent();,這樣通過原型鏈就可以把基類、父類和子類串連在一起,從而實現子類能夠繼承父類屬性,還可以繼承基類的屬性。

示例2

下面嘗試把類繼承模式封裝起來,以便規范代碼應用。

function extend (Sub, Sup) {  //類繼承封裝函數     var F = function () {};  //定義一個空函數     F.prototype = Sup.prototype;  //設置空函數的原型為父類的原型     Sub.prototype = new F ();  //實例化空函數,并把父類原型引用傳給給子類     Sub.prototype.constructor = Sub;  //恢復子類原型的構造器為子類自身     Sub.sup = Sup.prototype;  //在子類定義一個私有屬性存儲父類原型     //檢測父類原型構造器是否為自身     if (Sup.prototype.constructor == Object.prototype.constructor) {         Sup.prototype.constructor = Sup;  //類繼承封裝函數     } }

【操作步驟】

1) 定義一個封裝函數。設計入口為子類和父類對象,函數功能是子類能夠繼承父類的所有原型成員,不涉及出口。

function extend (Sub, Sup) {  //類繼承封裝函數     //其中參數Sub表示子類,Sup表示父類 }

2) 在函數體內,首先定義一個空函數 F,用來實現功能中轉。設計它的原型為父類的原型,然后把空函數的實例傳遞給子類的原型,這樣就避免了直接實例化父類可能帶來的系統負荷。因為在實際開發中,父類的規模可能會很大,如果實例化,會占用大量內存。

3) 恢復子類原型的構造器為子類自己。同時,檢測父類原型構造器是否與 Object 的原型構造器發生耦合。如果是,則恢復它的構造器為父類自身。

下面定義兩個類,嘗試把它們綁定為繼承關系。

function A (x) {  //構造函數A     this.x = x;  //私有屬性x     this.get = function () {  //私有方法get()         return this.x;     } } A.prototype.add = function () {  //原型方法add()     return this.x + this.x; } A.prototype.mul = function () {  //原型方法mul()     return this.x * this.x; } function B (x) {  //構造函數B     A.call (this.x);  //在函數體內調用構造函數A,實現內部數據綁定 } extend (B, A);  //調用封裝函數,把A和B的原型捆綁在一起 var f = new B (5);  //實例化類B console.log(f.get());  //繼承類A的方法get(),返回5 console.log(f.add());  //繼承類A的方法add(),返回10 console.log(f.mul());  //繼承類A的方法mul(),返回25

在函數類封裝函數中,有這么一句 Sub.sup=Sup.prototype;,在上面代碼中沒有被利用,那么它有什么作用呢?為了解答這個問題,先看下面的代碼。

extend (B, A); B.prototype.add = function () {  //為B類定義一個原型方法     return this.x + "" + this.x; }

上面的代碼是在調用封裝函數之后,再為 B 類定義了一個原型方法,該方法名與基類中原型方法 add() 同名,但是功能不同。如果此時測試程序,會發現子類 B 定義的原型方法 add() 將會覆蓋父類 A 的原型方法 add()。

console.log(f.add());  //返回字符串55,而不是數值10

如果在 B 類的原型方法 add() 中調用父類的原型方法 add(),避免代碼耦合現象發生。

B.prototype.add = function () {  //定義子類B的原型方法add()     return B.sup.add.call(this);  //在函數內部調用父類方法add() }

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
黄网站色视频免费观看| 国产成人片一区在线观看| 91人人澡人人爽内射电影院| JIZZ在线观看中国少妇| 插花弄玉小说荔枝很甜作者卿凌| 粉嫩av一区二区三区四区| 国产成人亚洲精品无码综合原创 | 日日摸夜夜添夜夜添影院| 日本一线产区和韩国二线产区区别 | 亚洲精品国产AV现线| 亚洲精品无码鲁网中文电影| 亚洲AV无码丰满尖叫高潮| 亚洲综合日韩AV无码毛片| 最新中文字幕AV专区| 草莓丝瓜向日葵黄瓜榴莲IOS| 国产白嫩护士被弄高潮| 精产国品一二三产区区别在线观看 | 亚洲欧美综合精品AⅤ一区二区| 中文成人无码精品久久久不卡免费 | 猫咪AV成人永久网站| 日韩AV高清在线观看| 亚洲AV片在线观看| 中文字幕亚洲无线码| 俄罗斯PONONDLX| 激情欧美成人小说在线视频| 男男GAY无套国产| 熟妇人妻久久中文字幕老熟妇| 亚洲高清国产AV拍精品青青草原 | 亚洲精品国产AⅤ成拍色拍| 中文字幕无码家庭乱欲| 大号BBVVBBW高潮| 激情内射亚州一区二区三区爱妻| 女人越喊男人越往里寨电视剧| 天天躁日日躁狠狠躁欧美老妇小说 | 又粗又大又爽又舒服日产| 成人免费无码大片A毛片直播| 国内精品久久久久影院中文字幕 | FREE国产粉嫩熟妇XXXHD| 国产美女视频国产视视频| 乱码精品一区二区三区| 四虎国产精品永久在线动漫| 夜夜爽77777妓女免费看| 成人无码专区免费播放三区 | 亚洲AV片无码久久尤物| 97在线视频人妻无码| 国产色欲AV一区二区三区| 男人的天堂在线视频| 无码人妻精品一区二区三| 做AJ的姿势教程大全图| 国产精品亚韩精品无码A在线| 麻花传媒MD0076沈芯语在线| 无码AV高潮喷水无码专区线| 中文字幕无线码中文字幕免费 | 无码免费一区二区三区免费播放| 中文国产成人精品久久| 国产精品久久久久精品日日| 妺妺坐在我腿上勃起弄了应用 | chineSe老女人老熟妇hd| 好爽好紧好大的免费视频国产 | 欧美成人V片观看| 亚洲AV无码一区二区二三区入口| CHINAGARY武警体育飞机| 狠狠躁夜夜人人爽天96| 日韩人妻无码精品-专区| 一二三四在线观看免费高清视频| 国产92刮伦脏话对白| 免费无码观看的AV在线播放| 亚洲AV中文无码字幕色本草| 成人精品一区二区三区中文字幕| 久久久WWW成人免费毛片| 无码国产精品久久一区免费| MONSTER无删减动漫| 久久久久人妻精品一区三寸| 无套内射GIF舔B吃奶| 薄荷奶糖(1V2)笔趣| 可以C女性角色的游戏手游| 亚洲 欧美 叧类人妖| 成人Av无码一区二区三区| 麻花传媒网站永久入口视频| 亚洲AV无码成人片在线观看一区 | 强行糟蹋人妻HD中文字幕| 欧美伊人久久大香线蕉综合| 亚欧色一区W666天堂| 成人欧美一区二区三区性视频 | 免费国产AV在线观看| 色综合色综合久久综合频道88| 四虎永久免费地址WW41.6| 综合色天天鬼久久鬼色| 精品久久久久久久无码| 无码精品国产VA在线观看DVD| 凹凸在线无码免费视频| 没带罩子让他捏了一节课| 亚洲A级成人无码网站| 国产成人亚洲日韩欧美| 亚洲综合一区国产精品| 亚洲AV区无码字幕中文色| 隔壁邻居是巨爆乳寡妇| 欧美亚洲国产片在线播放| 再深点灬舒服灬太大了AV| 精品国内在视频线2019| 性色a∨精品高清在线观看| 国产97色在线 | 国产| 人人爽人人爽人人爽| 91精品人妻一区二区三区蜜桃| 久久久久亚洲AV无码去区首| 亚洲AV永久无码精品成人| 国产蜜芽尤物在线一区| 天天躁夜夜踩很很踩2022| 菠萝蜜视频在线观看| 欧美啪啪抽搐一进一出免费| 中文在线中文资源| 老赵抱着媛媛在厨房做| 一二三四在线观看免费中文| 久久高清内射无套| 亚洲欧美另类视频| 精品无码黑人又粗又大又长AV | 国产操熟女性爱导航| 日本熟妇WWW色视频在线播放| WWW久久无码天堂MV| 欧美性猛交乱大交3| AV无码免费无禁网站| 欧美老妇交乱视频在线观看| 18VIDEOSEX性欧美| 农村肥BWBWBWBWBW| 2021自拍偷在线精品自拍偷| 免费一看一级毛片少妇丰满2| 做AJ的姿势教程大全图| 欧美XXXX狂喷| FREE嫩白18SEX性HD处| 漂亮人妻洗澡被公强 日日躁| TPU色母能与PA6色母通用吗| 青青草原精品国产亚洲AV| 把腿张开老子cao烂你动态图| 日本VA视频免费在线观看| 成人无码精品无码社区| 日韩精品无码一本二本三本| 成人午夜福利免费无码视频| 日小骚B少妇真舒服| 国产电影在免费播放在线观看| 午夜DJ免费完整在线看网| 国内精品久久久久久久999| 亚洲精品国产第一综合99久久| 久久99国产亚洲高清观看首页| 夜夜高潮夜夜爽夜夜爱爱一区| 毛片无码免费无码播放| A级毛片内射免费视频| 人妻被按摩到潮喷中文字幕| 丁香色欲久久久久久综合网| 无码AV最新无码AV专区| 好吊妞人成视频在线观看27DU| 亚洲日产韩国一二三四区| 蜜臀AⅤ永久无码精品| Z Z〇Z〇另类女人ZOZ〇| 5566好久不见MP3免费下载| 乱码人妻一区二区三区| 中文字幕久久精品无码| 少妇高清一区二区免费看| А√最新版地址在线天堂| 日韩无码视频二区| 国产伦精品一区二区三区免费| 亚洲顶级裸体AV片| 满熟妇XXXX性久久9久久| 把腿张开老子cao烂你n视频| 婷婷色婷婷开心五月| 激情偷乱人伦小说视频最新章节 | www.AV无码| 四季AV无码专区AV| 精东传媒VS天美传媒合作| 中国内地毛片免费高清| 日本极品人妻VIDEOSSEX| 国产乱子伦精品无码码专区| 亚洲日韩中文字幕日本| 欧美精品少妇XXXXX喷水| 丰满少妇被猛烈进入无码| 亚洲AV无码无在线观看| 么公的粗大挺进了我的密道| 成人无码一区二区三区网站| 亚洲AV无码久久久久网站蜜桃| 旧芭乐视频官网下载地址IOS| ぱらだいす天堂官网链接| 午夜福利理论片高清在线观看| 久久久久蜜桃精品成人片公司| ZOOM与牛性胶ZOOM| 性欧美XXXX乳| 蜜桃AV不卡无码三区| 第一次挺进苏雨萌| 亚洲精品中文字幕乱码4区| 欧美VA久久久噜噜噜久久| 国产Ⅴ亚洲V天堂A无码| 亚洲色国产欧美日韩| 人与畜禽共性关系的重要性| 国产嫖妓风韵犹存对白| 中文字字幕人妻中文| 图片 小说 校园 激情 都市| 久久天天躁狠狠躁夜夜96流白浆| 成人毛片一区二区| 亚洲女和黑人最新AV| 日本极品少妇XXXX| 久久精品国产免费播高清无卡| 边做奶水边喷H高H共妻|