简体   繁体   中英

JS Splice Array of Nulls Removes Last Index Regardless of Parameters

For a reason specific to this application an array of data or null s is used to display a list of forms. The difference is based on whether data was provided by a service or manually added, where null indicates everything was manually added via a button not a service.

So ignoring the use case of an array of null s it turns out that [null, null, null].splice(0, 1); removes the null at index 2 instead of 0 based on entering values into the different forms displayed based on the array length, and then seeing who disappears on delete.

It can be made to work by adding something unique like { index: theIndex } to the array instead of null . So splice now works correctly removing the item at index 0 instead of 2, but now I'm curious what splice does under the covers that it can't remove an index regardless of its value compared to the other indices.

Can anyone explain what splice is doing? Based on the spec for splice I don't really see why this happens.

(This follows from the comments in the question but is too large to be a comment).

So I think you are having a conceptual misconception (^^). Look at this examples:

let a = [1, 2, 3]
a.splice(0, 1) // => 1
a // => [2, 3]

let b = [1, 2, 3]
delete b[0] // => true
b // => [<1 empty slot>, 2, 3]

The splice function modifies the array in-place . Note that, although we spliced the first element, we got as a result an array of two elements.

Look now at this example

let a = [1, 1, 1]
a.splice(0, 1)
a // => [1, 1]
let b = [1, 1, 1]
b.splice(2, 1)
b // => [1, 1]

We are deleting the first element from a and the last from b , but of course there's no way of telling so just looking at the result.

In the case with the null s, the same thing is happening. Some library (Angular) is trying to figure out which element you deleted, but there's no way of knowing. This is because null === null .

Now if you use an array of empty objects, for example, there would be a way of knowing . Since {} !== {} ---because each time you cast a {} you are creating a unique object ---, then you could know which element is missing in an array of empty objects. The case is similar with the array [1, 2, 3] .

let a = [{}, {}, {}] // lets imagine that each object has a unique id
                     // and we have [{}#1, {}#2, {}#3]
let [obj1, obj2, obj3] = a
obj1 === obj2 // => false, because they have different ids.

a.splice(0, 1)
a // => [{}#2, {}#3]
a.includes(obj1) // => false, because {}#1 is no longer in a

So an alternative to using an array of null s, would be to use an array of empty objects. I think that is why the code works for you when you use objects like { index: theIndex } . But of course all depends on how smart Angular is. I bet there is a more native way of deleting an element, as @KaiserKatze points out, "it's always a bad idea to directly remove or add elements in the array if it maps to your model."

You have to understand that when you are splicing the array you're only doing that--removing an element from an array. You're not removing the "form element" when splicing the array . Instead, some foreign code is reading the array and trying to figure out --under the hood-- what you intended to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM