Iterator 和 for...of 循環(huán)

一锰什、Iterator(遍歷器)的概念

遍歷器(Iterator) 是一種接口下硕,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一訪問(wèn)機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)汁胆,只要部署 Iterator 接口梭姓,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)

Iterator 的作用有3個(gè):

  • 為各種數(shù)據(jù)結(jié)構(gòu)提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問(wèn)接口
  • 使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列
  • ES6 創(chuàng)造了一種新的遍歷命令 —— for...of 循環(huán)嫩码,Iterator 接口主要提供 for...of 消費(fèi)誉尖。

Iterator 的遍歷過(guò)程如下:

  1. 創(chuàng)建一個(gè)指針對(duì)象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置谢谦。也就是說(shuō)释牺,遍歷器對(duì)象本質(zhì)上就是一個(gè)指針對(duì)象
  2. 第一次調(diào)用指針對(duì)象的 next 方法,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個(gè)成員
  3. 第二次調(diào)用指針對(duì)象的 next 方法回挽,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個(gè)成員
  4. 不斷調(diào)用指針對(duì)象的 next 方法没咙,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置

每次調(diào)用 next 方法都會(huì)返回?cái)?shù)據(jù)結(jié)構(gòu)的當(dāng)前成員信息。具體來(lái)說(shuō)就是返回一個(gè)包含 value 和 done 兩個(gè)屬性的對(duì)象千劈。其中祭刚,value 屬性時(shí)當(dāng)前成員的值,done 屬性時(shí)一個(gè)布爾值墙牌,表示遍歷是否結(jié)束

模擬 next 方法返回值的例子

var it = makeIterator(['a', 'b'])

function makeIterator(array) {
  var nextIndex = 0
  return {
    next() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true}
    }
  }
}

it.next() // {value: "a", done: false}
it.next() // {value: "b", done: false}
it.next() // {value: undefined, done: true}

對(duì)于遍歷器來(lái)說(shuō)涡驮,done: falsevalue: undefined 屬性都是可以省略的,因此上面的 makeIterator 函數(shù)可以簡(jiǎn)寫成下面的形式

function makeIterator(array) {
  var nextIndex = 0
  return {
    next() {
      return nextIndex < array.length ?
        {value: array[nextIndex++] } :
        { done: true }
    }
  }
}

由于 Iterator 只是把接口規(guī)格加到了數(shù)據(jù)結(jié)構(gòu)上喜滨,所以捉捅,遍歷器與所遍歷的數(shù)據(jù)結(jié)構(gòu)實(shí)際上是分開(kāi)的。

var it = idMaker()

function idMaker() {
  var index = 0
  
  return {
    next() {
      return {value: index++, done: false}
    }
  }
}

it.next().value // '0'
it.next().value // '1'
// ...

遍歷器生成函數(shù) idMaker 返回一個(gè)遍歷器對(duì)象(即指針對(duì)象)虽风。但是并沒(méi)有對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)棒口,或者說(shuō),遍歷器對(duì)象自己描述了一個(gè)數(shù)據(jù)結(jié)構(gòu)辜膝。

二无牵、默認(rèn) Iterator 接口

當(dāng)使用 for...of 循環(huán)遍歷某種數(shù)據(jù)結(jié)構(gòu)時(shí),該循環(huán)會(huì)自動(dòng)去尋找 Iterator 接口厂抖。數(shù)據(jù)結(jié)構(gòu)只要部署了Iterator 接口茎毁,我們就稱這種數(shù)據(jù)結(jié)構(gòu)為“可遍歷”(iterable) 的。
ES6規(guī)定忱辅,默認(rèn)的Iterator接口部署在數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator 屬性七蜘,一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有 Symbol.iterator 屬性谭溉,就可以認(rèn)為是“可遍歷的”(iterable)

const obj = {
  [Symbol.itear]() {
    return {
      next() {
        return { value: 1, done: true }
      }
    }
  }
}

所有部署了 Symbol.iterator 屬性的數(shù)據(jù)結(jié)構(gòu)都稱為部署了遍歷器接口。調(diào)用這個(gè)接口就會(huì)返回一個(gè)遍歷器對(duì)象

原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下:

  • Array
  • Map
  • Set
  • String
  • TypeArray
  • 函數(shù)的 arguments 對(duì)象
  • NodeList 對(duì)象

數(shù)組的 Symbol.iterator 屬性

let arr = ['a', 'b', 'c']
let iter = arr[Symbol.iterator]()

