一料饥、字面量增強
如何理解Javascript中的字面量(literal)掸驱?
javascript字面量
- 更安全的二進制字面量(0b1111101)
- 更安全的八進制字面量(0o767)
- 字符串支持 Unicode
二、迭代器(Iterator)
所謂迭代器饭豹,其實就是一個具有next
方法的對象鸵赖,每次調(diào)用next
都會返回一個結(jié)果對象,該結(jié)果對象有兩個屬性拄衰,value
表示當前的值它褪,done
表示遍歷是否結(jié)束。
每一次調(diào)用next
方法肾砂,都會返回數(shù)據(jù)結(jié)構(gòu)的當前成員的信息列赎。具體來說,就是返回一個包含value
和done
兩個屬性的對象镐确。其中包吝,value
屬性是當前成員的值,done
屬性是一個布爾值源葫,表示遍歷是否結(jié)束诗越。
下面是用ES5實現(xiàn)的一個簡單迭代器的例子。
function makeIterator() {
var _value = 0
var max = 5
return {
next: function() {
_value += 1
if (_value > max) { throw new Error('已經(jīng)超過 5 了息堂!') }
if (_value === max) {
return { value: _value, done: true }
} else {
return { value: _value, done: false }
}
}
}
}
var it = makeIterator()
三嚷狞、生成器(Generator)
生成器其實就是生成迭代器的語法糖块促。形式上,Generator 函數(shù)是一個普通函數(shù)床未,但是有兩個特征竭翠。
-
function
關(guān)鍵字與函數(shù)名之間有一個星號; - 函數(shù)體內(nèi)部使用
yield
表達式薇搁,定義不同的內(nèi)部狀態(tài)(yield
在英語里的意思就是“產(chǎn)出”)斋扰。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
上面代碼定義了一個Generator
函數(shù)helloWorldGenerator
,它內(nèi)部有兩個yield
表達式(hello
和world
)啃洋,即該函數(shù)有三個狀態(tài):hello
传货,world
和return
語句(結(jié)束執(zhí)行)。
Generator
函數(shù)是分段執(zhí)行的宏娄,yield
表達式是暫停執(zhí)行的標記问裕,而next
方法可以恢復(fù)執(zhí)行。
總結(jié)一下孵坚,調(diào)用 Generator 函數(shù)粮宛,返回一個遍歷器對象,代表 Generator 函數(shù)的內(nèi)部指針十饥。以后窟勃,每次調(diào)用遍歷器對象的next
方法祖乳,就會返回一個有著value
和done
兩個屬性的對象逗堵。value
屬性表示當前的內(nèi)部狀態(tài)的值,是yield
表達式后面那個表達式的值眷昆;done
屬性是一個布爾值蜒秤,表示是否遍歷結(jié)束。
四亚斋、可迭代對象與for ... of
一個數(shù)據(jù)結(jié)構(gòu)只要部署了Symbol.iterator
屬性作媚,就被視為具有iterator
接口,就可以用for...of
循環(huán)遍歷它的成員帅刊。如果一個對象具有Symbol.iterator
屬性纸泡,則就稱這個對象是可迭代的對象。
for...of
循環(huán)可以使用的范圍包括數(shù)組赖瞒、Set
和Map
結(jié)構(gòu)女揭、某些類似數(shù)組的對象(比如arguments
對象、DOM NodeList
對象)栏饮、Generator 對象吧兔,以及字符串。
數(shù)組和普通對象都可以用for...in
來遍歷袍嬉,但數(shù)組可以迭代境蔼,而普通對象不能迭代灶平。而且 JS 原有的for...in
循環(huán),只能獲得對象的鍵名箍土,不能直接獲取鍵值逢享。
const arr = ['red', 'green', 'blue'];
for (let key in arr) {
console.log(key) // 0, 1, 2
}
var obj = {
name: 'JOJO',
sex: '男',
skills: '歐啦歐啦'
}
for (let key in obj) {
console.log(key) // name, sex, skills
}
ES6 提供了for...of
循環(huán),允許遍歷獲得鍵值吴藻。
但是對于普通的對象拼苍,for...of
結(jié)構(gòu)不能直接使用,會報錯
這是因為數(shù)組默認部署了Symbol.iterator
屬性调缨,而對象卻沒有這個屬性
有兩個辦法可以解決這個問題
一是使用Object.keys
方法將對象的鍵名生成一個數(shù)組疮鲫,然后遍歷這個數(shù)組。
var obj = {
name: 'JOJO',
sex: '男',
skills: '歐啦歐啦'
}
for (var key of Object.keys(obj)) {
console.log(key + ': ' + obj[key]); // name: JOJO, sex: 男, skills: 歐啦歐啦
}
二是使用 Generator 函數(shù)將對象重新包裝一下弦叶。
五俊犯、總結(jié)一下 JS 里的遍歷方法
以數(shù)組為例,JS里有以下幾種遍歷方法
- for循環(huán)
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}
缺點:寫起來比較麻煩
- forEach
myArray.forEach(function (value) {
console.log(value);
});
缺點:無法中途跳出forEach
循環(huán)伤哺,break
命令或return
命令都不能奏效燕侠。
- for...in(遍歷鍵名)
for (var index in myArray) {
console.log(myArray[index]);
}
缺點:
- 數(shù)組的鍵名是數(shù)字,但是
for...in
循環(huán)是以字符串作為鍵名“0”立莉、“1”绢彤、“2”等等。 -
for...in
循環(huán)不僅遍歷數(shù)字鍵名蜓耻,還會遍歷手動添加的其他鍵茫舶,甚至包括原型鏈上的鍵。 - 某些情況下刹淌,
for...in
循環(huán)會以任意順序遍歷鍵名饶氏。
總之,for...in
循環(huán)主要是為遍歷對象而設(shè)計的有勾,不適用于遍歷數(shù)組疹启。
- for...of(遍歷鍵值)
如果用for...of
遍歷對象,則必須是可迭代的對象蔼卡。
for (let value of myArray) {
console.log(value);
}
for...of
循環(huán)相比上面幾種做法喊崖,有一些顯著的優(yōu)點:
- 有著同
for...in
一樣的簡潔語法,但是沒有for...in
那些缺點雇逞。 - 不同于
forEach
方法荤懂,它可以與break
、continue
和return
配合使用喝峦。 - 提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口势誊。
參考:
迭代器與 for of的使用和原理
Iterator 和 for...of 循環(huán)
Generator 函數(shù)的語法
迭代器和生成器 MDN