javascript繼承方式的簡單介紹

javascript實現繼承有哪些方式

Javascript的繼承在很多書里面細致的分了很多種類型和實現方式,大體上就是兩種:對象冒充、原型方式。這兩種方式各有優(yōu)點和缺陷,這里我給你先列舉出來,再從底層分析區(qū)別:

創(chuàng)新互聯建站是一家專注于成都做網站、成都網站制作與策劃設計,靈臺網站建設哪家好?創(chuàng)新互聯建站做網站,專注于網站建設10年,網設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:靈臺等地區(qū)。靈臺做網站價格咨詢:13518219792

(一)對象冒充

function A(name){

this.name = name;

this.sayHello = function(){alert(this.name+” say Hello!”);};

}

function B(name,id){

this.temp = A;

this.temp(name); //相當于new A();

delete this.temp; //防止在以后通過temp引用覆蓋超類A的屬性和方法

this.id = id;

this.checkId = function(ID){alert(this.id==ID)};

}

當構造對象B的時候,調用temp相當于啟動A的構造函數,注意這里的上下文環(huán)境中的this對象是B的實例,所以在執(zhí)行A構造函數腳本時,所有A的變量 和方法都會賦值給this所指的對象,即B的實例,這樣子就達到B繼承了A的屬性方法的目的。之后刪除臨時引用temp,是防止維護B中對A的類對象(注 意不是實例對象)的引用更改,因為更改temp會直接導致類A(注意不是類A的對象)結構的變化。

我們看到了,在Js版本更新的過程中,為了更方便的執(zhí)行這種上下文this的切換以達到繼承或者更加廣義的目的,增加了call和apply函數。它們的 原理是一樣的,只是參數不同的版本罷了(一個可變任意參數,一個必須傳入數組作為參數集合)。這里就以call為例子,解釋一下用call實現的對象冒充 繼承。

function Rect(width, height){

this.width = width;

this.height = height;

this.area = function(){return this.width*this.height;};

}

function myRect(width, height, name){

Rect .call(this,width,height);

this.name = name;

this.show = function(){

alert(this.name+” with area:”+this.area());

}

}

關于Call方法,官方解釋:調用一個對象的一個方法,以另一個對象替換當前對象。

call (thisOb,arg1, arg2…)

這也是一種對象冒充的繼承,其實在call方法調用的時候發(fā)生的事情也是上下文環(huán)境變量this的替換,在myRect函數體中this肯定是指向類 myRect對象的實例了,然而用這個this作為上下文環(huán)境變量調用名字叫Rect方法,即類Rect的構造函數。于是此時調用Rect時候對this 的賦值屬性和方法都實際上是對一個myRect的對象進行。所以說盡管call和apply并不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。

對象冒充繼承就是這么一回事,它可以實現多重繼承,只要重復做這一套賦值的流程就可以了。不過目前真正大規(guī)模使用得并不多,為什么呢?因為它有一個明顯的 性能缺陷,這就要說道OO的概念了,我們說對象是成員+成員方法的集合,構造對象實例的時候,這些實例只需要擁有各自的成員變量就可以了,成員方法只是一 段對變量操作的可執(zhí)行文本區(qū)域而已,這段區(qū)域不用為每個實例而復制一份,所有的實例都可以共享。現在回到Js利用對象冒充模擬的繼承里,所有的成員方法都 是針對this而創(chuàng)建的,也就是所所有的實例都會擁有一份成員方法的副本,這是對內存資源的一種極度浪費。其它的缺陷比如說對象冒充無法繼承 prototype域的變量和方法就不用提了,筆者認為前一個致命缺陷就已經足夠。不過,我們還是需要理解它,特別是父類的屬性和方法是如何繼承下來的原 理,對于理解Js繼承很重要。

(二)原型方式

第二種繼承方式是原型方式,所謂原型方式的繼承,是指利用了prototype或者說以某種方式覆蓋了prototype,從而達到屬性方法復制的目的。 其實現方式有很多中,可能不同框架多少會有一點區(qū)別,但是我們把握住原理,就不會有任何不理解的地方了??匆粋€例子(某一種實現):

function Person(){

this.name = “Mike”;

this.sayGoodbye = function(){alert(“GoodBye!”);};

}

Person.prototype.sayHello = function(){alert(”Hello!”);};

