Backbone.js的一些使用技巧

自从3年前Backbone.js发布第一版以来,Backbone.js就成为一个流行的开源JavaScript “MV*”框架,并获得人们的青睐。尽管Backbone.js给JavaScript应用提供了框架,但是它仍然给开发者留有很多设计模式供选择,不管怎样,当开发者第一次使用Backbone.js时还会产生很多普遍的问题的。

因此,在这篇文章中,我们将介绍很多不同的设计模式供你在Backbone.js应用中使用,而且我们也会一同来看看对于开发者来说会产生很多普遍的有关性能伸缩的问题。 
 对象深度拷贝

JavaScript对待所有原生类型变量是传值。所以,当变量被引用时就传递了变量的值。
 

var helloWorld = “Hello World”; var helloWorldCopy = helloWorld;

举个例子,上面的代码将变量helloWorldCopy的值设置为变量helloWorld的值。这样, 自从它的值被复制之后,所有修改helloWorldCopy的值不会修改helloWorld的值。JavaScript对待所有非原始类型的变量时传引用,这就意味着当变量传递的时候将会传递内存地址引用。
 

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


举个例子,上面的代码将设置helloWorldCopy为helloWorld的引用,而且,也许你会猜到任何修改helooWorldCopy的值都会直接导致helloWorld值的变化。如果你想要helloWorld的拷贝,你可以创建一个拷贝对象即可。

也许你会想到“为什么Backbone.js可以解释为所有的工作都是通过传递引用?”事实上,Backbone.js不会拷贝对象,这将意味着如果你从模型里调用.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.set('name', 'Phillip W.', { validate: true });
上面的代码成功的给person对象的name属性赋了值。现在我们在来操作person对象的地址属性。当然,在我们这样做之前先验证一下地址属性。
 

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 invalid person.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' } */


这将会怎样呢?我们的验证出现了错误!为什么属性依旧被改变了?前边我们说过,Backbone.js不会拷贝模型属性;它会返回你所请求的一切。这样,你也许会猜到,如果你需要一个对象,你将得到这个对象的引用,对这个对象的任何操作都会直接改变模型里的对象。如果你要debug,这可能将把你带入到无底的兔子黑洞。
 这个问题对于新的Backbone.js使用要引起注意,甚至对于老练的JavaScript程序员有时也会没有提防。这个问题在GitHub的Backbone.js讨论组中有很激烈的讨论。正如Jeremy Ashkenas指出,执行一个深的对象引用是个很难解决的难题,一个很深的对象引用是要花费很大代价的。


幸运的,jQuery 提供了一个深度拷贝功能来实现,$.extend. 如同, Underscore.js ,一个Backbone.js的依靠,提供_.extend 方法,但是我必须避免使用它,因为它没有执行一份是个深度的复制,Lo-Dash, Underscore.js的一个分叉版本,提供了对象一个深度克隆的_.clone 方法的选项。然而,我使用 $.extend 方法的模型使用的语法规则去执行一个任意对象的深度克隆。记得通过后,结果它执行的是一个深度的克隆方法
 

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

我们现在快速准确的复制一个theaddressobject?,并且我们能够更改它对于我们要点没有包括在内的我们不用担心会更改它原有的模型。你必须要意思到这个父工厂对于上面所有的事例因为它所有的地址对象成员都是不可变的(numbers, strings, etc.),与此同时这上面所有的事例工厂当你要深度复制对象里面包含的对象时你都必须小心的使用。你必须也要知道一个小小的性能影响都来自于执行一个深度的克隆,但是我从来没有看到过很明显的问题。然而,如果你要深度的克隆一个大对象或者成千上万的对象所有的立即复制,你将有可能做大量的性能分析。这将领导我们直接到下一个模式。

为对象创建外观

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgdjyj.html