本文實例彙總了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; });
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
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.函數
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關鍵字完成了如下幾項工做:指針
lion.Shout();
lion.Eat();
可是這種繼承有個缺點:就是父類的構造函數的被調用了兩次,call一次,而後new又一次。