BackboneJS架構的技巧及模式(1)

來源:互聯網
上載者:User

原文見:http://coding.smashingmagazine.com/2013/08/09/backbone-js-tips-patterns/

譯者註:本文採用意譯,省略所有口水話,內容直指要義。

http://blog.csdn.net/chszs

BackboneJS是一個流行的JavaScript MVC/MVVM架構,第一版發佈於三年多前,到現在已經是一個頗有影響力的架構。儘管BackboneJS提供了JavaScript項目的基本結構,但它還留下了很多設計模式和決策供開發人員使用。

因此,本文會介紹很多不同的設計模式供BackboneJS開發過程中使用,還會介紹一些開發中可能遇到的陷阱。


應用就和建築一樣,都是遵循已知的模式進行構建。


一、實現對象的深度複製

JavaScript把所有的原生類型變數都以值傳遞的方式對待。因此,當原生類型的變數被引用時,變數的值會被傳遞。

比如,上面代碼中,設定helloWorldCopy變數的值等同於helloworld變數。因此,任何修改變數helloWorldCopy值的行為並不會影響到helloWorld變數,因為這是一份拷貝。

JavaScript把所有的非原生類型的變數都以參數傳遞的方式對待。這意味著當非原生類型的變數被引用時,JavaScript會傳遞變數的記憶體位址。

var helloWorld = {    ‘hello’: ‘world’}var helloWorldCopy = helloWorld;

比如,上面的代碼設定helloWorldCopy變數的值等同於helloworld變數的引用。當修改helloWorldCopy變數時,會直接操縱helloWorld變數。而如果你想擁有一份helloWorld的拷貝,那麼你必須建立對象的拷貝。

你或許會想到這樣的問題,“為什麼BackboneJS中到處都是引用傳遞?”

BackboneJS並不會複製對象,這意味著如果你從模型調用.get()方法獲得一個對象,任何對此對象的修改都會直接修改原對象。

下面我們一起看一個例子來說明此問題。如果你有如下的Person模型:

var Person = Backbone.Model.extend({   defaults: {        'name': 'John Doe',        'address': {            'street': '1st Street',            'city': 'Austin',            'state': 'TX',            'zipCode': 78701        }   }});

接著我們建立了一個新person對象:

var person = new Person({    'name': 'Phillip W'});

接下來我們操縱新person對象的一些屬性:

person.set('name', 'Phillip W.', { validate: true });

上面的代碼成功地修改了person對象的name屬性。接著,我們試著修改person對象的address屬性。但是,在做之前,我們先驗證一下地址屬性:

var Person = Backbone.Model.extend({    validate: function(attributes) {        if(isNaN(attributes.address.zipCode)) return "Address ZIP code must be a number!";    },    defaults: {        'name': 'John Doe',        'address': {            'street': '1st Street',            'city': 'Austin',            'state': 'TX',            'zipCode': 78701        }    } });

接著,我們嘗試用錯誤的ZIP代碼設定地址:

var address = person.get('address');address.zipCode = 'Hello World';// Raises an error since the ZIP code is invalidperson.set('address', address, { validate: true });console.log(person.get('address'));/* Prints an object with these properties.{    'street': '1st Street'    'city': 'Austin',    'state': 'TX'    'zipCode': 'Hello World'}*/

這會怎麼樣呢?我們的驗證出現了錯誤!為什麼屬性依舊被修改了?正如前面提過的,BackboneJS不會複製模型的屬性,它只會簡單地返回你所請求的一切。因此,如你所料,如果你請求一個對象,你會得到此對象的引用。對此對象的任何操作都會直接改變模型中的實際對象。

如果你要debug,這可能將把你帶入到無底的兔子黑洞。


實現一個深度模型對象的複製可能會讓你在調試中避免掉入兔子洞。


此問題對於BackboneJS新手要引起注意,甚至一些JavaScript老手也該提防。

在這裡:https://github.com/documentcloud/backbone/issues/2315有深度的討論。

正如Jeremy Ashkenas所說,實現深度複製是用於解決不同的問題,尤其是在很大、有深度的對象來說,此操作的記憶體開銷很大。

幸運的是,jQuery庫提過了一個深度複製的實現,即$.extend操作。順便說一句,UnderscoreJS架構(它依賴於BackboneJS),也提供了_.extend這樣的函數,但是我們應該盡量避免使用它,因為它沒有實現深度複製。

Lo-Dash (http://lodash.com/)是UnderscoreJS的分支和最佳化版本,提供了_.clone函數,實現了深度複製。但是,我使用$.extend來實現任意對象的深度複製,對象是通過.get()從模型中擷取的。記住要傳遞true,它指示執行對象的深度複製。

var address = $.extend(true, {}, person.address);

我們現在有address對象的準確複製了,我們可以隨心修改內容而無需擔心修改了實際的模型。要注意一點,此模式工作的前提是由於address對象的所有成員變數都是不可變 的(數字或字串等)。還要注意,深度複製對效能是有一點兒影響的,尤其是對於大對象來說。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.