2.8 The Object Model -- Enumerables
在Ember.js中,枚举是包含许多子对象的任何对象,并允许你使用Ember.Enumerable API和那些子对象一起工作。在大部分应用程序中最常见的可枚举是本地JS数组,Ember.js扩展到符合可枚举接口。
通过提供一个标准化的接口处理来可枚举,ember.js让你彻底改变存储的底层数据的方式而无需修改应用程序的其他部分获取它。
可枚举的API尽可能遵循ECMAScript标准。这样最大限度的减少与其他库的不兼容,并允许Ember.js在数组中使用原生的浏览器实现。
例如,所有的可枚举支持标准的forEach方法:
[1,2,3].forEach(function(item) { console.log(item); }); //=> 1 //=> 2 //=> 3
通常,可枚举的方法,例如forEach,第二个参数是可选的,这个回调函数中将变成this的值在。
var array = [1,2,3]; array.forEach(function(item) { console.log(item, this.indexOf(item)); }, array) //=> 1 0 //=> 2 1 //=> 3 2
一、Enumberables in Ember.js
通常,对象表示列表实现枚举器接口。
examples:
- Array -- Ember使用可枚举的接口扩展JS原生的Array(除非你禁用属性扩展)
- Ember.Set -- 一个数据结构,它可以有效回答是否它包含一个对象。
二、API概览
下面我们会探讨一些最常见的可枚举的便利。
1. Iterating Over An Enumerable(迭代)
使用forEach方法枚举所有可枚举对象的值:
var food = ["Poi", "Ono", "Adobo Chicken"]; food.forEach(function(item, index) { console.log('Menu Item %@: %@'.fmt(index+1, item)); }); // Menu Item 1: Poi // Menu Item 2: Ono // Menu Item 3: Adobo Chicken
2. Making An Array Copy
通过调用toArray()方法你可以制作一个任何实现了Ember.Enumerable的对象的原生数组的拷贝。
var states = Ember.Set.create(); states.add("Hawaii"); states.add("California") states.toArray() //=> ["Hawaii", "California"]
注意在许多的可枚举中,例如例子中使用的Ember.Set,所得到的数组的顺序是没有保证的。
3. First and Last Objects
所有的枚举接口暴露firstobject和lastobject属性可以绑定。
var animals = ["rooster", "pig"]; animals.get('lastObject'); //=> "pig" animals.pushObject("peacock"); animals.get('lastObject'); //=> "peacock"
4. Map
使用Map()方法你可以很容易地变化可枚举中的每一项,它可以调用每一项上回调函数的结果来创建一个新数组。
var words = ["goodbye", "cruel", "world"]; var emphaticWords = words.map(function(item) { return item + "!"; }); // ["goodbye!", "cruel!", "world!"]
如果可枚举的是合成的,会有一个mayBy()方法,它将反过来从这些对象中的每一项中提取指定的属性并返回一个新数组。
var hawaii = Ember.Object.create({ capital: "Honolulu" }); var california = Ember.Object.create({ capital: "Sacramento" }); var states = [hawaii, california]; states.mapBy('capital'); //=> ["Honolulu", "Sacramento"]
5. Filtering
另一个常见的任务是以枚举作为输入执行一个枚举,和基于一些条件过滤后返回一个数组。
对于任意的过滤,用过滤器方法。如果包含在最后的数组中,该过滤器的方法期望回调函数返回true,否则返回false或者undefined。
var arr = [1,2,3,4,5]; arr.filter(function(item, index, self) { if (item < 4) { return true; } }) // returns [1,2,3]
当使用一个集合对象时,通常需要根据某些属性的值来筛选一组对象。filterBy方法提供了一个快捷方式。
Todo = Ember.Object.extend({ title: null, isDone: false }); todos = [ Todo.create({ title: 'Write code', isDone: true }), Todo.create({ title: 'Go to sleep' }) ]; todos.filterBy('isDone', true); // returns an Array containing only items with `isDone == true`
如果你只需要返回第一个匹配的值,而不是包含所有匹配的值的数组,你可以使用find和findBy,它们只返回一条数据。
6. Aggregate Information(All or Any)汇总信息
如果你想找到可枚举中的每一条数据都满足一些条件,你可以使用every方法。
Person = Ember.Object.extend({ name: null, isHappy: false }); var people = [ Person.create({ name: 'Yehuda', isHappy: true }), Person.create({ name: 'Majd', isHappy: false }) ]; people.every(function(person, index, self) { if(person.get('isHappy')) { return true; } }); // returns false
如果你想找到可枚举中的至少一条数据都满足一些条件,你可以使用some方法。
people.some(function(person, index, self) { if(person.get('isHappy')) { return true; } }); // returns true
就像过滤方法一样,every和some有类似的方法isEvery和isAny方法。
people.isEvery('isHappy', true) // false people.isAny('isHappy', true) // true