CoffeeScript的循環(huán)和推導(dǎo)式

2018-08-25 14:47 更新
for ... in推導(dǎo)適用于數(shù)組、對(duì)象和范圍
推導(dǎo)使用可選的控制子句和當(dāng)前數(shù)組索引的值代替循環(huán):for value, index in array
數(shù)組推導(dǎo)是表達(dá)式,可以返回和賦值
推導(dǎo)可以代替each/forEach、map或select/filter
在知道循環(huán)的起點(diǎn)和終點(diǎn)的情況下使用范圍(整數(shù)步長(zhǎng))
使用by指定固定大小的步長(zhǎng)
在把推導(dǎo)的結(jié)果賦值給變量時(shí),CoffeeScript會(huì)把每次迭代的結(jié)果收集到一個(gè)數(shù)組中
如果循環(huán)的結(jié)果只產(chǎn)生副作用,那么要返回null、undefined或true
要迭代對(duì)象的鍵和值,使用of
使用for own key, value of object迭代直接在對(duì)象中定義的鍵
while是CoffeeScript提供的唯一的低級(jí)循環(huán);while循環(huán)可以用作表達(dá)式,返回一個(gè)數(shù)組,包含每次循環(huán)的結(jié)果
until等價(jià)于while not

loop等價(jià)于whilt true _ do關(guān)鍵字用于插入閉包,轉(zhuǎn)發(fā)所有參數(shù)并調(diào)用傳入的函數(shù)


循環(huán)
這點(diǎn)主要講的是對(duì)數(shù)組和對(duì)象的遍歷。


數(shù)組的遍歷
數(shù)組的遍歷我們只需要拿到每個(gè)元素和當(dāng)前元素的下標(biāo)就可以了。數(shù)組的遍歷也可以采用操作前置寫(xiě)法:


#編譯前
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);
}


獲取下標(biāo):

#編譯前
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);
}


多操作的時(shí)候就不能采用操作前置的寫(xiě)法了,要采用下面的寫(xiě)法,要注意縮進(jìn)。

#編譯前
array = ['xxx', 'yyy', 'zzz']

for item,i in array
  console.log i + ':' + item
  alert i + ':' + item
對(duì)象的遍歷

對(duì)象的遍歷只要拿到key和value就可以做愛(ài)做的事了。嘿嘿先看操作前置寫(xiě)法:

#編譯前
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);
}


多操作還是得這樣寫(xiě),注意縮進(jìn)

#編譯前
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);
}


如果你希望僅迭代在當(dāng)前對(duì)象中定義的屬性,通過(guò)hasOwnProperty檢查并避免屬性是繼承來(lái)的,可以這樣來(lái)寫(xiě):

#編譯前
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);
}


注意:別搞錯(cuò)關(guān)鍵字了

for item in array
for key of obj
推導(dǎo)式

所謂的推導(dǎo)式其實(shí)就是在遍歷數(shù)組進(jìn)行操作的同時(shí),將操作后的結(jié)果生成一個(gè)新的數(shù)組。注意啊,這里僅僅是操作數(shù)組,對(duì)象可不行。看例子:將每個(gè)數(shù)組的每個(gè)元素進(jìn)行+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;
})();


推導(dǎo)式的代碼就一行,但是編譯到JavaScript,大家可以看到節(jié)省了大量的代碼,而且從CoffeeScript代碼上,我們一眼就看出了代碼功能。當(dāng)然了,實(shí)際上推導(dǎo)式不可能就這樣簡(jiǎn)單:遍歷所有元素進(jìn)行操作。有時(shí)候得進(jìn)行一些過(guò)濾。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) #過(guò)濾掉第一個(gè)元素newArray2 = (addOne item for item,i in array when item > 3) #過(guò)濾掉小于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;
})();


相信大家也發(fā)現(xiàn)了,推導(dǎo)式都是寫(xiě)在一行的,如果要使用推導(dǎo)式,得將你的操作封裝成一個(gè)函數(shù)供調(diào)用。


切片
CoffeeScript構(gòu)建的思想,借鑒了很多Python和Ruby的。比如現(xiàn)在所說(shuō)的切片功能。切片其實(shí)就是對(duì)數(shù)組的截?cái)?,插入和刪除操作。說(shuō)白了就是用JavaScript的數(shù)組slice和splice函數(shù)操作數(shù)組。還是先簡(jiǎn)單說(shuō)明一下這兩函數(shù)吧。注意啊,這里講的JavaScript

slice(start,end)

功能:數(shù)組截取
**參數(shù): 
start:開(kāi)始位置
end:結(jié)束位置**
返回值:新的數(shù)組
注意:數(shù)組本身不發(fā)生變化

第一個(gè)參數(shù)是截取開(kāi)始位置(數(shù)組下標(biāo)是從0開(kāi)始),第二個(gè)參數(shù)是結(jié)束位置,但是不包括結(jié)束位置。

如果只有一個(gè)參數(shù),從開(kāi)始位置截取到剩下所有數(shù)據(jù)
開(kāi)始位置和結(jié)束位置也可以傳遞負(fù)數(shù),負(fù)數(shù)表示倒著數(shù)。例如-3是指倒數(shù)第三個(gè)元素

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...)

功能:數(shù)組插入數(shù)據(jù)、刪除數(shù)據(jù)
**參數(shù): 
start:開(kāi)始位置
len:截?cái)嗟膫€(gè)數(shù)
data:插入的數(shù)據(jù)**
返回值:截?cái)嗟臄?shù)據(jù),是數(shù)組
注意:操作的是數(shù)組本身
如果只有一個(gè)參數(shù),從開(kāi)始位置截取剩下所有數(shù)據(jù)

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);
注意: ... 不包括結(jié)束位置的元素, .. 包括結(jié)束位置的元素

CoffeeScript里面是這樣操作數(shù)組的。

#編譯前
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;


其實(shí)就是把兩個(gè)下標(biāo)之間的元素替換成新的數(shù)據(jù)。同樣的, ... 不包括結(jié)束位置的元素, .. 包括結(jié)束位置的元素



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)