CoffeeScript的循环和推导式
推导使用可选的控制子句和当前数组索引的值代替循环:for value, index in array
数组推导是表达式,可以返回和赋值
推导可以代替each/forEach、map或select/filter
在知道循环的起点和终点的情况下使用范围(整数步长)
使用by指定固定大小的步长
在把推导的结果赋值给变量时,CoffeeScript会把每次迭代的结果收集到一个数组中
如果循环的结果只产生副作用,那么要返回null、undefined或true
要迭代对象的键和值,使用of
使用for own key, value of object迭代直接在对象中定义的键
while是CoffeeScript提供的唯一的低级循环;while循环可以用作表达式,返回一个数组,包含每次循环的结果
until等价于while not
loop等价于whilt true _ do关键字用于插入闭包,转发所有参数并调用传入的函数
循环
这点主要讲的是对数组和对象的遍历。
数组的遍历
数组的遍历我们只需要拿到每个元素和当前元素的下标就可以了。数组的遍历也可以采用操作前置写法:
#编译前
array = ['xxx', 'yyy', 'zzz']
console.log item for item in array
#编译后
var array, item, _i, _len;
array = ['xxx', 'yyy', 'zzz'];
for (_i = 0, _len = array.length; _i < _len; _i++) {
item = array[_i];
console.log(item);
}
获取下标:
#编译前
array = ['xxx', 'yyy', 'zzz']
console.log i + ':' + item for item,i in array
#编译后
var array, i, item, _i, _len;
array = ['xxx', 'yyy', 'zzz'];
for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
item = array[i];
console.log(i + ':' + item);
}
多操作的时候就不能采用操作前置的写法了,要采用下面的写法,要注意缩进。
#编译前
array = ['xxx', 'yyy', 'zzz']
for item,i in array
console.log i + ':' + item
alert i + ':' + item
对象的遍历
对象的遍历只要拿到key和value就可以做爱做的事了。嘿嘿先看操作前置写法:
#编译前
obj =
name: 'xxx'
age: 10
console.log key + ':' + value for key,value of obj
#编译后
var key, obj, value;
obj = {
name: 'xxx',
age: 10
};
for (key in obj) {
value = obj[key];
console.log(key + ':' + value);
}
多操作还是得这样写,注意缩进
#编译前
obj =
name: 'xxx'
age: 10
for key,value of obj
console.log key + ':' + value
alert key + ':' + value
#编译后
var key, obj, value;
obj = {
name: 'xxx',
age: 10
};
for (key in obj) {
value = obj[key];
console.log(key + ':' + value);
alert(key + ':' + value);
}
如果你希望仅迭代在当前对象中定义的属性,通过hasOwnProperty检查并避免属性是继承来的,可以这样来写:
#编译前
obj =
name: 'xxx'
age: 10
for own key,value of obj
console.log key + ':' + value
#编译后
var key, obj, value,
__hasProp = {}.hasOwnProperty;
obj = {
name: 'xxx',
age: 10
};
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
value = obj[key];
console.log(key + ':' + value);
}
注意:别搞错关键字了
for item in array
for key of obj
推导式
所谓的推导式其实就是在遍历数组进行操作的同时,将操作后的结果生成一个新的数组。注意啊,这里仅仅是操作数组,对象可不行。看例子:将每个数组的每个元素进行+1
#编译前
array = [1, 2, 3, 4]
addOne = (item)->
return item + 1
newArray = (addOne item for item in array)
#编译后
var addOne, array, item, newArray;
array = [1, 2, 3, 4];
addOne = function(item) {
return item + 1;
};
newArray = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = array.length; _i < _len; _i++) {
item = array[_i];
_results.push(addOne(item));
}
return _results;
})();
推导式的代码就一行,但是编译到JavaScript,大家可以看到节省了大量的代码,而且从CoffeeScript代码上,我们一眼就看出了代码功能。当然了,实际上推导式不可能就这样简单:遍历所有元素进行操作。有时候得进行一些过滤。CoffeeScript里面也提供了这些功能,看例子:
#编译前
array = [1, 2, 3, 4]
addOne = (item)->
return item + 1
newArray = (addOne item for item,i in array)newArray1 = (addOne item for item,i in array when i isnt 0) #过滤掉第一个元素newArray2 = (addOne item for item,i in array when item > 3) #过滤掉小于4的元素newArray3 = (addOne item for item,i in array by 2) #迭代的跨度
#编译后
var addOne, array, i, item, newArray, newArray1, newArray2, newArray3;
array = [1, 2, 3, 4];
addOne = function(item) {
return item + 1;
};
newArray = (function() {
var _i, _len, _results;
_results = [];
for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
item = array[i];
_results.push(addOne(item));
}
return _results;
})();
newArray1 = (function() {
var _i, _len, _results;
_results = [];
for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
item = array[i];
if (i !== 0) {
_results.push(addOne(item));
}
}
return _results;
})();
newArray2 = (function() {
var _i, _len, _results;
_results = [];
for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
item = array[i];
if (item > 3) {
_results.push(addOne(item));
}
}
return _results;
})();
newArray3 = (function() {
var _i, _len, _results;
_results = [];
for (i = _i = 0, _len = array.length; _i < _len; i = _i += 2) {
item = array[i];
_results.push(addOne(item));
}
return _results;
})();
相信大家也发现了,推导式都是写在一行的,如果要使用推导式,得将你的操作封装成一个函数供调用。
切片
CoffeeScript构建的思想,借鉴了很多Python和Ruby的。比如现在所说的切片功能。切片其实就是对数组的截断,插入和删除操作。说白了就是用JavaScript的数组slice和splice函数操作数组。还是先简单说明一下这两函数吧。注意啊,这里讲的JavaScript
slice(start,end)
功能:数组截取
**参数:
start:开始位置
end:结束位置**
返回值:新的数组
注意:数组本身不发生变化
第一个参数是截取开始位置(数组下标是从0开始),第二个参数是结束位置,但是不包括结束位置。
如果只有一个参数,从开始位置截取到剩下所有数据
开始位置和结束位置也可以传递负数,负数表示倒着数。例如-3是指倒数第三个元素
var array = [1, 2, 3, 4, 5];
var newArray = array.slice(1); //newArray: [2,3,4,5]
var newArray1 = array.slice(0, 3); //newArray1: [1,2,3]
var newArray2 = array.slice(0, -1); //newArray2: [1,2,3,4]
var newArray3 = array.slice(-3, -2); //newArray3: [3]
splice(start,len,data...)
功能:数组插入数据、删除数据
**参数:
start:开始位置
len:截断的个数
data:插入的数据**
返回值:截断的数据,是数组
注意:操作的是数组本身
如果只有一个参数,从开始位置截取剩下所有数据
var array = [1, 2, 3, 4, 5]
var newArray = array.splice(1);//array=[1] newArray=[2,3,4,5]
var newArray1 = array.splice(0, 2);//array=[3,4,5] newArray1=[1,2]
var newArray2 = array.splice(0, 1, 6, 7);//array=[6,7,2,3,4,5] newArray2=[1]
好了,回到CoffeeScript,看看所谓的切片。
#编译前
array = [1, 2, 3, 4]
newArray = array[0...2] #newArray=[1,2]
newArray1 = array[0..2] #newArray1=[1,2,3]
newArray2 = array[..] #newArray2=[1,2,3,4]
newArray3 = array[-3...-1] #newArray3=[2,3]
#编译后
var array, newArray, newArray1, newArray2, newArray3;
array = [1, 2, 3, 4];
newArray = array.slice(0, 2);
newArray1 = array.slice(0, 3);
newArray2 = array.slice(0);
newArray3 = array.slice(-3, -1);
注意: ... 不包括结束位置的元素, .. 包括结束位置的元素
CoffeeScript里面是这样操作数组的。
#编译前
array = [1, 2, 3, 4]
array[0...1] = [5] #array=[5,2,3,4]
array[0..1] = [5] #array=[5,3,4]
#编译后
var array, _ref, _ref1;
array = [1, 2, 3, 4];
[].splice.apply(array, [0, 1].concat(_ref = [5])), _ref;
[].splice.apply(array, [0, 2].concat(_ref1 = [5])), _ref1;
其实就是把两个下标之间的元素替换成新的数据。同样的, ... 不包括结束位置的元素, .. 包括结束位置的元素
更多建议: