ES6中如何创建带有.next()迭代方法的Frame类以实现偏移量递增
The problem with your getter approach is that every call to Test.next uses the original instance's initial offset values—there's no state being tracked between calls. Each time you access the getter, it creates a new Frame based on the original offset_y (100) plus height (20), resulting in the same 120 value every time.
Let's look at three practical solutions depending on your use case:
1. Chainable next() Method (Non-Mutating)
This approach creates a new Frame instance each time, using the current instance's values. To accumulate offsets, you chain calls to next():
class Frame { constructor({ height, width, offset_x, offset_y }) { this.params = { height, width }; this.offset = { x: offset_x, y: offset_y }; } next() { return new Frame({ height: this.params.height, width: this.params.width, offset_x: this.offset.x + this.params.width, // Add width to current x offset_y: this.offset.y + this.params.height // Add height to current y }); } } // Usage const Test = new Frame({ height: 20, width: 10, offset_x: 100, offset_y: 100 }); let currentFrame = Test.next(); console.log(currentFrame.offset); // { x: 110, y: 120 } currentFrame = currentFrame.next(); console.log(currentFrame.offset); // { x: 120, y: 140 } ✔️
The original Test instance remains unchanged, and each next() call builds on the previous Frame's values.
2. Generator Function (Infinite Sequence)
Since you mentioned familiarity with generators, this is a clean way to produce a continuous sequence of frames without mutating the original instance:
class Frame { constructor({ height, width, offset_x, offset_y }) { this.params = { height, width }; this.offset = { x: offset_x, y: offset_y }; } *generateFrames() { let currentX = this.offset.x; let currentY = this.offset.y; const { width, height } = this.params; while (true) { // Yield a new Frame with current offsets yield new Frame({ height, width, offset_x: currentX, offset_y: currentY }); // Update offsets for the next iteration currentX += width; currentY += height; } } } // Usage const Test = new Frame({ height: 20, width: 10, offset_x: 100, offset_y: 100 }); const frameGenerator = Test.generateFrames(); console.log(frameGenerator.next().value.offset); // { x: 100, y: 100 } (initial frame) console.log(frameGenerator.next().value.offset); // { x: 110, y: 120 } console.log(frameGenerator.next().value.offset); // { x: 120, y: 140 } ✔️
You can even iterate over the sequence with a for...of loop (just add a break condition to avoid infinite loops).
3. Mutating next() Method (Update Original Instance)
If you want subsequent calls to next() on the same instance to return the next offset (and don't mind mutating the original), update the instance's offset directly:
class Frame { constructor({ height, width, offset_x, offset_y }) { this.params = { height, width }; this.offset = { x: offset_x, y: offset_y }; } next() { // Update the original instance's offset this.offset.x += this.params.width; this.offset.y += this.params.height; // Return a new Frame with the updated values (or return `this` for the same instance) return new Frame({ height: this.params.height, width: this.params.width, offset_x: this.offset.x, offset_y: this.offset.y }); } } // Usage const Test = new Frame({ height: 20, width: 10, offset_x: 100, offset_y: 100 }); console.log(Test.next().offset); // { x: 110, y: 120 } console.log(Test.next().offset); // { x: 120, y: 140 } ✔️ console.log(Test.offset); // { x: 120, y: 140 } (original instance is updated)
Note: Mutating the original instance can have side effects if other parts of your code rely on its initial values.
内容的提问来源于stack exchange,提问作者alexzedim

