Javascript学习---迭代器Iterator

数组内置了一个迭代方法来用于迭代数组的内容,例如for...of就是用到了迭代方法。不单单是Array,像String也同样内置了迭代方法,理论上讲,Javascript为所有对象都提供了迭代机制,对于普通的对象,我们需要手动实现迭代方法。


Symbol.iterator

要使对象可迭代,我们需要实现Symbol.iterator方法。当我们使用for...of时,Javascript会默认去调用对象的Symbol.iterator方法来得到一个迭代对象,然后再调用迭代对象里的next()方法来获得对象(也就是要被迭代的对象,如Array)下一个值。Javascript规定Symbol.iterator方法必须返回一个对象,next()返回的对象格式为{done: Boolean, value: any},其中done=true表示迭代结束,否则value为下一个新值,例子如下:
let range = {
  from: 1,
  to: 5
};

// 1. call to for..of initially calls this
range[Symbol.iterator] = function() {

  // 2. ...it returns the iterator:
  return {
    current: this.from,
    last: this.to,

    // 3. next() is called on each iteration by the for..of loop
    next() {
      // 4. it should return the value as an object {done:.., value :...}
      if (this.current <= this.last) {
        return { done: false, value: this.current++ };
      } else {
        return { done: true };
      }
    }
  };
};

// now it works!
for (let num of range) {
  alert(num); // 1, then 2, 3, 4, 5
}

为了提高代码的可读性,我们可以在Symbol.iterator方法里面返回this来指向被迭代对象本身,再在被迭代对象里添加next()方法,例如:
let range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    this.current = this.from;
    return this;
  },

  next() {
    if (this.current <= this.to) {
      return { done: false, value: this.current++ };
    } else {
      return { done: true };
    }
  }
};

for (let num of range) {
  alert(num); // 1, then 2, 3, 4, 5
}

String也是可迭代的


String也是可迭代的,由于它默认实现了迭代方法,故我们可以直接使用for...of,例如:
for (let char of "test") {
  alert( char ); // t, then e, then s, then t
}

对于特殊字符串也一样,例如:
let str = '??';
for (let char of str) {
    alert( char ); // ?, and then ?
}

显式调用迭代器iterator


通常我们都是使用for...of来隐示调用迭代器,当然我们也可以显示地调用,例如:
let str = "Hello";

// does the same as
// for (let char of str) alert(char);

let iterator = str[Symbol.iterator]();

while (true) {
  let result = iterator.next();
  if (result.done) break;
  alert(result.value); // outputs characters one by one
}

类数组对象

什么是类数组对象呢?类数组对象就是拥有索引号和length的对象,它的格式看起来像数组,可实际上它只是普通的对象,例如:
let arrayLike = { // has indexes and length => array-like
  0: "Hello",
  1: "World",
  length: 2
};

// Error (no Symbol.iterator)
for (let item of arrayLike) {}
类数组对象由于没有实现迭代方法,故不能使用迭代功能

Array.from()

Array.from()可以将一个类数组对象转换为一个数组,其内部原理是新建一个空数组对象,然后将类数组对象的属性一个个复制到空数组对象里,同时实现迭代方法,最后返回该新数组,使用例子如下:
let arrayLike = {
  0: "Hello",
  1: "World",
  length: 2
};

let arr = Array.from(arrayLike); // (*)
alert(arr.pop()); // World (method works)

Array.from()的具体语法如下:
Array.from(obj[, mapFn, thisArg])
其中mapFn是一个可选的函数参数,在把类数组属性复制到新数组对象的过程对该属性进行操作,thisArg用于为mapFn绑定this,例如:
// assuming that range is taken from the example above

// square each number
let arr = Array.from(range, num => num * num);

alert(arr); // 1,4,9,16,25

String也可以通过Array.from()转换数组对象,例如:
let str = '??';

// splits str into array of characters
let chars = Array.from(str);

alert(chars[0]); // ?
alert(chars[1]); // ?
alert(chars.length); // 2

它内部原理其实也就是下面的例子:
let str = '??';

let chars = []; // Array.from internally does the same loop
for (let char of str) {
  chars.push(char);
}

alert(chars);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值