iter.next()
// {value: "a", done: false}
iter.next()
// {value: "b", done: false}
iter.next()
// {value: "c", done: false}
iter.next()
// {value: undefined, done: true}

arr 具有遍歷器接口橡卤,部署在 arr 的 Symbol.iterator屬性上夜只。所以,調(diào)用這個(gè)屬性就會(huì)得到遍歷器對(duì)象蒜魄。


對(duì)象(Object) 沒(méi)有部署Iterator 接口, 是因?yàn)閷?duì)象屬性的遍歷先后順序是不正確的场躯,本質(zhì)上谈为,遍歷器是一種線性處理,對(duì)于任何非線性的數(shù)據(jù)結(jié)構(gòu)踢关,部署遍歷器接口就等于部署一種線性轉(zhuǎn)換伞鲫。嚴(yán)格地說(shuō),對(duì)象部署遍歷器接口并不是很必要签舞,因?yàn)檫@時(shí)對(duì)象實(shí)際上被當(dāng)作 Map 結(jié)構(gòu)使用秕脓,ES5 沒(méi)有 Map 結(jié)構(gòu),而 ES6 原生提供了儒搭。

一個(gè)對(duì)象如果要具備可被 for...of 循環(huán)調(diào)用的 Iterator 接口吠架,就必須再 Symbol.iterator 的屬性上部署遍歷器生成方法(原型鏈上的對(duì)象具有改方法也可)

類 部署 Iterator 接口的寫法

class RangeIterator {
  constructor(start, stop) {
    this.value = start
    this.stop = stop
  }

  [Symbol.iterator]() { return this }

  next() {
    var value = this.value
    if (value < this.stop) {
      this.value++
      return { done: false, value: value }
    }
    return { done: true, value: undefined }
  }
}

function range(start, stop) {
  return new RangeIterator(start, stop)
}

for (var value of range(0, 3)) {
  console.log(value)
}

下面是通過(guò) 遍歷器 實(shí)現(xiàn)指針結(jié)構(gòu)的例子

function Obj(value) {
  this.value = value
  this.next = null
}

Obj.prototype[Symbol.iterator] = function() {
  var iterator = { next: next }

  var current = this

  function next() {
    if (current) {
      var value = current.value
      current = current.next
      return { done: false, value: value }
    } else {
      return { done: true }
    }
  }
  return iterator
}

var one = new Obj(1)
var two = new Obj(2)
var three = new Obj(3)

one.next = two
two.next = three

for (var i of one) {
  console.log(i) // 1, 2, 3
 }

首先再構(gòu)造函數(shù)的原型鏈上部署 Symbol.iterator 方法,調(diào)用改方法會(huì)返回 遍歷器對(duì)象 iterator搂鲫,調(diào)用該對(duì)象的 next 方法傍药,在返回一個(gè)值的同時(shí)自動(dòng)將內(nèi)部指針移到 下一個(gè)實(shí)例。

下面是另一個(gè)為對(duì)象添加 Iterator 接口的例子

let obj = {
  data: ['hello', 'world'],
  [Symbol.iterator[() {
    const self = this
    let index = 0
    return  {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++],
            done: false
          }
        } else {
          return { value: undefined, done: true }
        }
      }
    }
  }
}

對(duì)于類似數(shù)組的對(duì)象(存在數(shù)值鍵名和 length屬性)魂仍,部署 Iterator 接口有一個(gè)簡(jiǎn)便方法拐辽,即使用 Symbol.iterator 方法直接引用數(shù)組的 Iterator 接口。

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]

// 或者 
NodeList.prototype[Symbol.iterator] = [] [Symbol.iterator]

[...document.querySelectorAll('div')] // 可以執(zhí)行

NodeList 對(duì)象是類似數(shù)組的對(duì)象擦酌,本來(lái)就具有遍歷接口俱诸,將它的遍歷接口改成數(shù)組的 Symbol.iterator 屬性,沒(méi)有任何影響

let iterable = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
}

for (let item of iterable) {
  console.log(item) // 'a', 'b', 'c'
}

注意:普通對(duì)象部署數(shù)組的 Symbol.iterator 方法并無(wú)效果赊舶。

如果 Symbol.iterator 方法對(duì)應(yīng)的不是遍歷器生成函數(shù)(即會(huì)返回一個(gè)遍歷器對(duì)象)睁搭,解釋引擎將報(bào)錯(cuò)。

var obj = {}

obj[Symbol.iterator] = () => 1