function Student(){}

Student.prototype = new Person();

關鍵是對最后一句Student原型屬性賦值為Person類構造的對象,這里筆者解釋一下父類的屬性和方法是如何copy到子類上的。Js對象在讀取某 個對象屬性的時候,總是先查看自身域的屬性列表,如果有就返回否則去讀取prototype域(每個對象共享構造對象的類的prototype域所有屬性 和方法),如果找到就返回,由于prototype可以指向別的對象,所以Js解釋器會遞歸的去查找prototype域指向對象的prototype 域,直到prototype為本身,查找變成了一種循環(huán),就停止,此時還沒找到就成undefined了。

這樣看來,最后一句發(fā)生的效果就是將父類所有屬性和方法連接到子類的prototype域上,這樣子類就繼承了父類所有的屬性和方法,包括name、 sayGoodbye和sayHello。這里與其把最后一句看成一種賦值,不如理解成一種指向關系更好一點。這種原型繼承的缺陷也相當明顯,就是繼承時 父類的構造函數時不能帶參數,因為對子類prototype域的修改是在聲明子類對象之后才能進行,用子類構造函數的參數去初始化父類屬性是無法實現的, 如下所示:

function Person(name){

this.name = name;

}

function Student(name,id){

this.id = id;

}

Student.prototype = new Person(this.name);

兩種繼承方式已經講完了,如果我們理解了兩種方式下子類如何把父類的屬性和方法“抓取”下來,就可以自由組合各自的利弊,來實現真正合理的Js繼承。下面是個人總結的一種綜合方式:

function Person(name){

this.name = name;

}

Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);};

function Student(name,id){

Person.call(this,name);

this.id = id;

}

Student.prototype = new Person();

Student.prototype.show = function(){

alert(“Name is:”+ this.name+” and Id is:”+this.id);

}

總結就是利用對象冒充機制的call方法把父類的屬性給抓取下來,而成員方法盡量寫進被所有對象實例共享的prototype域中,以防止方法副本重復創(chuàng) 建。然后子類繼承父類prototype域來抓取下來所有的方法。如想徹底理清這些調用鏈的關系,推薦大家多關注Js中prototype的 constructor和對象的constructor屬性,這里就不多說了。

vue模塊中如何使用javascript類繼承

1、首先確定一個vue模塊,點擊編輯。

2、其次選擇繼承方式為類繼承。

3、最后直接點擊選擇使用javascript類繼承即可保存。

js原型鏈和繼承的理解

Object() Function() Array() 等等都為構造函數。

Js 面向對象與傳統(tǒng)oop 有些不同,語法較高級 語法糖封裝。

This 為指針。指向this作用域的調用者

1.原型繼承鏈頂端為Object 。Js函數是對象

2.當讀取對象中的屬性時,先去實例本身中搜索,如搜索不到則去指向的原型中搜索

1.原型的存在意義在于實現繼承共享,是在構造函數中定義的一個成員對象,在下次實例化時不需要在構造函數中定義成員 就可實現實例共享方法屬性。

例子:通常為。 構造函數.prototype.xxx=我想實現實例繼承的東西 -》 new 構造函數 -》新實例a對象.原型指針指向構造函數的xxx對象(引用類型)

例子:Array 不等于 Array() 原因 Array為一個函數,而Array()為一個構造函數調用語句,故Array擁有prototype對象用于實例的共享繼承,Array()產生一個實例 故只能擁有prototype對象的私有指針 proto

2.在使用原型繼承時 不能使用字面量 構造函數.prototype={} 的方式重寫原型對象 。因為會導致該原型對象的constructor屬性被重寫,在生成的實例中導致constructor指向Object并且會切斷之前原型對象的聯系,破壞原型鏈。

3.JavaScript 主要通過原型鏈實現繼承。原型鏈的構建是通過將一個類型的實例賦值給另一個構造函數的原型實現的

例子:

xxx實例. proto -》function xxx()構造函數.prototype對象故xxx. proto === xxx.prototype

xxx.prototype. proto -》Object.prototype因為所有對象都為Object函數構造來的。故xxx.prototype. proto ===Object.prototype。

Object.prototype. proto 為原型鏈頂端 proto 定義了尚未使用所以為null故Object.prototype. proto ===null約定俗成。

instanceof 用來判斷某實例是否為某構造函數的實例

