js中的繼承

來源:互聯網
上載者:User

標籤:

物件導向語言中都支援兩種繼承:介面繼承和實現繼承,但是由於js中函數沒有簽名(接收的參數類型和數量不同),所以無法實現介面繼承。

下面講講js中實現繼承的方法:

一、原型繼承

原型繼承:既繼承了父類的模板,又繼承了父類的原型對象。

function Person(name,age){    this.name=name;    this.age=age;}Person.prototype.sayName=function(){    alert(this.name);}function Boy(){}Boy.prototype=new Person(‘a‘,12);Boy.prototype.sayHello=function(){    alert(‘hello‘);}var boy=new Boy();alert(boy.name);//aboy.sayName();//aalert(boy.constructor);//function Person(...){...}alert(boy instanceof Person);//truealert(boy instanceof Boy);//true

 

由上可見,子類執行個體的建構函式指向了父類的建構函式(Boy.prototype指向了另一個原型,而這個原型的constructor是父類)。子類執行個體又是Person類又是Boy類。但是,有一個問題:若建構函式中需傳參,就必須要在new Person()上傳參,若在建立子類執行個體中傳參則會顯示undefined,如下:

function Person(name,age){    this.name=name;    this.age=age;}Person.prototype.sayName=function(){    alert(this.name);}function Boy(){}Boy.prototype=new Person();Boy.prototype.sayHello=function(){    alert(‘hello‘);}var boy=new Boy(‘a‘,12);alert(boy.name);//undefined

雖然它既繼承了父類的模板又繼承了父類的原型對象,但若是在子類中傳遞參數,則會被屏蔽。

原型繼承的圖解:

建構函式.prototype=原型

原型.constructor=建構函式

執行個體中的內部指標指向原型

function Person(){}Person.prototype.setName=function(){};var person=new Person();function Boy(){}Boy.prototype=person;var boy=new Boy();

繼承調用方法的搜尋步驟:①搜尋執行個體 ②搜尋子類.prototype ③ 搜尋父類.prototype

二、借用建構函式的方式繼承

這種繼承只繼承模板,而不繼承原型對象,這就會導致函數無法複用。

function Person(name,age){  this.name=name;  this.age=age;}function Boy(name,age){    Person.call(this,‘a‘);//繼承了父類的模板 } var boy=new Boy(); alert(boy.name);//a
三、組合繼承(最常用的繼承模式)

組合繼承是將原型繼承和借用建構函式結合起來。

function Person(name,age){    this.name=name;    this.age=age;}Person.prototype.sayName=function(){    alert(this.name);}function Boy(name,age,sex){    this.sex=sex;    Person.call(this,name,age);}Boy.prototype=new Person();Boy.prototype.sayHello=function(){alert(‘hello‘);}var boy=new Boy(‘a‘,12,‘男‘);alert(boy.name);//aalert(boy.sex);//男boy.sayName();//aboy.sayHello();//hello
但是這種繼承由於Person.call()繼承了一次父類的模板,又因Boy.prototype=new Person(),繼承了一次原型對象,並且又繼承了一次模板。這就導致繼承了兩次父類的模板。那我們能不能直接將父類原型賦給子類原型呢?
function Person(name,age){    this.name=name;    this.age=age;}Person.prototype.sayName=function(){    alert(this.name);}function Boy(name,age,sex){    this.sex=sex;}Boy.prototype.sayHello=function(){alert(‘hello‘);}Boy.prototype=new Person();var boy=new Boy(‘a‘,12,‘男‘);alert(boy.name);//aalert(boy.sex);//男alert(boy.constructor);boy.sayName();//aboy.sayHello();//報錯

不行,因為若直接將父類原型賦給子類原型,則當調用子類原型中定義的方法將會報錯:Uncaught TypeError: boy.sayHello is not a function。那麼我們要如何解決這個問題呢?

我們可以自己定義一個只繼承父類原型對象的方法:

function extend(sub,sup){    function F(){};//建立一個空的建構函式    F.prototype=sup.prototype;//將父類的原型賦給空建構函式的原型    sub.prototype=new F();    sub.prototype.constructor=sub;//還原子類的建構函式    sub.superClass=sup.prototype;//儲存父類的原型對象    if(sub.prototype.constructor==Object.prototype.constructor){        sub.prototype.constructor=sub;//防止子類的建構函式是object    }    }function Person(name,age){    this.name=name;    this.age=age;}Person.prototype.sayName=function(){    alert(this.name);}function Boy(name,age,sex){    this.sex=sex;   Boy.superClass.constructor.call(this,name,age);//之前儲存的原型對象在這裡就起到瞭解除耦合的作用了}extend(Boy,Person);Boy.prototype.sayHello=function(){alert(‘hello‘);}var boy=new Boy(‘a‘,12,‘男‘);alert(boy.name);//aalert(boy.sex);//男boy.sayName();//aboy.sayHello();//hello

這樣就會只繼承一次父類的模板和一次原型對象。上面的判斷建構函式是為了如果對下面的原型對象上設定了一個以對象字面量形式建立的新對象,那麼此原型對象的constructor屬性會變成新的constructor屬性,不再指向原來的建構函式,而是指向了Object。

上面的這種方法就是所謂的寄生組合式繼承。他結合了原型式繼承和寄生式繼承,是參考型別最理想的繼承方式。

那麼什麼是原型式繼承,什麼是寄生式繼承?

四、原型式繼承

在一個函數內建立一個空建構函式,將傳入的對象作為空白建構函式的原型,然後返回空建構函式的執行個體。這種繼承必須要有一個對象作為另一個對象的基礎。

function object(obj){    function F(){};    F.prototype=obj;    return new F();}var person={    name:‘a‘,    age:12};var person2=object(person);alert(person.name);//aalert(person2.name);//a

這種繼承適用於只想讓一個對象與另一個對象保持類似。

在ECMA5中新增了Object.create(用作新對象原型的對象,為新對象定義額外屬性的對象)方法,此方法和我們定義的object()的作用差不多。

支援的瀏覽器:IE 9+ 、Firefox 4+、Safari 5+、Opera 12+、Chrome。

五、寄生式繼承

在內部以某種方式增強對象,再返回此對象。

function object(obj){    function F(){};    F.prototype=obj;    return new F();}function createAnother(sup){    var o=object(sup);    o.sayHello=function(){      alert(‘hello‘);    };    return o;    }var person={    name:‘a‘,    age:12    };var person2=createAnother(person);person2.sayHello();//hello

這種繼承方式適用於對象不是自訂類型和建構函式。

 

 

js中的繼承

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.