没有合适的资源?快使用搜索试试~ 我知道了~
自从3年前Backbone.js发布第一版以来,Backbone.js就成为一个流行的开源JavaScript “MV*”框架,并获得人们的青睐。尽管Backbone.js给JavaScript应用提供了框架,但是它仍然给开发者留有很多设计模式供选择,不管怎样,当开发者第一次使用Backbone.js时还会产生很多普遍的问题的。 因此,在这篇文章中,我们将介绍很多不同的设计模式供你在Backbone.js应用中使用,而且我们也会一同来看看对于开发者来说会产生很多普遍的有关性能伸缩的问题。 对象深度拷贝 JavaScript对待所有原生类型变量是传值。所以,当变量被引用时就传递了变量的值。
资源详情
资源评论
资源推荐
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.),与此同时这上面所有的事例工厂当你要深度复制对象里面包含的对象时你都必须小心的使用。你必须也要知道一个小小
的性能影响都来自于执行一个深度的克隆,但是我从来没有看到过很明显的问题。然而,如果你要深度的克隆一个大对象或者
成千上万的对象所有的立即复制,你将有可能做大量的性能分析。这将领导我们直接到下一个模式。
为对象创建外观为对象创建外观
在现实世界中,需求经常变化,JavaScript对象符号(或者说JSON)也是一样,这些对象是由模型和集合所在的端点返回
的。这或许会成为你的基础代码中的一个真正的大麻烦,如果你的视图与底层的数据模型是紧耦合的话。因此,我为所有对象
创建了getters和setters。
支持这个模式的人非常多。如果任何底层的数据结构改变了,那么视图层并不需要更新许多;你将有一个数据的访问点,所以
你不太可能忘记做一个深度拷贝,你的代码将会更易于维护更易于调试。负面因素在于这个模式可能导致模型或集合的一点点
膨胀。
我们看一个例子来阐明这个模式。想像我们有一个Hotel模型,包含有rooms和目前可获得的rooms,而且我们希望可以通过床
位大小来获得rooms。
var Hotel = Backbone.Model.extend({
defaults: {
"availableRooms": ["a"],
"rooms": {
"a": {
"size": 1200,
"bed": "queen"
},
"b": {
"size": 900,
"bed": "twin"
},
"c": {
"size": 1100,
"bed": "twin"
}
},
getRooms: function() {
$.extend(true, {}, this.get("rooms"));
},
getRoomsByBed: function(bed) {
return _.where(this.getRooms(), { "bed": bed });
}
}
});
现在我们假设明天你就要发布你的代码,而你又发现端点开发者忘记告诉你rooms的数据结构改变了,由一个对象变为一个数
组。你的代码现在看起来会像下面这样。
var Hotel = Backbone.Model.extend({
defaults: {
"availableRooms": ["a"],
"rooms": [
{
"name": "a",
"size": 1200,
"bed": "queen"
},
{
"name": "b",
"size": 900,
"bed": "twin"
},
{
"name": "c",
"size": 1100,
"bed": "twin"
}
],
getRooms: function() {
var rooms = $.extend(true, {}, this.get("rooms")),
newRooms = {};
// transform rooms from an array back into an object
_.each(rooms, function(room) {
newRooms[room.name] = {
"size": room.size,
"bed": room.bed
}
});
},
getRoomsByBed: function(bed) {
return _.where(this.getRooms(), { "bed": bed });
}
}
});
我们仅仅更新了一个函数,以便将Hotel的结构转变为这个应用的其余部分所期望的结构,同时整个应用仍然像我们所期待的
一样运作。如果这里没有一个getter,我们很可能不得不为rooms更新每个访问点。理想情况下,你会希望更新所有的函数,
以适应新的数据结构,但如果你在时间方面有压力急于发布的话,这个模式将可以拯救你。
离题说一句,这个模式既可以被认为是装饰模式,因为它隐藏了创建对象拷贝的复杂性,也可以认为是桥接模式,因为它可以
用来将数据转换为所期望的形式。一个好的经验是对任何对象元素使用getters 和setters 。
存储数据不是通过服务器保存存储数据不是通过服务器保存
尽管Backbone.js有模型和集合映射的规定去具象状态的传输(or REST-ful)的端点,你将花大量的时间去找你想要的存储数据
在你的模型或者不是在服务器上的连接。另外一些关于Backbone.js的文章,例如“Backbone.js Tips: Lessons From the
Trenches” 是通过SupportBee的Prateek Dayal ,这个模式还有其他的描述。让我们一起来快速的看一个小例子来帮助我们说
明它可能会派上用场。假设你有一个集合。
剩余10页未读,继续阅读
weixin_38746166
- 粉丝: 8
- 资源: 960
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0