js繼承實例講解,如何實現繼承js

本文目錄一覽:

關於JS實現繼承的方法都有哪一些?

定義一個父類:

// 定義一個動物類

function Animal (name) {

// 屬性

this.name = name || ‘Animal’;

// 實例方法

this.sleep = function(){

console.log(this.name + ‘正在睡覺!’);

}

}

// 原型方法

Animal.prototype.eat = function(food) {

console.log(this.name + ‘正在吃:’ + food);

1.原型鏈繼承

核心:將父類的實例作為子類的原型

function Cat(){

}

Cat.prototype = new Animal();

Cat.prototype.name = ‘cat’;

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.eat(‘fish’));

console.log(cat.sleep());

console.log(cat instanceof Animal); //true

console.log(cat instanceof Cat); //true

特點:

1.非常純粹的繼承關係,實例是子類的實例,也是父類的實例

2.父類新增的原型方法、屬性,子類都能訪問到

3.簡單,易於實現

缺點:

1.要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之後執行

(可以在cat構造函數中,為Cat實例增加實例屬性)

2.無法實現多繼承

3.來自原型對象的引用屬性被所有實例共享

4.創建子類實例時,無法向父類構造函數傳參

下面代碼解釋缺點3(注意是引用屬性):

function Super(){

this.val = 1;

this.arr = [1];

}

function Sub(){

// …

}

Sub.prototype = new Super(); // 核心

var sub1 = new Sub();

var sub2 = new Sub();

sub1.val = 2;

sub1.arr.push(2);

alert(sub1.val); // 2

alert(sub2.val); // 1

alert(sub1.arr); // 1, 2

alert(sub2.arr); // 1, 2

2.構造繼承

核心:使用父類的構建函數來增強子類實例,等於複製父類的實例屬性給子類(沒用到原型),除了call方法,也可以用apply()

function Cat(name){

Animal.call(this);

this.name = name || ‘Tom’;

}

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // false

console.log(cat instanceof Cat); // true

特點:

1.解決了1中,子類實例共享父類引用屬性的問題

2.創建子類實例時,可以向父類傳遞參數

3.可以實現多繼承(call多個父類對象)

缺點:

1.實例並不是父類的實例,只是子類的實例

2.只能繼承父類的實例屬性和方法,不能繼承原型屬性和方法

3.無法實現函數復用,每個子類都有父類的實例函數的副本,影響性能

3.實例繼承

核心:為父類實例添加新特性,作為子類實例返回

function Cat(name){

var instance = new Animal();

instance.name = name || ‘Tom’;

return instance;

}

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // true

console.log(cat instanceof Cat); // false

特點:

1.不限制調用方式,不管是new 子類()還是子類(),返回的對象都具有相同的效果

缺點:

1.實例是父類的實例,不是子類的實例

2.不支持多繼承

4. 拷貝繼承

核心:使用for…in將父類實例中的方法賦給子類實例

unction Cat(name){

var animal = new Animal();

for(var p in animal){

Cat.prototype[p] = animal[p];

}

Cat.prototype.name = name || ‘Tom’;

}

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // false

console.log(cat instanceof Cat); // true

特點:

1.支持多繼承

缺點:

1.效率較低,內存佔用高(因為要拷貝父類的屬性)

2.無法獲取父類不可枚舉的方法(for in無法訪問不可枚舉的方法)

5.組合繼承

核心:通過調用父類構造,繼承父類的屬性並保留傳參的優點,然後通過將父類實例作為子類原型,實現函數復用

function Cat(name){

Animal.call(this);

this.name = name || ‘Tom’;

}

Cat.prototype = new Animal();

//組合繼承需要修復構造函數的指向

Cat.prototype.constructor=Cat;

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // true

console.log(cat instanceof Cat); // true

特點:

1.彌補了方式2的缺陷,可以繼承實例屬性、方法,也可以繼承原型屬性、方法

2.既是子類的實例,也是父類的實例

3.不存在引用屬性的共享問題

4.可傳參

5.函數可復用

缺點:

1.調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)

6.寄生組合繼承

核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點

function Cat(name){

Animal.call(this);

this.name = name || ‘Tom’;

}

(function(){

// 創建一個沒有實例方法的類

var Super = function(){};

Super.prototype = Animal.prototype;

//將實例作為子類的原型

Cat.prototype = new Super();

//寄生組合繼承需要修復構造函數的指向

Cat.prototype.constructor=Cat;

})();

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // true

console.log(cat instanceof Cat); //true

特點:

1.堪稱完美

缺點:

1.實現較為複雜 (BY三人行慕課)

JS中關於繼承的幾種方式

1、原型鏈繼承

2、構造繼承

3、實例繼承

4、拷貝繼承

5、組合繼承

6、寄生組合繼承

js繼承之組合繼承

組合繼承,指的是將原型鏈和借用構造函數的技術組合在一塊,從而發揮二者之長的一種繼承模式。

紅寶書是這樣說的,其思路是使用原型鏈實現對原型屬性和方法的繼承,通過借用構造函數來實現對實例屬性的繼承,這樣,即通過在原型上定義方法實現了函數復用,又能保證每個實例都有自己的屬性。

下面我們看一個組合繼承的例子,沒有女朋友我們就new一個女朋友

組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優點,So,組合繼承成為了JavaScript中最常用的繼承模式。

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 方法可將一個函數的對象上下文從初始的上下文改變為由 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優越的地方

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卻優雅,高效,簡潔得多。

//再比如數組的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]]

//我們只能用一個循環去一個一個的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

原創文章,作者:NTSS,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/139803.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
NTSS的頭像NTSS
上一篇 2024-10-04 00:22
下一篇 2024-10-04 00:22

相關推薦

發表回復

登錄後才能評論