isPrototypeOf 用于判斷某實例是否擁有某構造函數的原型對象指針

1.原型模式有忽略構造函數定義初始值步驟及原型中操作引用類型的缺點。

所以需要組合使用 構造函數模式+原型模式 來創(chuàng)建實例。在構造函數中定義實例的屬性,而需共享的方法就定義在原型對象中。

繼承:在子構造函數中調用 父.call(this, name); 實現構造函數之間的屬性繼承。使用 子.prototype = new 父(); 子.prototype.constructor = 子;實現方法的繼承。

2.如要在生產環(huán)境下的構造函數新增方法(如Array) 需要使用一個類似于工廠函數的寄生構造函數模式 在構造函數中返回一個修改后的對象

JavaScript六種繼承方式?

繼承是面向對象編程中又一非常重要的概念,JavaScript支持實現繼承,不支持接口繼承,實現繼承主要依靠原型鏈來實現的。

原型鏈

首先得要明白什么是原型鏈,昆明北大青鳥建議可以在一篇文章看懂proto和prototype的關系及區(qū)別中講得非常詳細

原型鏈繼承基本思想就是讓一個原型對象指向另一個類型的實例

添加方法

在給SubType原型添加方法的時候,如果,父類上也有同樣的名字,SubType將會覆蓋這個方法,達到重新的目的。但是這個方法依然存在于父類中。

記住不能以字面量的形式添加,因為,上面說過通過實例繼承本質上就是重寫,再使用字面量形式,又是一次重寫了,但這次重寫沒有跟父類有任何關聯,所以就會導致原型鏈截斷。

問題

單純的使用原型鏈繼承,主要問題來自包含引用類型值的原型。

借用構造函數

此方法為了解決原型中包含引用類型值所帶來的問題。

這種方法的思想就是在子類構造函數的內部調用父類構造函數,可以借助apply()和call()方法來改變對象的執(zhí)行上下文

傳遞參數

借助構造函數還有一個優(yōu)勢就是可以傳遞參數

js中繼承的幾種用法總結

一,js中對象繼承

js中有三種繼承方式

1.js原型(prototype)實現繼承

復制代碼 代碼如下:

SPAN style="BACKGROUND-COLOR: #ffffff"SPAN style="FONT-SIZE: 18px"html

body

script type="text/javascript"

function Person(name,age){

this.name=name;

this.age=age;

}

Person.prototype.sayHello=function(){

alert("使用原型得到Name:"+this.name);

}

var per=new Person("馬小倩",21);

per.sayHello(); //輸出:使用原型得到Name:馬小倩

function Student(){}

Student.prototype=new Person("洪如彤",21);

var stu=new Student();

Student.prototype.grade=5;

Student.prototype.intr=function(){

alert(this.grade);

}

stu.sayHello();//輸出:使用原型得到Name:洪如彤

stu.intr();//輸出:5

/script

/body

/html/SPAN/SPAN

2.構造函數實現繼承

復制代碼 代碼如下:

SPAN style="FONT-SIZE: 18px"html

body

script type="text/javascript"

function Parent(name){

this.name=name;

this.sayParent=function(){

alert("Parent:"+this.name);

}

}

function Child(name,age){

this.tempMethod=Parent;

this.tempMethod(name);

this.age=age;

this.sayChild=function(){

alert("Child:"+this.name+"age:"+this.age);

}

}

var parent=new Parent("江劍臣");

parent.sayParent(); //輸出:“Parent:江劍臣”

var child=new Child("李鳴",24); //輸出:“Child:李鳴 age:24”

child.sayChild();

/script

/body

/html/SPAN

3.call , apply實現繼承

復制代碼 代碼如下:

SPAN style="FONT-SIZE: 18px"html

body

script type="text/javascript"

function Person(name,age,love){

this.name=name;

this.age=age;

this.love=love;

this.say=function say(){

alert("姓名:"+name);

}

}

//call方式

function student(name,age){

Person.call(this,name,age);

}

//apply方式

function teacher(name,love){

Person.apply(this,[name,love]);

//Person.apply(this,arguments); //跟上句一樣的效果,arguments

}

//call與aplly的異同:

//1,第一個參數this都一樣,指當前對象

//2,第二個參數不一樣:call的是一個個的參數列表;apply的是一個數組(arguments也可以)

