What you’ve shown is equivalent to this (except this goes beyond five elements, but also beyond one in the other direction):
return this.result = Array.from({
  length: Math.floor(this.foo)
}, (_value, index) => ({
  year: index + 1
}));
This assumes that this statement is inside a function (otherwise, return wouldn’t work).
A more reasonable length may be Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo))) which clamps1 the length to at least 0 and at most 232 − 1, the maximum Array length.
If you want to always have at least one element in your array, then use Math.max(1,…) instead.
Returning an assignment (i.e. return this.result =…;) is frowned upon.
The best practice is to separate these statements2:
this.result = Array.from({
  length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo)))
}, (_value, index) => ({
  year: index + 1
}));
return this.result;
Array.from is used with both arguments: the first one is the “array-like” object { length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo))) } which gets converted to a proper Array object.
In this case, an array with a length of Math.floor(this.foo) is initialized (clamped to the range of possible Array lengths).
The second argument maps each value at a certain index to an object with the year property with the value index + 1.
_value isn’t used (it’s undefined anyway).
The advantage to use Array.from(array-like,mapping-function) over e.g. .fill().map(…) is that only a single array is created in memory.
Array(…).fill().map(…) creates two new arrays: the first one at Array(…).fill(), the second one at .map(…).
Therefore, the Array.from approach is more memory-efficient.
1: Maybe soon we’ll finally get a Math.clamp method…
2: Technically, this would be equivalent.
If this.result is a getter / setter, there may be an observable difference.
const result = Array.from({
    length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo)))
  }, (_value, index) => ({
    year: index + 1
  }));
this.result = result;
return result;