簡說一下coffeescript的constructor是如何致使Backbone.View的事件沒法正常工做的.

 

在繼承方面,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對象就不會初始化,從而致使點擊無效果。

相關文章
相關標籤/搜索