how does destructuring array get length property

2020-02-08 20:57发布

问题:

I came across this destructuring expression in an article.

const words = ['oops', 'gasp', 'shout', 'sun'];
let { length } = words;
console.log(length); // 4

How does length get the value of 4? I know .length is a property of the array, but how does this syntax work? It seems to be doing let length = words.length; and in fact in babel does output it as such. But my question is what is the logic behind it? What is confusing me is the mix of an array of values and the the use of {length}.

I have read MDN 's description but can't see this example explained.

回答1:

Think of the code as being

const words = {0:'oops', 1:'gasp', 2:'shout', 3:'sun', length:4};
let { length } = words;
console.log(length);

Which it essentially is (nevermind all the other stuff arrays come with)

Does it make sense now?



回答2:

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;

BONUS: Cool Usage w/ Arrow Functions (MDN)

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):



回答3:

If you add a property inside the { and } that belongs to the Array, it's value is copied.
Here we check for the property constructor. Will log constructor function to console.

IF you add a property not belongs to an array, will return undefined

Another Example

const words = ['oops', 'gasp', 'shout', 'sun'];
let { constructor } = words;
console.log(constructor); 

We are testing for something will return undefined

const words = ['oops', 'gasp', 'shout', 'sun'];
let { something } = words;
console.log(something);