Intro
I had the same question so I read the docs and it finally clicked for me that the variable (length
) is just being assigned the Object’s value at the key with the same name as the variable (words[length]
).
That may not make sense, so I’m going to start by explaining this type of destructuring in 2 steps and then show how it applies in this situation.
I’ll then provide one last (cool) example which confused me initially and led me to research this topic. It’s also the exact problem described in a duplicate question.
Destructuring
This syntax is called Object Destructuring (MDN):
let a, b;
({a, b} = {a: 1, b: 2});
a; // 1
b; // 2
({b, a} = {c: 3, b: 2, d: 4, a: 1});
a; // 1
b; // 2
Same result – order doesn't matter!
The variables on the left (a
& b
) are assigned to the value of their corresponding key's value on the Object (right).
const obj = {a: 1, b: 2};
let {a, b} = obj;
a; // 1
b; // 2
We can store the object on the right into a variable (obj
in this case) and then use the same syntax (without parens).
Applied to your Example (Array)
Finally, let's show the words
array as an Object (arrays are just Objects under the hood).
Here's what you'll see if you type ['oops', 'gasp', 'shout', 'sun']
into Chrome's console:
const words = {0: 'oops', 1: 'gasp', 2: 'shout', 3: 'sun', length: 4};
let { length } = words;
console.log(length); // 4
Just like above, it's going to set the length
variable (left) to the value of the corresponding key in the words
Object/array (right). words[length]
has a value of 4
so the length
variable (left) now has a value of 4
as well.
Example Where Destructuring is Useful
From Wes Bos's Blog:
Given a person
Object, how do you create global variables referring to its properties?
const person = {
first: 'Wes',
last: 'Bos',
country: 'Canada',
city: 'Hamilton',
twitter: '@wesbos'
};
Old School:
const first = person.first;
const last = person.last;
The power of destructuring!
const { first, last } = person;
Challenge: return new array with the lengths of the respective elements in the input array.
This example is shown as a way to use arrow functions. All three solutions solve the problem, they’re just showing the evolution to finally arrive at a simple one-liner.
var materials = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
materials.map(function(material) {
return material.length;
}); // [8, 6, 7, 9]
materials.map((material) => {
return material.length;
}); // [8, 6, 7, 9]
materials.map(({length}) => length); // [8, 6, 7, 9]
On each iteration of the input array passed to map
, we are setting the {length}
parameter to the current element of materials
that is passed in as an argument:
{length} = 'Hydrogen';
This sets the length
variable to the length
property of the current string element (more on that below) and then simply returns the value of length
to the map
function which eventually returns a new array with all of the elements from the original array's lengths as its elements.
Supplement: String (primitive) vs. Array (Object)
"strings" are "primitives", not objects, so they don't have properties BUT when you try to call a property such as .length
on a string, the primitive is coerced (changed) into a String Object.
Here's what a String
Object looks like in the Chrome console. Notice how it's practically the same as the Array
Object. String
(function) is a constructor, so calling new
will create a new Object constructed from that function with String
(Object) as its prototype (which is what __proto__
refers to):