第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

TypeScript 迭代器(Iterator)

如果要從一個數(shù)據(jù)集中獲取一個數(shù)據(jù)項,可以對這個數(shù)據(jù)集進(jìn)行迭代。

JavaScript 提供了許多迭代集合的方法,從簡單的 for 循環(huán)到 map()filter()。本節(jié)要介紹的迭代器也是一種方案,并且迭代器將迭代的概念直接帶入核心語言,同時提供了一種機制來自定義 for...of 循環(huán)的行為。

1. 慕課解釋

迭代器是一種特殊對象,它符合迭代器協(xié)議規(guī)范。在 TypeScript 中,我們可以定義一個接口,這個接口上有一個函數(shù)類型 next ,next() 方法的返回值類型是 { value: any, done: boolean }。其中,value 是 any 類型,表示下一個將要返回的值;done 是布爾類型,當(dāng)沒有更多可返回數(shù)據(jù)時返回 true。迭代器還會保存一個內(nèi)部指針,用來指向當(dāng)前集合中值的位置。

迭代器一旦創(chuàng)建,迭代器對象就可以通過重復(fù)調(diào)用 next() 顯式地迭代。

2. 模擬一個簡略的迭代器

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
interface IteratorInterface {
  next: () => {
    value: any
    done: boolean
  }
}

function createIterator(array: any[]): IteratorInterface {
  let index = 0
  let len = array.length

  return {
    next: function () {
      return index < len ? { value: array[index++], done: false } : { value: undefined, done: true }
    }
  }
}

var iterator = createIterator([1, 2, 3])

console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: undefined, done: true }
運行案例 點擊 "運行案例" 可查看在線運行效果

代碼解釋:

第 1 行,聲明了一個 Iterator 接口,具有 next 這樣一個函數(shù)類型。

第 8 行,聲明了一個可以返回迭代器對象的函數(shù),這個函數(shù)的返回值類型必須符合 Iterator 接口。

倒數(shù)第 4 行,通過調(diào)用迭代器對象上的 next() 方法,可以拿到數(shù)據(jù)集中的下一個數(shù)據(jù)項。

最后一行,拿到數(shù)據(jù)集中的所有數(shù)據(jù)后,done 屬性變?yōu)?true。

3. 可迭代性

上面的例子,用模擬的迭代器地迭代了一個數(shù)組對象,那是不是所有的對象都可以這樣迭代呢?當(dāng)然不是。

只有一個對象實現(xiàn)了 Symbol.iterator 屬性時,我們才認(rèn)為它是可迭代的。一些內(nèi)置的類型如 Array,Map,Set,String,Int32Array,Uint32Array 等都已經(jīng)實現(xiàn)了各自的 Symbol.iterator。

Symbol.iterator 屬性本身是一個函數(shù),就是當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的迭代器生成函數(shù)。執(zhí)行這個函數(shù),就會返回一個迭代器。

比如,String 是一個內(nèi)置的可迭代對象:

let str: string = 'Hi'
console.log(typeof str[Symbol.iterator]) // function

String 的默認(rèn)迭代器會依次返回該字符串的字符:

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
let str: string = 'Hi'
let iterator: IterableIterator<string> = str[Symbol.iterator]()
 
console.log(iterator.next())      // { value: 'H', done: false }
console.log(iterator.next())      // { value: 'i', done: false }
console.log(iterator.next())      // { value: undefined, done: true }
運行案例 點擊 "運行案例" 可查看在線運行效果

代碼解釋:

第 1 行,聲明一個字符串類型變量,字符串類型內(nèi)置了默認(rèn)迭代器生成函數(shù) Symbol.iterator

第 2 行,執(zhí)行這個函數(shù),返回了一個迭代器。

總結(jié)一下迭代器的作用:

  • 為各種數(shù)據(jù)結(jié)構(gòu)(Array,Map,Set,String等),提供一個統(tǒng)一的、簡便的訪問接口。
  • 使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列。
  • 創(chuàng)造了一種新的遍歷命令 for..of 循環(huán)。

