JavaScript: Reducing Array elements using the length property
--
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.
Check out this new API tool:
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.