CoffeeScript系列教程(七)—循环和推导式

循环

这点主要讲的是对数组和对象的遍历。

数组的遍历

数组的遍历我们只需要拿到每个元素和当前元素的下标就可以了。数组的遍历也可以采用操作前置写法:

#编译前
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;

其实就是把两个下标之间的元素替换成新的数据。同样的, ...  不包括结束位置的元素, ..  包括结束位置的元素

你可能感兴趣的:(CoffeeScript)