從來沒有正經寫個文,今天開始要改改了。。
javascript中的繼承無非是new 一個函數,稱為建構函式,叫什麼無所謂,都是函數function,
然後給這個方法的prototype添加一些方法,這些方法我們就說是繼承過來的。
javascript中有個概念叫做:“一切皆對象”,就是javascript存在都是對象,
一個對象有2種屬性,一種是繼承過來的,一種是自己的,
就像大自然的動物一樣,從最基礎的草履蟲到現在的人類,都是一代代的繼承擴充,實現豐富多樣的世界,javascript的世界也類比大自然的世界,包括其他語言也類似,軟體的世界就是在類比學習大自然規律。
回到正題,javascript本身語言中沒有實現標準的繼承方法,
那什麼是標準的繼承方法呢,就是一個語言中專門用來繼承的。
像php中有:
Ancestor{ //這裡面寫一大堆方法和屬性,私人、共有的等等 function __construct($options){ $this->options= $options; } function run(){ return 1; }};
關於上面的文法,不懂的php的可以不用理會了,把上面代碼寫好之後就可以new 一下Class ,返回了一個對象了,上面的方法和屬性可以在對象$obj使用了
$obj = new Ancestor(1);
然後繼承呢,就是下面這麼寫
Child extend Ancestor{ //裡面寫一大堆方法屬性,可以私人,可以公用等function __construct($options,$name){ //執行一下父類的__construct方法 parent::__construct(); $this->name= $name;} function run(){ $num = parent::__construct(); return $num +1; }}$childObj= new Child(1,'一隻柯楠');
上面的代碼就是Child繼承Ancestor的方法和屬性了。。執行個體化也是new一下
我們可以注意到當Child和Ancestor的方法重複時,我們可以使用parent::方法名來執行父類的方法,這樣既可以不覆蓋父類的方法,又可以自己擴充一些方法了,很方便。。。
關鍵到了,
javascript中是這樣實現的
var Ancestor= function(options){ this.options= options; this.run=function(){ return 1; }} //執行個體化Classvar obj= new Ancestor;//寫一個構造方法childvar Child= function(){ this.run= function(){ return 2; }}//讓child繼承Ancestor
Child.prototype= new Ancestor;
var childObj= new Child(1,'一隻柯楠');
//然後給child這裡繼承之後,Child的run方法肯定會覆蓋prototype裡面的run方法。
問題來了
1、我們這裡沒有一個標準方法,先調用父類的重名的方法
2、這樣寫Child.prototype= new Ancestor;很麻煩,很不規範,對於大項目來說很不統一可能有些人是這樣child.prototype.run= function(){}等。。
第一個問題的他解決辦法也是有的,不錯我個人認為比較搓,即是obj.run.apply(this,arguments);
var Ancestor= function(options){ this.options= options; this.run=function(){ return 1; }} //執行個體化Classvar obj= new Ancestor;//寫一個構造方法childvar Child= function(){ this.run= function(){ //這裡就是先調用父類的run方法,不過你得直接寫obj很不友好 var num = obj.run.apply(this,arguments); return num+1; }}//讓child繼承ClasshChild.prototype= obj;var childObj= new Child(1,'一隻柯楠');//然後給child這裡繼承之後,Child的run方法肯定會覆蓋prototype裡面的run方法。
我們需要一個統一的繼承方法解決上面的問題,我已經給大家寫了詳細的注釋,
好吧,
其實寫了上面那麼多就是為了引出它存在的意義:
(function(win,undefined){ var initializing = false, superTest = /vnice/.test(function () {vnice;}) ? /\b_super\b/ : /.*/; this.Class = function () {}; Class.extend = function (prop) { //_super和prototype:new建立一個新的對象,作為新類的prototype,不能直接在上面添加方法,會影響其他使用extend方法返回的類 var _super = this.prototype; //設為true就不再執行init方法 initializing = true; var prototype = new this(); initializing = false; //將傳進來的prop對象裡的方法拷貝到prototype上面去 for (var name in prop) { prototype[name] = (typeof prop[name] === 'function' && typeof _super[name] === 'function' && superTest.test(prop[name])) ? (function (name, fn) { //這一步為了實現,prop裡面的某個方法(如prop.init)和原型prototype方法中的方法衝突時,可以在方法中調用【this._super()】,這裡將this._super方法替換成原型中的這個方法(prototype.init). return function () { var temp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = temp; return ret; } })(name, prop[name]) : prop[name]; } function Class () { //建構函式中預設調用this.init方法 if (!initializing && this.init) { this.init.apply(this, arguments); } } //讓將要返回的類繼承prototype Class.prototype = prototype; //將類的建構函式設為Class Class.constructor = Class; //將類添加extend方法,方便繼續繼承 Class.extend = arguments.callee; //返回建構函式 return Class; };})(window,undefined)
上面的方法怎麼使用呢???
(function(){//class類的實現var Ancestor= Class.extend({ init: function(options){ this.options= options; }, run: function(){ return 1; }});//執行個體化Class類var obj= new Ancestor();var Child= Ancestor.extend({ init: function(options,name){ //執行父類的init方法,類似PHP中的parent::init(); this._super(); this.name= name }, run: function(){ var num= this._super(); return num+1; }});var childObj= new Child(1,'一隻柯楠');})()
這樣就可以生生不息,的繼承擴充了。。說的不對的地方歡迎大牛指正。。。