[...obj] // TypeError: [] is not a function

三锯岖、調(diào)用 Iterator 接口的場(chǎng)合

有一些場(chǎng)合會(huì)默認(rèn)調(diào)用 Iterator 接口(即 Symbol.iterator 方法)介袜,除了 for...of 循環(huán) 還有幾個(gè)別的場(chǎng)合

1. 解構(gòu)賦值
對(duì)數(shù)組和 Set 結(jié)構(gòu)進(jìn)行結(jié)構(gòu)賦值時(shí),會(huì)調(diào)用 Symbol.iterator 方法

let set = new Set().add('a').add('b').add('c')

let [x, y] = set
// x = 'a'; b = 'b'

let [first, ...rest] = set
//first = 'a'; rest = ['b', 'c']

2. 擴(kuò)展運(yùn)算符

擴(kuò)展運(yùn)算符(...)也會(huì)調(diào)用默認(rèn)的 Iterator 接口出吹。

var str = 'hello';
[...str] //  ["h", "e", "l", "l", "o"]

這提供了一種簡(jiǎn)便機(jī)制遇伞,只要某個(gè)數(shù)據(jù)結(jié)構(gòu)部署了 Iterator 接口,就可以對(duì)它使用擴(kuò)展運(yùn)算符捶牢,將其轉(zhuǎn)為數(shù)組

let arr = [...iterable]

3. yield*

yield* 后面跟的是一個(gè)可遍歷的結(jié)構(gòu)鸠珠,它會(huì)調(diào)用該結(jié)構(gòu)的遍歷器接口巍耗。

let generator = function* () {
  yield 1
  yield* [2, 3, 4]
  yield 5
}
var iterator = generator()

iterator.next()
// {value: 1, done: false}
iterator.next()
// {value: 2, done: false}
iterator.next()
// {value: 3, done: false}
iterator.next()
// {value: 4, done: false}
iterator.next()
// {value: 5, done: false}
iterator.next()
// {value: undefined, done: true}

4. 其他場(chǎng)合
由于數(shù)組的遍歷會(huì)調(diào)用遍歷器接口,所以任何接受數(shù)組作為參數(shù)的場(chǎng)合其實(shí)都調(diào)用了遍歷器接口渐排。

  • for...of
  • Array.from()
  • Map()炬太、Set()、WeakMap()驯耻、WeakSet()
  • Promise.all()
  • Promise.race()

四亲族、字符串的 Iterator 接口

字符串是一個(gè)類似數(shù)組的對(duì)象,也具有原生 Iterator 接口

var someString = 'hi'
typeof someString[Symbol.iterator]
// 'function'

var iterator = someString[Symbol.iterator]()

iterator.next()
// {value: "h", done: false}
iterator.next()
// {value: "i", done: false}
iterator.next()
// {value: undefined, done: true}

可以覆蓋原生的 Symbol.iterator 方法達(dá)到修改遍歷器行為的目的可缚。

var str = new String('hi');

[...str] // ['h', 'i']

str[Symbol.iterator] = function() {
  return {
    next() {
      if (this._first) {
        this._first = false
        return { value: 'bye', done: false }
      } else {
        return { done: true }
      }
    }, 
    _first: true
  }
};

[...str] // ['bye']
str // 'hi'

上面的代碼中霎迫,字符串 str 的 Symbol.iterator 方法被修改了,所以擴(kuò)展運(yùn)算符(...) 返回的值變成了 bye帘靡,而字符串本身還是 hi知给。

五、Iterator 接口 與 Generator 函數(shù)

Symbol.iterator 方法的最簡(jiǎn)單實(shí)現(xiàn)還是使用 Generator 函數(shù)

var myIterable = {}

myIterable[Symbol.iterator] = function* () {
  yield 1
  yield 2
  yield 3
}
[...myIterable] // [1, 2, 3]

// 或者采用下面的簡(jiǎn)潔寫法

let obj = {
  * [Symbol.iterator]() {
    yield 'hello'
    yield 'world'
  }
}

for (let x of obj) {
  console.log(x)
}
// hello
// world

Symbol.iterator 方法幾乎不用部署任何代碼描姚,只要用 yield 命令給出每一步的返回值即可

六涩赢、遍歷器對(duì)象 return()、throw()

遍歷器對(duì)象除了具有 next方法轩勘,還可以具有 return 方法 和 throw 方法筒扒。如果自己寫遍歷器對(duì)象生成函數(shù),next 方法是必須部署的赃阀,return 方法 和 throw 方法則是可選部署的