4. for…of

for...of 會遍歷可迭代的對象(包括 Array,Map,Set,String,TypedArray,arguments 對象等等),調(diào)用對象上的 Symbol.iterator 方法。

4.1 迭代數(shù)組

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
let iterable = [10, 20, 30]

for (const value of iterable) {
  console.log(value)
}
// 10
// 20
// 30
運行案例 點擊 "運行案例" 可查看在線運行效果

解釋: 通過 for...of 循環(huán)遍歷數(shù)組 iterable 的每一項元素。

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
const heroes = [
  {
    name: '艾希',
    gender: 2
  },
  {
    name: '泰達(dá)米爾',
    gender: 1
  }
]

for (let { name } of heroes) {
  console.log(name)
}
運行案例 點擊 "運行案例" 可查看在線運行效果

解釋: 通過 let { name } of heroes 循環(huán)迭代 heroes 對象數(shù)組,將每一個對象解構(gòu),得到每一個對象的 name 屬性值。

4.2 迭代字符串

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
let iterable = 'imooc'

for (const s of iterable) {
  console.log(s)
}
// i
// m
// o
// o
// c
運行案例 點擊 "運行案例" 可查看在線運行效果

字符串具有可迭代性,通過 for...of 可以快速遍歷出每一個字符。

4.3 迭代 Map:

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
let iterable = new Map()

iterable.set('a', 1)
iterable.set('b', 2)
iterable.set('c', 3)

for (let entry of iterable) {
  console.log(entry)
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (let [key, value] of iterable) {
  console.log(value)
}
// 1
// 2
// 3
運行案例 點擊 "運行案例" 可查看在線運行效果

解釋: 一個 Map 對象在迭代時會根據(jù)對象中元素的插入順序來進(jìn)行。for...of 循環(huán)在每次迭代后會返回一個形式為 [key,value] 的數(shù)組。通過使用 let [key, value] 這種解構(gòu)形式,可以快速獲取每一項屬性值。

5. for…of 與 for…in 的區(qū)別

  • for...of 語句遍歷可迭代對象定義要迭代的數(shù)據(jù)。
  • for...in 語句以任意順序迭代對象的可枚舉屬性。
實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
let iterable: number[] = [3, 5, 7]

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i)
  }
}
// 0
// 1
// 2

for (let i of iterable) {
  console.log(i)
}
// 3
// 5
// 7
運行案例 點擊 "運行案例" 可查看在線運行效果

for...in 可以操作任何對象,迭代對象的可枚舉屬性。但是 for...of 只關(guān)注于可迭代對象的值。

6. 解構(gòu)賦值與擴展運算符

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

let [head, ...tail] = [1, 2, 3, 4]
// tail = [2, 3, 4]

擴展運算符也會調(diào)用默認(rèn)的 Iterator 接口,得到一個數(shù)組結(jié)構(gòu):

let arr = [...'imooc']
console.log(arr) //  ['i','m','o','o','c']

7. 小結(jié)

本小節(jié)介紹了迭代器的一些具體使用,要注意 for...offor...in 的區(qū)別。

另外,可以借助編輯器(如 vscode)查看一下 TypeScript 迭代器接口定義的源碼:

interface IteratorYieldResult<TYield> {
  done?: false
  value: TYield
}

interface IteratorReturnResult<TReturn> {
  done: true
  value: TReturn
}

type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>

interface Iterator<T, TReturn = any, TNext = undefined> {
  // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
  next(...args: [] | [TNext]): IteratorResult<T, TReturn>
  return?(value?: TReturn): IteratorResult<T, TReturn>
  throw?(e?: any): IteratorResult<T, TReturn>
}

interface IterableIterator<T> extends Iterator<T> {
    [Symbol.iterator](): IterableIterator<T>;
}