JS 中数字原型的自定义迭代器

问题描述 投票:0回答:5

最近我了解了 JS 迭代器,它被用在

for( of )
循环中。由于在 JS 中,即使基元也有原型,我想知道是否可以扩展 Number 原型,以便以下内容成为有效的表达式:

for(let i of 10) console.log(i); //0 1 2 3 4 5 6 7 8 9

显然这仅适用于整数,但是有没有办法实现呢?

希望有,但我无法自己创建这个,因为我对 JS 的这一部分很陌生......

javascript for-loop iterator prototype
5个回答
8
投票

您可以将

Generator
Symbol.iterator
作为
Number
的原型。

Number.prototype[Symbol.iterator] = function* () {
    for (var i = 0; i < this; i++) {
        yield i;
    }
};

console.log([...10]);
.as-console-wrapper { max-height: 100% !important; top: 0; }


5
投票

当然,只需定义

Number.prototype[Symbol.iterator]

Number.prototype[Symbol.iterator] = function() {
  let currentNum = 0;
  return {
    next: () => (
      currentNum == this
      ? { done: true }
      : {
        value: currentNum++,
        done: false
      }
    )
  }
}
for (const i of 10) console.log(i);

但是改变内置对象(如全局

Number
)是非常不好的做法 - 如果可能的话,最好找到另一种方法来完成你想要完成的任何事情。


1
投票

您可以通过定义一个初始值(在本例中为 0)并在yield 循环中递增该值直到该值等于数字来实现此目的:

Number.prototype[Symbol.iterator] = function* () {
  var value = 0;
  //< or <= depending on what you are expecting as the end number
  while(value <= this){
    //yield the value and increment
    yield value++;
  }
};
for (let i of 10) {
  console.log("num", i)
}


0
投票

感谢其他答案,我现在能够创建一个稍微全面的原型扩展,支持负数和验证......

Number.prototype[Symbol.iterator] = function*(){
    if(!Number.isInteger(this.valueOf()))
        throw new TypeError("Only integers can be iterated over.");
    if(this>0)
        for(let i=0;i<this;i++)
            yield i;
    if(this<0)
        for(let i=0;i>this;i--)
            yield i;
    
};

console.log([...5]);
console.log([...-5]);
console.log([...0]);
console.log([...1.5]);


0
投票

另一种方法是使用无槽数组实例的

keys
迭代器:

Number.prototype[Symbol.iterator] = function () {
    const iter = Array(Math.abs(this)).keys();
    return this < 0 ? iter.map(x => -x) : iter;
}

console.log([...5]);
console.log([...-5]);
console.log([...0]);
console.log([...1.5]); // Error: invalid array length

© www.soinside.com 2019 - 2024. All rights reserved.