return 方法的使用場(chǎng)合是霎肯,如果 for...of 循環(huán)提前退出(常常是因?yàn)槌鲥e(cuò),或者有 break 語(yǔ)句 或 continue 語(yǔ)句)榛斯,就會(huì)調(diào)用 return 方法观游;

function readLinesSync(file) {
  return {
    next() {
      return { done: true }
    },
    return() {
      file.close()
      return { done: true }
    }
  }
}

函數(shù) readLinesSync 接受一個(gè)文件對(duì)象作為參數(shù),返回一個(gè)遍歷器對(duì)象驮俗。

讓文件的變量提前返回懂缕,這樣就會(huì)觸發(fā)執(zhí)行 return 方法

for (let line of readLinesSync(fileName)) {
  console.log(line)
  break;
}

注意:return 方法必須返回一個(gè)對(duì)象,這是 Generator 規(guī)格決定的

throw 方法主要配合 Generator 函數(shù)使用王凑,一般的遍歷器對(duì)象用不到這個(gè)方法搪柑。

七、for...of 循環(huán)

ES6 引入了 for...of 循環(huán)作為遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一方法索烹。for...of 循環(huán)內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator 方法工碾。
for...of 循環(huán)可以使用的范圍包括數(shù)組、Set 和 Map 結(jié)構(gòu)百姓、某些類似數(shù)組的對(duì)象(比如 arguments 對(duì)象渊额、DOM NodeList 對(duì)象)、Generator 對(duì)象,以及字符串

7.1旬迹、數(shù)組

數(shù)組原生具備 iterator 接口(即默認(rèn)部署了 Symbol.iterator 屬性)火惊,for...of 循環(huán)本質(zhì)上就是調(diào)用這個(gè)接口產(chǎn)生的遍歷器。

const arr = ['red', 'green', 'blue']

for(let v of arr) {
  console.log(v) // red green blue
}

const obj = {}
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr)

for(let v of obj) {
  console.log(v) // red green blue
}

空對(duì)象 obj 部署了數(shù)組 arr 的 Symbol.iterator 屬性奔垦,結(jié)果 obj 的 for...of 循環(huán)產(chǎn)生了與 arr 完全一樣的效果

for...of 循環(huán)可以代替數(shù)組實(shí)例的 forEach 方法屹耐。


JavaScript 原有的 for...in 循環(huán)只能獲得對(duì)象的鍵名,不能直接獲取鍵值椿猎。ES6提供的 for...of循環(huán)允許遍歷獲取鍵值惶岭。

let arr = ['a', 'b', 'c', 'd', 'e'];

for (let a in arr) {
  console.log(a) // 0 1 2 3 4
}

for (let a of arr) {
  console.log(a) // a b c d e
}

如果要通過(guò) for...of 循環(huán)獲取數(shù)組的索引,可以借助數(shù)組實(shí)例的 entries 方法和 keys 方法

for...of 循環(huán)調(diào)用遍歷器接口犯眠,數(shù)組的遍歷器接口只返回具有數(shù)字索引的屬性俗他。這一點(diǎn)跟 for...in 循環(huán)也一樣。

let arr = [3, 5, 7]
arr.foo = 'hello'

for (let i in arr) {
  console.log(i) // 0 1 2 foo
}

for (let i of arr) {
  console.log(i) // 3 5 7
}

for...of 循環(huán)不會(huì)返回?cái)?shù)組 arr 的 foo 屬性

7.2阔逼、Set 和 Map 結(jié)構(gòu)

Set 和 Map 結(jié)構(gòu)原生具有 Iterator 接口,可以直接使用 for...of 循環(huán)

var engines = new Set(['Gecko', 'Trident', 'WebKit'])
for (var e of engines) {
  console.log(e)
}
// Gecko
// Trident
// WebKit


var es6 = new Map()
es6.set('edition', 6)
es6.set('committee', 'TC39')
es6.set('standard', 'ECMA-262')
for (var [name, value] of es6) {
  console.log(name + ": " + value)
}
// edition: 6
// committee: TC39
// standard: ECMA-262

上面演示了 如何遍歷Set結(jié)構(gòu)和Map 結(jié)構(gòu)地沮,值得注意的地方有兩個(gè):

  • 遍歷的順序時(shí)按照各個(gè)成員被添加進(jìn)數(shù)據(jù)結(jié)構(gòu)的順序
  • Set 結(jié)構(gòu)遍歷時(shí)返回的是一個(gè)值嗜浮,而 Map 結(jié)構(gòu)遍歷時(shí)返回的是一個(gè)數(shù)組,該數(shù)組的兩個(gè)成員分別為當(dāng)前Map成員的鍵名和鍵值
