<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ES6 迭代器和生成器

          共 6701字,需瀏覽 14分鐘

           ·

          2021-06-08 20:36

          作者 | wangchao
          鏈接 | https://juejin.cn/post/6969842645417852964

          一、可迭代對象和迭代器

          1、可迭代對象指的是,可通過 for/of 循環(huán)的對象,是es6的特性,包括(數(shù)組,字符串,set對象,map對象)

          2、擴展操作符...可以展開可迭代對象

          let chars = [..."abcd"] // chars === ["a","b","c","d"]let data = [1, 2, 3, 4]Math.max(data) // 4

          3、迭代器可用于解構(gòu)賦值

          let purple = Uint8Array.of(255, 0, 255, 128)let [r, g, b, a] = purple // a===128

          4、 迭代map對象,返回值是[key,value]對, 在for/of中可直接解構(gòu)賦值

          let m = new Map([["one", 1], ["two", 2]])for (let [k, v] of m) console.log(k, v);

          5、值迭代鍵或值,可使用keys()或values()

          [...m]; // [["one", 1], ["two", 2]][...m.entries()]; // [["one", 1], ["two", 2]][...m.keys()]; // ["one","two"][...m.values()]; // [1,2]

          6、可接收Array對象的內(nèi)置函數(shù)和構(gòu)造函數(shù),可接收任意迭代器

          new Set("abc"); new Set(["a", "b", "c"]); // 兩者相同

          7、迭代器原理

          // 可迭代對象:具有迭代器的方法,且該方法返回迭代器的對象let list1 = [1, 2]// 迭代器對象:具有next()方法,且該方法返回迭代結(jié)果的對象listlet iterator = list1[Symbol.iterator]() //有一個Symbol.iterator方法,返回自己// 迭代結(jié)果:具有屬性value和done的對象for (let result = iterator.next(); !result.done; result = iterator.next()) {    console.log(result.value);}// 例let list2 = [1, 2, 3, 4, 5]let iter = list2[Symbol.iterator]()console.log(iter.next().value); // 1console.log([...iter]); // [2, 3, 4, 5]

          二、可迭代對象的實現(xiàn)

          原則:只要數(shù)據(jù)類型表示某種可迭代的結(jié)構(gòu),就應該實現(xiàn)為可迭代對象。

          實現(xiàn):為了讓類可迭代,必須實現(xiàn)一個Symbol.iterator的方法,該方法必須返回一個迭代器對象,該對象有一個next()方法,next()方法必須返回一個有value和done屬性的對象。

          操作:可迭代的數(shù)值Range類

          1、Range對象表示一個數(shù)值范圍{x: form<=x<=to}

          /* Range定義了has()方法,用于測試給定數(shù)值是不是該范圍的成員 Range是可迭代的,迭代其范圍內(nèi)的所有整數(shù) */class Range {    constructor(from, to) {        this.from = from        this.to = to    }    has(x) {        return typeof x === 'number' &&            x >= this.from &&            x <= this.to    }    toString() { return `{x: ${this.from}<=x <=${this.to}}` }    [Symbol.iterator]() {        let next = Math.ceil(this.from);        let last = this.to        return {            next() {                return {                    done: next > last,                    value: next++,                }            }        }    }}

          console.log(new Range(1, 3).toString());console.log(new Range(1, 3).has(4));
          for (const i of new Range(1, 3)) { console.log(i);}
          console.log([...new Range(-1, 3)]);

          2、定義返回可迭代值的函數(shù)

          // 替代數(shù)組的map方法function map(iterable, fn) {    let iterator = iterable[Symbol.iterator]()    // 返回一個可迭代對象,也是迭代器對象    return {        [Symbol.iterator]() { return this },        next() {            let obj = iterator.next()            if (obj.done) {                return obj            } else {                return { value: fn(obj.value) }            }        }    }}console.log([...map([1, 2, 3], x => x * x)]);// 替代數(shù)組的filter方法function filter(iterable, fn) {    let iterator = iterable[Symbol.iterator]()    // 返回一個可迭代對象,也是迭代器對象    return {        [Symbol.iterator]() { return this },        next() {            while (true) {                let obj = iterator.next()                if (fn(obj.value) || obj.done) {                    return obj                }            }        }    }}console.log([...filter([1, 2, 3, 4, 5, 6, 12, 56], x => x > 3)]);

          3、懶惰迭代

          // 假設一個非常長的字符串想要以空格為分隔,如果使用字符串split方法,那么要處理整個字符串,// 會占用很多內(nèi)存來保存返回的數(shù)組和其中的字符串.// 使用懶惰迭代,則不必全部保存在內(nèi)存function words(s) {    let r = /\s+|$/g    r.lastIndex = s.match(/[^ ]/).index    return {        [Symbol.iterator]() { return this },        next() {            let start = r.lastIndex            if (start < s.length) { let match = r.exec(s) if (match) { return { value: s.substring(start, match.index) } } }            return { done: true }        }    }} console.log([...words(" abc def ghi ")]);

          三、生成器概念和實例

          原則:生成器是es6語法定義的迭代器,適合要迭代的值不是某個數(shù)據(jù)結(jié)構(gòu)的元素,而是計算結(jié)果的場景。

          實現(xiàn):創(chuàng)建生成器需要先定義一個生成器函數(shù),使用關(guān)鍵字function*,調(diào)用生成器函數(shù)不會執(zhí)行函數(shù)體,而是返回一個迭代器。

          操作:調(diào)用迭代器的next方法,會導致生成器函數(shù)的函數(shù)體從頭開始執(zhí)行,知道遇見一個yield語句。yield語句的值,會成為返回值。 

          yield 和yield*只能在生成器函數(shù)中使用,常規(guī)函數(shù)不能出現(xiàn)!

          1、例子

          // 例1function* oneDigitPrimes() {    yield 2;    yield 3;    yield 5;    yield 7;}let primes = oneDigitPrimes()primes.next().value // 2primes.next().value // 3console.log(primes.next().value); // 5console.log(primes.next().done); // falseconsole.log(primes.next().done); // true
          let primesIterator = primes[Symbol.iterator]()// 可迭代對象console.log(primesIterator.next()); // {value: undefined, done: true}
          console.log([...oneDigitPrimes()]); //[2, 3, 5, 7]let sum = 0for (const v of oneDigitPrimes()) { sum += v}console.log(sum); // 17
          // 例2const seq = function* (from, to) { for (let i = from; i <= to; i++) yield i}console.log([...seq(3, 5)]); // [3, 4,5]
          // 例3 類和對象字面量, 不能使用箭頭函數(shù)定義生成器函數(shù)let o = { x: 1, y: 2, z: 3, *g() { for (const key of Object.keys(this)) { yield key } }}console.log([...o.g()]); //["x", "y", "z", "g"]
          // 例4 無限回送斐波那契數(shù) 如果執(zhí)行[...fibonacciSequence()]會一直循環(huán)直到內(nèi)存耗盡function* fibonacciSequence() { let x = 0, y = 1; while (1) { yield y; [x, y] = [y, x + y] }}
          //通過限制條件, 返回第20個斐波那契數(shù)function fibonacci(n) { for (const f of fibonacciSequence()) { if (n-- <= 0) { return f } }}console.log(fibonacci(10)); //89
          // 配合take生成器(用另一個生成器封裝一下) 回送指定可迭代對象的前n個元素function* take(n, iterable) { let it = iterable[Symbol.iterator]() while (n-- > 0) { let next = it.next() if (next.done) { return } yield next.value }}console.log([...take(5, fibonacciSequence())]); //[1, 1, 2, 3, 5]
          // 拿到可迭代對象數(shù)組,交替回送元素function* zip(...iterables) { // 取得每個可迭代對象的迭代器 let iterators = iterables.map(i => i[Symbol.iterator]()) let index = 0 while (iterators.length > 0) { if (index >= iterators.length) { index = 0 } let item = iterators[index].next() if (item.done) { iterators.splice(index, 1) } else { yield item.value index++ } }}console.log([...zip(oneDigitPrimes(), 'ab', [0])]); //[2, "a", 0, 3, "b", 5, 7]
          // yield*與遞歸生成器// 順序回送元素function* sequence(...iterables) { for (const iterable of iterables) { for (const item of iterable) { yield item; } }}console.log([...sequence("abc", [1, 2, 3])]); // ["a", "b", "c", 1, 2, 3]// 使用yield* 簡化function* sequence2(...iterables) { for (const item of iterables) { yield* item }}console.log([...sequence2('abc', 'def')]); // ["a", "b", "c", "d", "e", "f"]

          2、生成器函數(shù)返回值

          function* oneAndDone() {    yield 1    return "done"}// 正常迭代中不會出現(xiàn)返回值console.log([...oneAndDone()]); // [1]//在顯式調(diào)用next可以得到let generator = oneAndDone()console.log(generator.next()); // { value: 1, done: false }console.log(generator.next()); // { value: 'done', done: true }console.log(generator.next()); // { value: undefined, done: true }

          本文完~

          學習更多技能

          請點擊下方公眾號

          瀏覽 24
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天视频黄 | 中文字幕免费在线观看 | 国内自拍青青 | 婷婷丁香五月天影院亚洲综合桃花 | 国产黄色视频在线观看免费 |