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

简介: 原文见:http://coding.smashingmagazine.com/2013/08/09/backbone-js-tips-patterns/ 译者注:本文采用意译,省略所有口水话,内容直指要义。

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

译者注:本文采用意译,省略所有口水话,内容直指要义。

BackboneJS是一个流行的JavaScript MVC/MVVM框架,第一版发布于三年多前,到现在已经是一个颇有影响力的框架。尽管BackboneJS提供了JavaScript项目的基本结构,但它还留下了很多设计模式和决策供开发者使用。

因此,本文会介绍很多不同的设计模式供BackboneJS开发过程中使用,还会介绍一些开发中可能遇到的陷阱。


应用就和建筑一样,都是遵循已知的模式进行构建。


一、实现对象的深度复制

JavaScript把所有的原生类型变量都以值传递的方式对待。因此,当原生类型的变量被引用时,变量的值会被传递。

比如,上面代码中,设置helloWorldCopy变量的值等同于helloworld变量。因此,任何修改变量helloWorldCopy值的行为并不会影响到helloWorld变量,因为这是一份拷贝。

JavaScript把所有的非原生类型的变量都以参数传递的方式对待。这意味着当非原生类型的变量被引用时,JavaScript会传递变量的内存地址。


[javascript]   view plain copy print ?
  1. var helloWorld = {  
  2.     ‘hello’: ‘world’  
  3. }  
  4. var helloWorldCopy = helloWorld;  

比如,上面的代码设置helloWorldCopy变量的值等同于helloworld变量的引用。当修改helloWorldCopy变量时,会直接操纵helloWorld变量。而如果你想拥有一份helloWorld的拷贝,那么你必须创建对象的拷贝。


你或许会想到这样的问题,“为什么BackboneJS中到处都是引用传递?”

BackboneJS并不会复制对象,这意味着如果你从模型调用.get()方法获得一个对象,任何对此对象的修改都会直接修改原对象。

下面我们一起看一个例子来说明此问题。如果你有如下的Person模型:


[javascript]   view plain copy print ?
  1. var Person = Backbone.Model.extend({  
  2.    defaults: {  
  3.         'name''John Doe',  
  4.         'address': {  
  5.             'street''1st Street',  
  6.             'city''Austin',  
  7.             'state''TX',  
  8.             'zipCode': 78701  
  9.         }  
  10.    }  
  11. });  

接着我们创建了一个新person对象:



[javascript]   view plain copy print ?
  1. var person = new Person({  
  2.     'name''Phillip W'  
  3. });  

接下来我们操纵新person对象的一些属性:



[javascript]   view plain copy print ?
  1. person.set('name''Phillip W.', { validate: true });  

上面的代码成功地修改了person对象的name属性。接着,我们试着修改person对象的address属性。但是,在做之前,我们先验证一下地址属性:



[javascript]   view plain copy print ?
  1. var Person = Backbone.Model.extend({  
  2.     validate: function(attributes) {  
  3.   
  4.         if(isNaN(attributes.address.zipCode)) return "Address ZIP code must be a number!";  
  5.     },  
  6.   
  7.     defaults: {  
  8.         'name''John Doe',  
  9.         'address': {  
  10.             'street''1st Street',  
  11.             'city''Austin',  
  12.             'state''TX',  
  13.             'zipCode': 78701  
  14.         }  
  15.     }   
  16. });  

接着,我们尝试用错误的ZIP代码设置地址:



[javascript]   view plain copy print ?
  1. var address = person.get('address');  
  2. address.zipCode = 'Hello World';  
  3. // Raises an error since the ZIP code is invalid  
  4. person.set('address', address, { validate: true });  
  5. console.log(person.get('address'));  
  6. /* Prints an object with these properties. 
  7. { 
  8.     'street': '1st Street' 
  9.     'city': 'Austin', 
  10.     'state': 'TX' 
  11.     'zipCode': 'Hello World' 
  12. } 
  13. */  

这会怎么样呢?我们的验证出现了错误!为什么属性依旧被修改了?正如前面提过的,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,它指示执行对象的深度复制。

[javascript]   view plain copy print ?
  1. var address = $.extend(true, {}, person.address);  

我们现在有address对象的准确复制了,我们可以随心修改内容而无需担心修改了实际的模型。要注意一点,此模式工作的前提是由于address对象的所有成员变量都是不可变 的(数字或字符串等)。还要注意,深度复制对性能是有一点儿影响的,尤其是对于大对象来说。

目录
相关文章
|
人工智能 监控 安全
政府行业应用解决方案 | 应急行业
本文介绍了政府行业应用解决方案 | 应急行业的方案概述,方案价值及优势以及最佳实践。
政府行业应用解决方案 | 应急行业
【面试题精讲】JVM中哪些对象可以被称为GC ROOT对象
【面试题精讲】JVM中哪些对象可以被称为GC ROOT对象
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
321 3
|
人工智能 文件存储 对象存储
Stable Diffusion 模型库,AIGC 画风任你选
Stable Diffusion(简称 SD)模型库包含写实、国漫、科技等几十种风格。可以让用户一键转存到自己的存储空间,而后直接挂载到 PAl 或 FC 下进行推理和训练。无需复杂漫长的下载和上传步骤,即可获得多种模型的使用体验,实现云上 AIGC 的快速搭建。
52621 22
Stable Diffusion 模型库,AIGC 画风任你选
|
对象存储 Python
Ceph Reef(18.2.X)之python操作对象存储网关
这篇文章介绍了如何在Ceph Reef(18.2.X)环境中使用Python操作对象存储网关(rgw),包括环境搭建、账号创建、使用s3cmd工具以及编写和测试Python代码。
194 3
|
安全 Java 编译器
深入理解 Java 枚举 Enum 类型用法
深入理解 Java 枚举 Enum 类型用法
1799 0
|
Java Maven
IntelliJ IDEA - 普通文件夹转 Module 模块
IntelliJ IDEA - 普通文件夹转 Module 模块
2926 0
IntelliJ IDEA - 普通文件夹转 Module 模块
|
JavaScript 安全 前端开发
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(下)
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞
337 0
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(下)
|
Java 程序员 Scala
Scala基础教程 - 单例对象、伴生类是什么?
Scala基础教程 - 单例对象、伴生类是什么?
323 0
|
Windows
WINDOWS下,找包含特殊字串的文件的解决办法
WINDOWS下,找包含特殊字串的文件的解决办法
157 0