let map = new Map().set('a', 1).set('b', 2)
for(let pair of map) {
  console.log(pair)
}
// ["a", 1]
// ["b", 2]

for (lett [key, value] of map) {
  console.log(key + ': ' + value)
}
// a: 1
// b: 2

7.3摩疑、計(jì)算生成的數(shù)據(jù)結(jié)構(gòu)

有些數(shù)據(jù)結(jié)構(gòu)是現(xiàn)在數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)上計(jì)算生成的危融。比如,ES6的數(shù)組雷袋、Set吉殃、Map都部署了一下三個(gè)方法,調(diào)用后都返回遍歷器對(duì)象

  • entries():返回一個(gè)遍歷器對(duì)象楷怒,用于遍歷[鍵名蛋勺,鍵值] 組成的數(shù)組。對(duì)于數(shù)組鸠删,鍵名就是索引抱完;對(duì)于 Set,鍵名與鍵值相同刃泡。Map 結(jié)構(gòu)的iterator 接口默認(rèn)就是調(diào)用 entries 方法
  • keys():返回一個(gè)遍歷器對(duì)象巧娱,用于遍歷所有的鍵名
  • values():返回一個(gè)遍歷器對(duì)象,用于遍歷所有的鍵值

這 3 個(gè)方法調(diào)用后生成的遍歷器對(duì)象所遍歷的都是計(jì)算生成的數(shù)據(jù)結(jié)構(gòu)

let arr = ['a', 'b', 'c']
for (let pair of arr.entries()) {
  console.log(pair)
}
// [0, "a"]
// [1, "b"]
// [2, "c"]

7.4烘贴、類似數(shù)組的結(jié)構(gòu)

類似數(shù)組的對(duì)象包括好幾類禁添。下面是 for...of 循環(huán)用于字符串、DOM NodeList 對(duì)象 arguments 對(duì)象的例子

// 字符串
let str = 'hello'
for (let s of str) {
  console.log(s) // h e l l o
}

// DOM NodeList 對(duì)象
let paras = document,querySelectorAll('p')

for(let p of paras) {
  p.classList.add('test')
}

// arguments 對(duì)象
function printArgs() {
  for (let x of arguments) {
    console.log(x)
  }
}
printArgs(1, 2, 3)// 1 2 3

對(duì)于字符串來(lái)說(shuō)桨踪,for...of 循環(huán)還有一個(gè)特點(diǎn)老翘,就是可以正確識(shí)別 32 位 UTF-16 字符。


并不是所有類似數(shù)組的對(duì)象都具有 Iterator 接口,一個(gè)簡(jiǎn)便的解決方法就是使用 Array.from 方法將其轉(zhuǎn)為數(shù)組酪捡。

let arrayLike = {
  0: 'a',
  1: 'b',
  length: 2
}

// 報(bào)錯(cuò)
for (let x of arrayLike) {
  console.log(x)
}

// 正確
for(let x of Array.from(arrayLike)) {
  console.log(x) // a b
}

7.5叁征、對(duì)象

對(duì)于普通的對(duì)象,for...of 結(jié)構(gòu)不能直接使用逛薇,否則會(huì)報(bào)錯(cuò)捺疼,必須部署了 Iterator 接口才能使用。但是永罚,這樣的情況下啤呼,for...in 循環(huán)依然可用于遍歷鍵名

let es6 = {
  edition: 6,
  committee: 'TC39',
  standard: 'ECMA-262'
}

for(let e in es6) {
  console.log(e)
}
// edition
// committee
// standard

for (let e of es6) {
  console.log(e)
}
// TypeError: es6 is not iterable

解決方法是,使用 Object.keys 方法將對(duì)象的鍵名生成一個(gè)數(shù)組呢袱,然后遍歷這個(gè)數(shù)組

for(var key of Object.keys(someObject)) {
  console.log(key + ': ' + someObject[key])
}

另一個(gè)方法是 使用 Generator 函數(shù)將對(duì)象重新包裝一下官扣。

function* entries(obj) {
  for(let key of Object.keys(obj)) {
    yield [key, obj[key]]
  }
}

for (let [key, value] of entries(obj)) {
  console.log(key, ' - > ', value)
}

