admin管理员组

文章数量:1026989

I'm building my own map method to be as close as the native map method. Since the native map pushes(i think) the changed values into a new array, it still keeps the empty slots. I wasn't able to find a solution to push an empty slot into an array, like this example below.

[1, 2, 3].push(some code) // [1, 2, 3, empty]

I tried pushing an array with one empty item prefixed with a spread operator arr.push(...(new Array(1))) or arr.push(...[,]) but that just pushes undefined.

I solved my problem by not using push and instead assigning values to the array index that way skipped indices will be set to empty.

But I'm writing this post to see if anyone knows that if it's possible to use the push method to push an empty slot to an array.

I'm building my own map method to be as close as the native map method. Since the native map pushes(i think) the changed values into a new array, it still keeps the empty slots. I wasn't able to find a solution to push an empty slot into an array, like this example below.

[1, 2, 3].push(some code) // [1, 2, 3, empty]

I tried pushing an array with one empty item prefixed with a spread operator arr.push(...(new Array(1))) or arr.push(...[,]) but that just pushes undefined.

I solved my problem by not using push and instead assigning values to the array index that way skipped indices will be set to empty.

But I'm writing this post to see if anyone knows that if it's possible to use the push method to push an empty slot to an array.

Share Improve this question edited Jun 19, 2019 at 4:10 Caleb Taylor asked Jun 19, 2019 at 4:04 Caleb TaylorCaleb Taylor 3,2803 gold badges24 silver badges33 bronze badges 2
  • 2 It's not possible to push an empty slot. .push adds an item to the array, while an empty slot is the notion of no item in the array. There is no "nothing" available anywhere in JS - null and undefined are actual things that exist but represent a nothing, aren't actually a nothing. – VLAZ Commented Jun 19, 2019 at 4:06
  • Check out this answer for a detailed look at what is actually going on when there are empty slots in an array -- specifically, there are no keys for the "empty" slots. – Herohtar Commented Jun 19, 2019 at 4:11
Add a ment  | 

3 Answers 3

Reset to default 4

No, it's not possible, not with the push method. empty can only exist if the array has a certain length, but a whole number property of the array does not exist at some index. This is called a sparse array, and cannot be created with push (or other array methods, if they're called on and with non-sparse arrays).

The only way to do so would be to assign to an index for which a lower index doesn't exist yet.

Look at the results for the below two snippets in your browser console, not the snippet console:

const arr = [];
arr[1] = 'a';
console.log(arr);

Or to set the .length of the array above the last index that the array has:

const arr = [];
arr.length = 1;
console.log(arr);

But the two approaches above are very weird to do and probably have no good reason to be used. Better to avoid sparse arrays entirely.

Keep in mind that an empty slot is different from undefined, which is perfectly possible to have as an array value:

const arr = [];
arr.push(undefined);
console.log(arr);

You can create an empty slot in an array by incrementing the array length:

var a = []
a.push(1)
a.length++
a.push(3)
console.log(a)
console.log(1 in a) // anything at index 1?

Alternatively, you can push something and then delete it:

var a = []
a.push(1)
a.push(2)
a.push(3)
delete a[1]
console.log(a)
console.log(1 in a) // anything at index 1?

There is no need to actually push to a new array in your implementation. You can simply do new Array(this.length) where this.length is the array you are mapping through length.

For example consider this map implementation:

