JavaScript: Reducing Array elements using the length property

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto
Published in
5 min readJul 30, 2020

--

I know this article title will be surprising to you. That’s why you are here, right? 😀😀

Yes, manipulating Arrays length property value has effects on the elements in the Array. Let’s see how.

Array on EcmaSpec

Looking at the Ecmaspec on Arrays, we can deduce that Array is a number-indexed Object in JS. It has a length property which indicates the number of the number-indexed properties on the Array.

Number-indexed properties mean that the contents of an array are set by the index number as properties to the Array instance

const names  = ["Nnamdi", "Chidume"]

The names is an Array instance with elements “Chidume”, “Nnamdi”. These elements are set by their index number as property to the names instance. So we can refer to the elements by their index number:

names[0] // Nnamdi
names[1] // Chidume

So

const names  = ["Nnamdi", "Chidume"]

can be written like this:

const names = {
0: "Nnamdi",
1: "Chidume"
}

just like an Object. Array is an object but their properties are numbers while Object's properties are set by names.

Arrays have a length property that holds the number of the number-indexed properties on it. So, our names array will have a length property of 2 because names have two elements.

names.length // 2

the length of an array is by one-unit greater than the number-indexed properties in the array.

Now, if we reduce the value of the length property, the elements of the array will be reduced.

For example:

The names array const names =["Nnamdi","Chidume"] has a length of 2. If we set the length to be 1, the contents of the names array will be deleted to the value of the length property set.

const names =["Nnamdi","Chidume"]l(names)names.length = 1l(names)

Output:

[ 'Nnamdi', 'Chidume' ]
[ 'Nnamdi' ]

See after setting the names length property to 1, the "Chidume" element was removed from the names array. See, that JS pops off the elements from the right-hand side until the number of the number-indexed elements equals the value of the length set.

If we set the length to zero:

const names = [ "Nnamdi", "Chidume" ]l(names)names.length = 0l(names)

Output:

[ 'Nnamdi', 'Chidume' ]
[]

We will have an empty array. All the elements in the names array were deleted.

So we see that reducing the Array length makes the JS engine rush to delete the elements in the array so they tally up to the length value.

How about increasing the length value?

Good question, what happens when we increase the length value?

Increasing the length value will make the JS engine add empty items to the array.

const l=console.log
const names =["Nnamdi","Chidume"]
l(names)names.length = 3l(names)

The names array has two elements, and the length is two. See set the length property to be 3 which is more than the length of the array.

Output:

[ 'Nnamdi', 'Chidume' ]
[ 'Nnamdi', 'Chidume', <1 empty item> ]

See, JS added an empty item to the names array so the length will add up to 3.

If we set a length that is n-elements more than the original length, JS will add n-empty items more to the array.

const names =["Nnamdi","Chidume"]l(names)names.length = 5l(names)

See, we set length that is 3-elements more than the original length. JS will add 3 empty items to names array so it will compensate for the new length value.

Output:

[ 'Nnamdi', 'Chidume' ]
[ 'Nnamdi', 'Chidume', <3 empty items> ]

The empty items are undefined.

Lets’ try referencing one:

const names =["Nnamdi","Chidume"]l(names)names.length = 5l(names)l(names[2])

Output:

[ 'Nnamdi', 'Chidume' ]
[ 'Nnamdi', 'Chidume', <3 empty items> ]
undefined

We referenced index 2, we know it will contain an empty item. See, it logged undefined. Empty items are all undefined primitives.

Can non-configurable properties be affected by length value manipulation?

Non-configurable properties are not affected.

Let’s see an example:

const names = ["Nnamdi", "Chidume"]
Object.defineProperty(names, 2, {
value: "David",
writable: false,
configurable: false
})

We added a third element using the Object.defineProperty(...) to the names array because Arrays are indexed by numbers, we used the number 2 as property to add to the names Array. We set the value to "David", and make it non-configurable and non-writable.

Non-configurable and non-writable means that the property cannot be overwritten.

Now, if we reduce the length of the names array:

...l(names)names.length = 2l(names)

We reduced the length to 2. Normally, this should remove the “David” element to compensate for the new length, but because we have a non-configurable element “David”, it will not be removed.

Output:

[ 'Nnamdi', 'Chidume', 'David' ]
[ 'Nnamdi', 'Chidume', 'David' ]

The names array sill remains unchanged.

If we try increasing the length value

...
names.length = 4

It will work normally. Empty items will be added to the names array:

[ 'Nnamdi', 'Chidume', 'David', <1 empty item> ]

If we push new elements:

const names = ["Nnamdi", "Chidume"]
Object.defineProperty(names, 2, {
value: "David",
writable: false,
configurable: false
})
names.push("Philip")

We pushed a new element “Philip”, it will have index 3. names will have length 4.

If we try to reduce the names length property to 2

...
l(names)
names.length = 2l(names)

This should reduce the names array to:

[ 'Nnamdi', 'Chidume', 'David', 'Philip' ]                    |
|
v
[ 'Nnamdi', 'Chidume' ]

But because the index 2 (“David”) is non-configurable, the names reduction will stop at index 2, the "David" will not be removed, only "Philip" will be removed.

Output:

[ 'Nnamdi', 'Chidume', 'David', 'Philip' ]
[ 'Nnamdi', 'Chidume', 'David' ]

Use Cases

One of the most useful uses cases I found out when using the length property, was when I wanted to copy an array to another array.

function copyTo(source, destination) {
for(let i =0: i< source.length;i++) {
destination[i] = source[i]
}
return destination
}

I found out that if the source array has elements more than the destination array I will have some uncopied elements left in the source,

source = [1,2,3,4]
destination = [5,6]
// after copyingdestination = [1,2,3]

and if the source array has elements less than the destination array, I will have unwanted elements still left in the destination array.

destination = [1,2,3,4]
source = [5,6]
// after copying
destination = [5,6,3,4]

I used the length property manipulation to set it right.

I just set the destination to the source array, so JS will either reduce or add more elements for me on the destination,

function copyTo(source, destination) {
destination.length = source.length
for(let i =0: i< source.length;i++) {
destination[i] = source[i]
}
return destination
}

the destination gets trimmed down to the number of elements in the source array. So I set them from the source to the destination without errors. Perfect!!!

Conclusion

JS is awesome and tricky at the same time.

Thanks for stopping by my little corner of the web. I think you’ll love my email newsletter about programming advice, tutoring, tech, programming and software development. Just sign up below:

Follow me on Twitter.

--

--

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto

JS | Blockchain dev | Author of “Understanding JavaScript” and “Array Methods in JavaScript” - https://app.gumroad.com/chidumennamdi 📕