7.6、與其他遍歷語(yǔ)法的比較

以數(shù)組為例羞福,JavaScript 提供了很多遍歷語(yǔ)法惕蹄。最原始的寫法就是 for 循環(huán)。

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index])
}

這種寫法比較麻煩治专,因此數(shù)組提供了內(nèi)置的 forEach 方法卖陵。

myArray.forEach( value => {
  console.log(value)
})

這種寫法的問(wèn)題在于,無(wú)法中途跳出 forEach 循環(huán)张峰,break泪蔫、return 命令都不能。

for...in 循環(huán)可以遍歷數(shù)組的鍵名喘批。

for (var index in myArray) {
  console.log(myArray[index])
}

for...in 循環(huán)有幾個(gè)缺點(diǎn)撩荣。

  • 數(shù)組的鍵名是數(shù)字,但是 for...in 循環(huán)是以字符串作為鍵名饶深,"0"餐曹、"1"、"2"等敌厘。
  • for...in 循環(huán)不僅可以遍歷數(shù)字鍵名凸主,還會(huì)遍歷手動(dòng)添加的其他鍵,甚至包括原型鏈上的鍵
  • 某些情況下额湘,for...in 循環(huán)會(huì)以任意順序遍歷鍵名

總之卿吐,for...in 尋魂主要視為遍歷對(duì)象而設(shè)計(jì)的,不適合遍歷數(shù)組

for...of 循環(huán)相比上面幾種做法有一些明顯的優(yōu)點(diǎn)锋华。

for (let value of myArray) {
  console.log(value)
}
  • 有著同 for...of 一樣的簡(jiǎn)潔語(yǔ)法嗡官,但是沒(méi)有 for...in 那些缺點(diǎn)
  • 不同于 forEach 方法,它可以與 break毯焕、continue 衍腥、return 配合使用
  • 提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末磺樱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子婆咸,更是在濱河造成了極大的恐慌竹捉,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尚骄,死亡現(xiàn)場(chǎng)離奇詭異块差,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)倔丈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門憨闰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人需五,你說(shuō)我怎么就攤上這事鹉动。” “怎么了宏邮?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵泽示,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蜜氨,道長(zhǎng)边琉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任记劝,我火速辦了婚禮,結(jié)果婚禮上族扰,老公的妹妹穿的比我還像新娘厌丑。我一直安慰自己,他們只是感情好渔呵,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布怒竿。 她就那樣靜靜地躺著,像睡著了一般扩氢。 火紅的嫁衣襯著肌膚如雪耕驰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天录豺,我揣著相機(jī)與錄音朦肘,去河邊找鬼。 笑死双饥,一個(gè)胖子當(dāng)著我的面吹牛媒抠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咏花,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趴生,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起苍匆,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刘急,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后浸踩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體叔汁,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年民轴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了攻柠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡后裸,死狀恐怖瑰钮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情微驶,我是刑警寧澤浪谴,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站因苹,受9級(jí)特大地震影響苟耻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扶檐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一凶杖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧款筑,春花似錦智蝠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至攘须,卻和暖如春漆撞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背于宙。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工浮驳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捞魁。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓抹恳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親署驻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奋献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Iterator(遍歷器)的概念 JavaScript原有的表示“集合”的數(shù)據(jù)結(jié)構(gòu)健霹,主要是數(shù)組和對(duì)象,ES6又添加...
    oWSQo閱讀 609評(píng)論 0 1
  • 一瓶蚂、Iterator(遍歷器)的概念 Iterator 是一種接口糖埋,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問(wèn)機(jī)制。 任何...
    magic_pill閱讀 310評(píng)論 0 1
  • Iterator(遍歷器)的概念 默認(rèn) Iterator 接口 調(diào)用 Iterator 接口的場(chǎng)合 字符串的 It...
    Android_馮星閱讀 289評(píng)論 0 0
  • Iterator(遍歷器)的概念 ??javascript原有的表示"集合"的數(shù)據(jù)結(jié)構(gòu)主要是數(shù)組和對(duì)象窃这,ES6又添...
    A鄭家慶閱讀 306評(píng)論 0 0
  • 今天上冰心的《荷葉.母親》一篇自讀課瞳别,一篇借荷葉在風(fēng)雨中保護(hù)紅蓮的畫面,贊美母愛(ài)的文章杭攻。主旨學(xué)生很好懂祟敛。 ...
    一身書生氣閱讀 635評(píng)論 0 0