if (!Array.prototype.mapIt) {
  Object.defineProperty(Array.prototype, "mapIt", {
    value: function(fn) {
      if (this === null) {
        throw new TypeError('Array.prototype.mapIt called on null or undefined');
      }
      if (typeof fn !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      let _array = this.filter(x => x != null) // remove empty values
      let result = new Array(_array.length) // the new array we will return
      for (var i = 0; i < _array.length; i++) {
        result[i] = fn.call(arguments[1], _array[i], i, _array) // call the predicate
      }
      return result;
    }
  });
}

let arr = [1, 2, , , 3] // the test array

let result = arr.mapIt((c, i, a) =>
  console.log(`current: ${c}`, `index: ${i}`, `array: ${a}`) || c + 2)

console.log('result: ', result)
console.log('original array: ', arr)

Hope this helps you with an gives you an idea about a possible map implementation.

I'm building my own map method to be as close as the native map method. Since the native map pushes(i think) the changed values into a new array, it still keeps the empty slots. I wasn't able to find a solution to push an empty slot into an array, like this example below.

[1, 2, 3].push(some code) // [1, 2, 3, empty]

I tried pushing an array with one empty item prefixed with a spread operator arr.push(...(new Array(1))) or arr.push(...[,]) but that just pushes undefined.

I solved my problem by not using push and instead assigning values to the array index that way skipped indices will be set to empty.

But I'm writing this post to see if anyone knows that if it's possible to use the push method to push an empty slot to an array.

I'm building my own map method to be as close as the native map method. Since the native map pushes(i think) the changed values into a new array, it still keeps the empty slots. I wasn't able to find a solution to push an empty slot into an array, like this example below.

[1, 2, 3].push(some code) // [1, 2, 3, empty]

I tried pushing an array with one empty item prefixed with a spread operator arr.push(...(new Array(1))) or arr.push(...[,]) but that just pushes undefined.

I solved my problem by not using push and instead assigning values to the array index that way skipped indices will be set to empty.

But I'm writing this post to see if anyone knows that if it's possible to use the push method to push an empty slot to an array.

Share Improve this question edited Jun 19, 2019 at 4:10 Caleb Taylor asked Jun 19, 2019 at 4:04 Caleb TaylorCaleb Taylor 3,2803 gold badges24 silver badges33 bronze badges 2
  • 2 It's not possible to push an empty slot. .push adds an item to the array, while an empty slot is the notion of no item in the array. There is no "nothing" available anywhere in JS - null and undefined are actual things that exist but represent a nothing, aren't actually a nothing. – VLAZ Commented Jun 19, 2019 at 4:06
  • Check out this answer for a detailed look at what is actually going on when there are empty slots in an array -- specifically, there are no keys for the "empty" slots. – Herohtar Commented Jun 19, 2019 at 4:11
Add a ment  | 

3 Answers 3

Reset to default 4

No, it's not possible, not with the push method. empty can only exist if the array has a certain length, but a whole number property of the array does not exist at some index. This is called a sparse array, and cannot be created with push (or other array methods, if they're called on and with non-sparse arrays).

The only way to do so would be to assign to an index for which a lower index doesn't exist yet.

Look at the results for the below two snippets in your browser console, not the snippet console:

const arr = [];
arr[1] = 'a';
console.log(arr);

Or to set the .length of the array above the last index that the array has:

const arr = [];
arr.length = 1;
console.log(arr);

But the two approaches above are very weird to do and probably have no good reason to be used. Better to avoid sparse arrays entirely.

Keep in mind that an empty slot is different from undefined, which is perfectly possible to have as an array value:

const arr = [];
arr.push(undefined);
console.log(arr);

You can create an empty slot in an array by incrementing the array length:

var a = []
a.push(1)
a.length++
a.push(3)
console.log(a)
console.log(1 in a) // anything at index 1?

Alternatively, you can push something and then delete it:

var a = []
a.push(1)
a.push(2)
a.push(3)
delete a[1]
console.log(a)
console.log(1 in a) // anything at index 1?

There is no need to actually push to a new array in your implementation. You can simply do new Array(this.length) where this.length is the array you are mapping through length.

For example consider this map implementation:

if (!Array.prototype.mapIt) {
  Object.defineProperty(Array.prototype, "mapIt", {
    value: function(fn) {
      if (this === null) {
        throw new TypeError('Array.prototype.mapIt called on null or undefined');
      }
      if (typeof fn !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      let _array = this.filter(x => x != null) // remove empty values
      let result = new Array(_array.length) // the new array we will return
      for (var i = 0; i < _array.length; i++) {
        result[i] = fn.call(arguments[1], _array[i], i, _array) // call the predicate
      }
      return result;
    }
  });
}

let arr = [1, 2, , , 3] // the test array

let result = arr.mapIt((c, i, a) =>
  console.log(`current: ${c}`, `index: ${i}`, `array: ${a}`) || c + 2)

console.log('result: ', result)
console.log('original array: ', arr)

Hope this helps you with an gives you an idea about a possible map implementation.

本文标签: javascriptPossible to push empty slot to an arrayStack Overflow