Backbone的寫類方式


從兩個角度去討論Backbone的寫類方式

  1. Backbone內部的寫類方式,Backbone自身的類如Model、Collection、View等是如何定義的
  2. Backbone外部的寫類方式,如何使用Backbone提供的類來定義自己的類

 

一、Backbone內部的寫類方式

Backbone提供給客戶端程序員的類都是通過 構造函數+原型 的方式寫的,Backbone.Model的代碼大致如下

// 定義構造器
var Model = Backbone.Model = function(attributes, options) {
    // ...
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
};

// 擴展原型,往原型上添加了很多方法,如Events
_.extend(Model.prototype, Events, {
    // ...
});

這種寫法很傳統,Backbone.Collection / Backbone.View / Backbone.Router / Backbone.History 都是通過這種方式定義的。

 

二、Backbone的外部寫類方式

說外部的寫類方式,不得不提 extend 方法,該方法定義在Backbone.js的底部。不到30行代碼,它是私有的,外部並不能訪問。
也就是說,這個方法只在Backbone內部使用,為其它模塊服務。

 

其實這個說法不嚴謹,雖然extend不能直接訪問,但它通過僅一行代碼

Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;


轉身變為以下方法

  • Backbone.Model.extend
  • Backbone.Collection.extend
  • Backbone.View.extend
  • Backbone.Router.extend
  • Backbone.History.extend

這時,外部還是可以訪問得到。

 

在一個閉包內,寫一個私有的函數,然后把該函數賦值給多個類或類原型。這些寫法並不少見,這樣寫節省了內存,函數實例其實只有一份。

此外,不要把這里的extend 和 _.extend 搞混了。_.extend是underscore提供的較底層的方法,用來Mixin對象。這里的extend則是用來寫類。

 

介紹下extend

  1. 它接受兩個參數,都是對象類型
  2. 它返回一個類(構造器,函數),怎么叫都行
  3. 第一個參數的所有屬性、方法都會拷貝到類的原型上(實例對象上)
  4. 第二個參數的所有屬性、方法都會拷貝的類上(類靜態屬性、方法)
  5. 第一個參數中如果有constructor屬性,那么最后就返回它,否則返回內部提供的child
  6. 返回的類有個特殊屬性 __super__。

上面的第六點,使用它很方便的取得父類原型,進而取到父類構造器,進而在子類中去調用父類,這類似於Java里的super關鍵字。

 

拿示例詳細說說

1. 兩個參數,都是對象類型,第一個擴展為原型方法,第二個擴展為類方法

var instanceObj = {
	name: '',
	getName: function() {},
	setName: function(name) {}
}
var classObj = {
	trim: function(str) {},
	mix: function() {}
}

// 生成一個新類CustomModel,它具有Backbone.Model的所有方法
var CustomModel = Backbone.Model.extend(instanceObj, classObj)

// instanceObj屬性都拷貝到了CustomModel.prototype 上
_.each(['name','getName', 'setName'], function(attr) {
	console.log(attr in CustomModel.prototype)
})

// classObj屬性都拷貝到了 CustomModel 上
_.each(['trim','mix'], function(attr) {
	console.log(attr in CustomModel)
})

 

2. 參數中如果有constructor屬性,那么最后就返回它,否則返回內部提供的child

這實際上告訴使用者可以自定義構造器,而不使用內部的child。

function MyConstructor(name, age) {
	this.name = name;
	this.age  = age;
}
var CustomModel = Backbone.Model.extend({
	constructor: MyConstructor,
	getName: function(){},
	setName: function(){}
})

var m1 = new CustomModel('John', 30)
console.log(m1.constructor === MyConstructor) // true

 

3. 返回的類有個特殊屬性 __super__,用它很方便的取得父類原型,進而取到父類構造器,最后在子類中去調用父類

function Person(name, age) {
	this.name = name
	this.age = age
}
Person.extend = Backbone.Model.extend // 把Backbone的extend拿出來用,O(∩_∩)O~

function ManConstructor(name, age) {
	ManConstructor.__super__.constructor.call(this, name, age) // 調用父類構造器
	this.gender = 'male'
}
var Man = Person.extend({
	constructor: ManConstructor
})
var man = new Man('John', 30)
console.log(man) // ManConstructor { name="John", age=30, gender="male"}

 

總結下Backbone的寫類方式

Backbone內部的寫類方式是 構造函數+原型。外部寫類則是通過extend,寫類和繼承同時存在。

1. 通過Model(View/Router等)的extend方法寫類,產生的類直接繼承了Model(View/Router等)
2. 如果寫的類不是Backbone提供的類,那么可以象3那樣,把extend方法拿出來

 

使用Backbone開發,多數時候都采用方式1,它強制要求把代碼分為了幾層,一些實用工具函數由underscore提供。

如果是瀏覽器端開發,DOM及HTTP通訊操作一般由jQuery或zepto等提供。你寫的代碼幾乎都集中在業務處理,無非就是模型(Model)、集合(Collection)、視圖(View)、路由(Router)、歷史管理(History)。

 

 

相關:

JavaScript的寫類方式

JavaScript的繼承方式

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM