Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 系列之迭代器与 for of #68

Open
yangtao2o opened this issue Apr 6, 2020 · 0 comments
Open

ES6 系列之迭代器与 for of #68

yangtao2o opened this issue Apr 6, 2020 · 0 comments

Comments

@yangtao2o
Copy link
Owner

yangtao2o commented Apr 6, 2020

ES6 系列之迭代器与 for of

所谓迭代器,其实就是一个具有 next() 方法的对象,每次调用 next() 都会返回一个结果对象,该结果对象有两个属性,value 表示当前的值,done 表示遍历是否结束。

用 ES5 的语法创建一个迭代器:

function createIterator(item) {
  var i = 0;
  return {
    next: function() {
      var done = i >= item.length;
      var value = !done ? item[i++] : undefined;
      return {
        done: done,
        value: value
      };
    }
  };
}

var itera = createIterator([1, 2, 3]);
itera.next(); // {value: 1, done: false}
itera.next(); // {value: 2, done: false}
itera.next(); // {value: 3, done: false}
itera.next(); // {value: undefined, done: true}

除了迭代器之外,我们还需要一个可以遍历迭代器对象的方式,ES6 提供了 for of 语句,我们无法直接用 for of 遍历对象,需要部署了 Iterator 接口“可遍历的”(iterable)对象,for of 遍历的其实是对象的 Symbol.iterator 属性。如:

var o = {
  value: 1
};

for (value of o) {
  console.log(value); // Uncaught TypeError: o is not iterable
}

// 给该对象添加 Symbol.iterator 属性
o[Symbol.iterator] = function() {
  return createIterator([1, 2, 3]);
};

for (value of o) {
  console.log(value);
}
// 1
// 2
// 3

所以,优化下 createIterator:

function createIterator(items) {
  function addIterator(items) {
    let i = 0;
    let done = false;
    return {
      next() {
        done = i >= items.length;
        return {
          value: items[i++],
          done
        };
      }
    };
  }
  let iterator = addIterator(items);
  iterator[Symbol.iterator] = () => addIterator(items);
  return iterator;
}

一些数据结构默认部署了 Symbol.iterator 属性:

  1. 数组
  2. Set
  3. Map
  4. 类数组对象,如 arguments 对象、DOM NodeList 对象
  5. Generator 对象
  6. 字符串

模拟实现 for of:

function forOf(obj, cb) {
  let iterable, result;

  if (typeof obj[Symbol.iterator] !== "function")
    throw new TypeError(result + " is not iterable");
  if (typeof cb !== "function") throw new TypeError("cb must be callable");

  iterable = obj[Symbol.iterator]();

  result = iterable.next();
  while (!result.done) {
    cb(result.value);
    result = iterable.next();
  }
}

ES6 为数组、Map、Set 集合内建了以下三种迭代器

  • entries() 返回一个遍历器对象,用来遍历[键名, 键值]组成的数组。对于数组,键名就是索引值。
  • keys() 返回一个遍历器对象,用来遍历所有的键名。
  • values() 返回一个遍历器对象,用来遍历所有的键值。

Map 类型与数组类似,Set 类型的 keys() 和 values() 返回的是相同的迭代器,这也意味着在 Set 这种数据结构中键名与键值相同。

const values = new Set([1, 2, 3]);
const valuess = new Map([
  ["key1", "value1"],
  ["key2", "value2"]
]);

for (let value of values) {
  console.log(value);
}
// 1
// 2
// 3

for (let [key, value] of valuess) {
  console.log(key + ":" + value);
}
// key1:value1
// key2:value2

原文链接:ES6 系列之迭代器与 for of

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant