1

Having an iterable range of dates

const dateRange = {
    from: new Date(2018, 0, 23),
    to: new Date(2018, 0, 28),
    [Symbol.iterator]() {
        this.current = this.from

        return this
    },
    next() {
        if (this.current <= this.to) {
            this.current.setDate(this.current.getDate() + 1)

            return {done: false, value: this.current}
        }

        return {done: true}
    }
}

And creating a new Array instance from the iterable object

const dateList = Array.from(dateRange)

When console.log(dateList) I get the following output

[ 2018-01-29T06:00:00.000Z,
  2018-01-29T06:00:00.000Z,
  2018-01-29T06:00:00.000Z,
  2018-01-29T06:00:00.000Z,
  2018-01-29T06:00:00.000Z,
  2018-01-29T06:00:00.000Z ]

Iterating using forEach over dateList also give the wrong result

dateList.forEach(date => {
    console.log(date)
})

2018-01-29T06:00:00.000Z
2018-01-29T06:00:00.000Z
2018-01-29T06:00:00.000Z
2018-01-29T06:00:00.000Z
2018-01-29T06:00:00.000Z
2018-01-29T06:00:00.000Z

But iterating on the iterable object give the excepted result

for (let date of dateRange) {
    console.log(date)
}

2018-01-24T06:00:00.000Z
2018-01-25T06:00:00.000Z
2018-01-26T06:00:00.000Z
2018-01-27T06:00:00.000Z
2018-01-28T06:00:00.000Z
2018-01-29T06:00:00.000Z

In order to give context to the question

I am taking the next iterable example from http://javascript.info/iterable is almost the same example. The difference is that in this case it's about numbers

let range = {
  from: 1,
  to: 5
};

range[Symbol.iterator] = function() {
  return {
    current: this.from,
    last: this.to,
    next() {
      if (this.current <= this.last) {
        return { done: false, value: this.current++ };
      } else {
        return { done: true };
      }
    }
  };
};

When console.log this i get the expected result

const numberList = Array.from(range)

console.log(numberList)

[ 1, 2, 3, 4, 5 ]

This makes me suppose that the way in which I increase the date produces this result, if so, what alternative do I have? Thanks again

Could you please explain the reason for the error? Thank you very much.

Mario
  • 4,784
  • 3
  • 34
  • 50
  • 3
    All array members share the same Date object, so they all will display the most recent mutation once it gets to the console. `return {done: false, value: new Date(this.current)}` –  Jan 24 '18 at 15:49
  • 1
    Regarding your updated, there's a big difference between objects and primitives. The primitives are immutable and are are coped on assignment. With an object, it doesn't copy the object itself, but rather just a reference to the object, and the object is mutable. So the reasons remains that you're putting multiple references to *the same object* into the array, so naturally, mutations to one of those references will be seen via all references. –  Jan 24 '18 at 16:45
  • I understand your explanation. Based on this fact. How could I get the expected result? – Mario Jan 24 '18 at 17:01
  • Use the code in my first comment –  Jan 24 '18 at 17:58
  • true, I check it now – Mario Jan 24 '18 at 18:22

1 Answers1

3

You are creating the array indexes by reference and not by value.

That means your array is basically a chain of "pointers" where they're just all equal references to the same object (Thanks to @rock star).

For more information about by reference/value

flx
  • 1,560
  • 13
  • 22
  • 1
    You're right, except that it's odd to say that the last one holds the actual value. Instead they're just all equal references to the same object. –  Jan 24 '18 at 15:58