javascript中的繼承用法

本文實例彙總了javascript關於繼承的用法,但願本文所述對你們的javascript程序設計有所幫助。分享給你們供你們參考。具體以下:
代碼以下:javascript

/**
* 實現子類繼承父類,但不會產生多餘的屬性和方法
* @returns {Function}
*/
define(function(){
return function(subType, superType){
var proto = new Object(superType.prototype);
proto.constructor = subType;
subType.prototype = proto;
};
});
//——————————————————————————
define(function(){
function ostring(s)
{
this.str = s;
this.length = this.str.length;
}
ostring.prototype.show = function(){
alert(this.str);
};
return ostring;
});
//——————————————————————————
define(['inherit', 'ostring'], function(inherit, ostring){
function wstring(s){
//用call實現調用父類構造函數
ostring.call(this, s);
this.chlength = 2 * s.length;
}
//繼承其餘的屬性
inherit(wstring, ostring);
wstring.prototype.add = function(w)
{
alert(this.str + w);
};
return wstring;
});

1、用function實現:

function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
}
function Author(name, books) {
    this.inherit=person;
    this.inherit(name);
    this.books = books;
    
}
var au=new Author("dororo","Learn much");
au.name

或者同等效力的:java

function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
}
function Author(name, books) {
    Person.call(this, name);
    this.books = books;
    
}
var au=new Author("dororo","Learn much");
au.getName

因爲這只是將this做爲參數,調用父類Person的構造函數,把賦予父類的全部域賦予Author子類,因此任何父類Person構造函數以外的定義的域(原型prototype),子類都不會繼承。因此上面例子中,au.getName將是沒有被定義的(undefined),由於getName是在Person的原型對象中定義的。app

並且,子類的構造函數要在定義本身的域以前調用父類構造函數,省得子類的定義被父類覆蓋掉。也就是說,Author定義屬性book要在Person.call以後,不然會被Person中屬性覆蓋。同時,在子類中也最好不要用prototype來定義子類的函數域,由於在一個子類被new,實例化以後就要執行prototype,而後纔是調用父類的構造函數,這樣也容易被父類的屬性覆蓋掉。less

2、用prototype實現:

function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
}
function Author(name, books) {
    this.books = books;  
}
Author.prototype=new Person(name);
Author.prototype.constructor=Author;
Author.prototype.getBooks = function() {
    return this.books;
}
var au1=new Author("dororo1","Learn much");
var au2=new Author("dororo2","Learn less");
alert(au1.getName());
alert(au2.getName());

這種方法避免了function實現中,沒法繼承prototype的問題。由於 Author.prototype=new Person(name);new Person()實例會調用Person構造和原型的全部屬性。可是缺點是已經實例化了Author.prototype。因此當子類實例化的時候,全部非基本數據類型都是reference copy。因此上面例子中,不管實例au1,仍是au2返回的值都是dororo1.函數

3、用「混合」實現

function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
}
function Author(name, books) {
    this.base = new Person(name);
    for(var key in this.base){
        if(!this[key]){
           this[key]=this.base[key];
           }
           }
    this.book=books;
}
var au1=new Author("dororo1","work");
var au2=new Author("dororo2","play");
alert(au1.getName());
alert(au2.getName());
au1.book;
au2.book;
 

屬於擴展,把父類的全部域都拷貝到子類。徹底沒有上述兩方面的問題。
寄生組合模式)this

JS的繼承包括屬性的繼承和方法的繼承,他們分別經過不一樣的方法來實現。
1.屬性的繼承spa

屬性的繼承經過改變函數的執行環境來實現的。而改變函數的執行環境可使用call()和apply()兩種方法來實現。prototype

咱們首先建立一個Animal「類」(由於JS中沒有類的概念,這裏只是一個模擬,它實際上只是一個Function函數對象)。設計

function Animal(typeName) {
//爲當前方法的執行環境(this)添加一個屬性typeName
//可是執行環境(this)要執行這個函數的時候才能肯定
this.typeName = typeName;
this.colors = ["red","while"];
}
//想函數的原型裏 添加 兩個(對象共享的)的方法
Animal.prototype.Shout = function () { alert("我是:--" + this.typeName);};
Animal.prototype.Eat = function () { alert("我是:--" + this.typeName) };
//--定義一個獅子--「類」(其實就是一個函數)
function Lion(tn) {
//--執行Animal方法,並經過apply的第一個參數 修改了Animal的執行環境爲Lion的this
//一樣的,Lion的this,也要在執行的時候才能肯定是誰
Animal.apply(this,["獅子"]);//--繼承了父類的變量屬性,this由於是new了Lion,this是Lion
}
Lion.prototype = Animal.prototype; //繼承父類的方法,搞定--可是這寫很差,當子類再添加方法時候,父類一樣也有此方法,這是指針引用
Lion.prototype.Hunt = function () {
alert("我是:獅子,我要去捕獵~~·~");
}
var aminm = new Animal();
aminm.Hunt(); //---能夠訪問到子類的方法,這樣就很差了
//----那麼如何解決這個問題呢》??????
//---解決方案:繼承方法時候能夠這樣寫:
Lion.prototype = new Animal();//繼承父類的方法,把Animal對象賦給了prototype原型,其實它裏面也有屬性
var lion = new Lion(); //new 關鍵字除了建立的,還會修改Lion對象的執行環境爲Lion對象自己
// ---換句話說,就是new完了以後,Lion函數裏的this就是Lion函數自己了,而後調用Lion函數

new關鍵字做用解析:

而new關鍵字是十分偉大的,在上段代碼中,new關鍵字完成了如下幾項工做:指針

  1. 開闢堆空間,以準備存儲Lion對象
  2. 修改Lion對象自己的執行環境,使得Lion函數的this指向了Lion函數對象自己。
  3. 調用Lion「類」的「構造函數」,建立Lion對象
  4. 將Lion函數對象的堆地址賦值給變量l,這個時候l就指向了這個Lion函數對象
    lion.Shout();
    lion.Eat();

    可是這種繼承有個缺點:就是父類的構造函數的被調用了兩次,call一次,而後new又一次。

相關文章
相關標籤/搜索