var per=new Person("武鳳樓",25,"魏熒屏"); //輸出:“武鳳樓”

per.say();

var stu=new student("曹玉",18);//輸出:“曹玉”

stu.say();

var tea=new teacher("秦杰",16);//輸出:“秦杰”

tea.say();

/script

/body

/html/SPAN

二、call和apply的用法(詳細介紹)

js中call和apply都可以實現繼承,唯一的一點參數不同,func.call(func1,var1,var2,var3)對應的apply寫法為:func.apply(func1,[var1,var2,var3])。

JS手冊中對call的解釋:

復制代碼 代碼如下:

SPAN style="FONT-SIZE: 18px"call 方法

調用一個對象的一個方法,以另一個對象替換當前對象。

call([thisObj[,arg1[, arg2[, [,.argN]]]]])

參數

thisObj

可選項。將被用作當前對象的對象。

arg1, arg2, , argN

可選項。將被傳遞方法參數序列。

說明

call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對象。

如果沒有提供 thisObj 參數,那么 Global 對象被用作 thisObj。/SPAN

說簡單一點,這兩函數的作用其實就是更改對象的內部指針,即改變對象的this指向的內容。這在面向對象的js編程過程中有時是很有用的。下面以apply為例,說說這兩個函數在 js中的重要作用。如:

復制代碼 代碼如下:

SPAN style="FONT-SIZE: 18px" function Person(name,age){ //定義一個類

this.name=name; //名字

this.age=age; //年齡

this.sayhello=function(){alert(this.name)};

}

function Print(){ //顯示類的屬性

this.funcName="Print";

this.show=function(){

var msg=[];

for(var key in this){

if(typeof(this[key])!="function"){

msg.push([key,":",this[key]].join(""));

}

}

alert(msg.join(" "));

};

}

function Student(name,age,grade,school){ //學生類

Person.apply(this,arguments);//比call優(yōu)越的地方

Print.apply(this,arguments);

this.grade=grade; //年級

this.school=school; //學校

}

var p1=new Person("卜開化",80);

p1.sayhello();

var s1=new Student("白云飛",40,9,"岳麓書院");

s1.show();

s1.sayhello();

alert(s1.funcName);/SPAN

另外,Function.apply()在提升程序性能方面有著突出的作用:

我們先從Math.max()函數說起,Math.max后面可以接任意個參數,最后返回所有參數中的最大值。

比如

復制代碼 代碼如下:

SPAN style="FONT-SIZE: 18px"alert(Math.max(5,8)); //8

alert(Math.max(5,7,9,3,1,6)); //9

//但是在很多情況下,我們需要找出數組中最大的元素。

var arr=[5,7,9,1];

//alert(Math.max(arr)); // 這樣卻是不行的。NaN

//要這樣寫

function getMax(arr){

var arrLen=arr.length;

for(var i=0,ret=arr[0];iarrLen;i++){

ret=Math.max(ret,arr[i]);

}

return ret;

}

alert(getMax(arr)); //9

//換用apply,可以這樣寫

function getMax2(arr){

return Math.max.apply(null,arr);

}

alert(getMax2(arr)); //9

//兩段代碼達到了同樣的目的,但是getMax2卻優(yōu)雅,高效,簡潔得多。

//再比如數組的push方法。

var arr1=[1,3,4];

var arr2=[3,4,5];

//如果我們要把 arr2展開,然后一個一個追加到arr1中去,最后讓arr1=[1,3,4,3,4,5]

//arr1.push(arr2)顯然是不行的。 因為這樣做會得到[1,3,4,[3,4,5]]

//我們只能用一個循環(huán)去一個一個的push(當然也可以用arr1.concat(arr2),但是concat方法并不改變arr1本身)

var arrLen=arr2.length;

for(var i=0;iarrLen;i++){

arr1.push(arr2[i]);

}

//自從有了Apply,事情就變得如此簡單

Array.prototype.push.apply(arr1,arr2); //現在arr1就是想要的結果/SPAN

分享題目:javascript繼承方式的簡單介紹
本文來源:http://muchs.cn/article24/phisje.html

成都網站建設公司_創(chuàng)新互聯,為您提供商城網站、響應式網站、網站建設、外貿建站、關鍵詞優(yōu)化、定制網站

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

h5響應式網站建設