Reputation: 903
I am using rest parameter to do some operations, but got some properties disappeared in result.
The data format of this.props
looks like this:
```
this.props = {
data: [{...}, ...],
...
}
```
And I tried to rest it in this way:
```
let {showWaveAnimation, ...otherProps} = this.props;
console.log('data' in otherProps); // false
console.log('data' in this.props); //true
```
Why would 'data' property lost after I tried rest operation?
According to MDN, I found the description:
rest parameters are only the ones that haven't been given a separate name (i.e. formally defined in function expression), while the arguments object contains all arguments passed to the function;
What does separate name
here means? Is it means properties that extends from its prototype would not be rest? But after I tried the following statements, I got the same result, I am confusing.
```
class Parent {
constructor() {
this.props = {
data: '123',
};
}
}
class Child extends Parent {
constructor() {
super();
this.props.childProp = 'test';
let {test, ...otherProps} = this.props;
console.log('data' in this.props, 'data' in otherProps);
// true true
}
}
new Child();
```
The former code behaviors abnormal after Babel's transpiling, could it be Babel's plugin problem?
ADD: I found this concept may be more precise in describing my rest
operations. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Rest_in_Object_Destructuring
Upvotes: 2
Views: 1245
Reputation: 903
I figured out why 'data' disappeared in my rest result, it's the enumerable
property of 'data' field!
Once, the property is set as enumerable: false
, we can't get it with the operation of rest in object destructuring.
According to MDN
The Rest/Spread Properties for ECMAScript proposal (stage 3) adds the rest syntax to destructuring. Rest properties collect the remaining own enumerable property keys that are not already picked off by the destructuring pattern.
I think this example can explain my ideas more precisely:
const person = {
name: 'Dave',
surname: 'Bowman'
};
Object.defineProperty(person, 'age', {
enumerable: false, // Make the property non-enumerable
value: 25
});
console.log(person['age']); // => 25
const clone = {
...person
};
console.log(clone); // => { name: 'Dave', surname: 'Bowman' }
Upvotes: 1
Reputation: 202751
rest parameters are only the ones that haven't been given a separate name (i.e. formally defined in function expression), while the arguments object contains all arguments passed to the function;
What does separate name here means? Is it means properties that extends from its prototype would not be rest? But after I tried the following statements, I got the same result, I am confusing.
Given a function definition function foo(a, b, ...c) {}
, arguments a
, and b
are the named parameters, whereas the rest of the passed arguments are spread into the last variable c
. Now, c
is a named variable, but any parameters passed from the third on will just be accessible in c
, i.e. c[0]
.
Now, your console.log error is stemming from your use of the in
operator. You defined an object const foo = {'data': 'bar'}
. 'data' in foo
is true, but 'blarg' in foo
is false since foo doesn't contain a key/property named 'blarg'.
You're actually using the spread operator to destructure your props object into several named variables.
const object = {
data: 'foo',
other: 'bar',
moreData: [1,2,3],
};
// Example usage of the spread operator
const { data, ...allTheRest} = object; // data is destructured, other and moreData into allTheRest
console.log(data);
console.log(allTheRest);
// in operator
console.log('data' in object); // true
console.log('data' in allTheRest); // false
console.log('moreData' in allTheRest); // true
// This is an example of the rest operator
const foo = (...allTheArgs) => {
allTheArgs.forEach(e => console.log(e));
}
foo(1,2,3); // all the args are collected into a single array variable in the function
const bar = (a, b, ...c) => {
console.log(`a: ${a}`);
console.log(`b: ${b}`);
console.log(`c: ${c}`);
};
bar('this is first param', 42, 'foo', 'bar', '1', 2, 'stackoverflow');
Upvotes: 0
Reputation: 40658
The rest parameter allows you to get all the remaining attributes not already selected by identifier preceding it in the assignment.
const obj = {
a: 1,
b: 2,
c: 3
}
const { a, ...rest } = obj;
console.log(a);
console.log(rest);
Above obj
has a property named a
so it is destructured from obj
and assigned to the variable a
, then all other properties are assigned in an object to rest
.
const obj = {
a: 1,
b: 2,
c: 3
}
const { d, ...rest } = obj;
console.log(d);
console.log(rest);
Here obj
doesn't have a property named d
. So it is destructured from obj
as undefined
and assgined to the variable a
. Then all other properties not already assigned, i.e. a
, b
and c
are given to rest
.
In your code otherProps
has the same properties as this.props
, because object this.props
doesn't have a property named test
. In other words, in order to destructure an object you have to know its structure.
Upvotes: 0