在繼承方面,js仍是弱項呀。發如今繼承的時候constructor和initialize之分。網上文章沒有說明兩者關係。看了源碼才發現兩者的區別呀。javascript
首先我用coffeescript來實現js的繼承,過程當中發現一個問題。java
就是經過用Backbone來構造單頁面程序的時候,若是父類或子類中定義了constructor而沒有super。那麼很高興的告訴你,在子類註冊的events是不工做滴。app
這裏提早告訴你是由於父類中若是沒有super,擇不會執行默認的構造器來構造Backbone.View類。而這個類在構造的時候工做是初始化類中的initialize和綁定events事件(基於Jquery的delegate)函數
不信你試試看。例如:this
class OA extends Backbone.View constructor:-> #super; console.log "OA constructor"; initialize :-> console.log "OA init"; class A extends OA constructor:-> #super; console.log "A constructor"; initialize:-> console.log "A init"; events : "click #btn1" : "btnClick" btnClick : -> console.log "btn click 1";
就是這樣你在A中定義了constructor,而沒有執行super,或者你在A中定義了construto且定義了super而在OA中的construtor構造中沒有super。子類A中的events就沒有執行。spa
根據這個一步步分析緣由。prototype
1:coffeescript在定義類中,若是類中沒有構造constructor,則它會本身構造constructor。若是指定了constructor那麼就會按照指定的來執行.code
源碼:對象
指定了constructor繼承
OA = (function(){ function e(){console.log("OA constructor")} })(Backbone.View)
未定義construto或定義而且super了
__extend = function(t,n){ function i(){ this.constructor = t; } for(var r in n) e.call(n,r) && (t[r]=n[r]); i.prototype = n.prototype; t.prototype = new i; t.__super__ = n.prototype; return t; } OA = (function(n){ function e(){ console.log("OA constructor") _ref = e.__super__.constructor.apply(this,arguments);//這個等價於Backbone.View.prototype.constructor.apply(this,arguments); } __extend(e,n);//這個是用來繼承的。 })(Backbone.View)
ok刨到這裏還得繼續往祖墳刨,看下這個源碼再解釋。
Backbone.View不用說。上面就幾個屬性和方法。能夠看到爲何類定義了initialize後自動調用的緣由了吧。
還有你也知道爲何view中events定義後就能夠處理事件了吧(由於delegateEvents初始化了)。
這是部分代碼,若是有js高級教程經驗的能夠看下backbone.js關於view類的源碼。
Backbone.View.prototype是經過underscore的extend繼承Events和opt拓展屬性組合而成的(若是不懂underscore.js的extend請看這裏:http://underscorejs.org/#extend)。View.prototype==Backbone.View由於function是引用調用,公用一片內存,
因此View.prototype的變化會影響到Backbone.View的prototype.
再看e.__super == Backbone.View.prototype以後Backbone.View.prototype.constructor就是由Backbone.View的構造的,因此e.__super__.constructor則就是Backbone.View.apply(this,arguments);因此執行Backbone.View就有了一些關於事件,initialize函數的一些初始化。在類中若是super了。就會執行parent的constructor。直到執行繼承Backbone.View的constructor便可。
不知道你們明白了與否。
也就是super執行的流程以下:
child(constructor)->parent(constructor).......//若是constructor中有super.就是這個執行順序。只要繼承類中某個類沒有super。擇constructor就中止了構造。
ok,到了這裏,我想大概都應該明白了。因此若是之後涉及到繼承。請謹慎定義constructor。若是你須要在子類中定義事件,而有繼承了父類。那你必定要檢查一下父類的constructor和子類的constructor是否super了(coffee中的super就是調用父類的構造函數,然-child.__super__.constructor.apply(this,arguments)).不然你子類的events對象就不會初始化,從而致使點擊無效果。