Each object can define a new property and set the property descriptor.

There are six attribute descriptors:

  • Value: Sets the property value. The default value is undefined.
  • Writable: Sets whether the property value is writable. The default value is true.
  • Enumerable: Sets whether a property is enumerable, that is, allowed to iterate through it using either a for/in statement or the object.keys () function. Defaults to true.
  • The default value is true. The video works without any additional control system. If false, the property cannot be deleted, the value of the property cannot be modified, nor the property descriptor of the property can be modified.
  • Get: Specifies the value function. The default value is undefined.
  • Set: Storage function, default is undefined.

Enumerable is the enumerable property descriptor.

Set enumerability:

The object.defineProperty () method directly defines a new property on an Object, or modifies an existing property of an Object, and returns the Object.

Parameters:

  • obj

    The object for which attributes are to be defined.

  • prop

    The name or Symbol of the property to be defined or modified.

  • descriptor

    The property descriptor to define or modify.

Return value: The object passed to the function.

The method’s property descriptor enumerable sets whether the property is enumerable or not. When it is set to false, it is not enumerable. Otherwise, it can be enumerated. As follows:

 Object.defineProperty(object1, 'property1', {
     enumerable: false,
     value: 'not enumerable'
});
Copy the code

The attribute structure is as follows:

Retrievability:

Each property of an object has a Descriptor that controls the behavior of the property. The description of the Object. GetOwnPropertyDescriptor method can obtain the attribute Object.

Parameters:

  • obj

    The target object to be searched

  • prop

    The name of the property in the target object

Return value: Returns the property descriptor if the specified property exists on the object, otherwise undefined is returned.

This method allows a description of an attribute to be retrieved as follows:

Object.getOwnPropertyDescriptor(object1, 'property1')
Copy the code

The attribute structure is as follows:

An enumerable property that describes an object is called “enumerable.” If it is false, it means that some operations ignore the current property.

Currently, there are four operations that ignore enumerable as false.

  • for... inLoop: Only the enumerable properties of the object itself and its inheritance are iterated over.
  • Object.keys(): returns the key names of all the enumerable properties of the object itself.
  • JSON.stringify(): Serializes only enumerable properties of the object itself.
  • Object.assign(): ignoreenumerableforfalseOnly enumerable properties of the object itself are copied.

Of the four operations, the first three are available in ES5, and the last object.assign () is new in ES6. Among them, only… In returns the inherited properties, and the other three methods ignore the inherited properties and process only the properties of the object itself.

In fact, the original purpose of enumerable was to make it possible for certain properties to bypass for… In operation, otherwise all internal properties and methods will be traversed. For example, the toString method of an object prototype and the length property of an array are “enumerable” to avoid being used for… Go through to.

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false
​
Object.getOwnPropertyDescriptor([], 'length').enumerable
// false
Copy the code

In the code above, both toString and Length are Enumerable false, so for… In does not iterate over these two attributes inherited from the stereotype.

In addition, ES6 states that all Class stereotype methods are non-enumerable.

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable
// false
Copy the code

In general, the introduction of inherited properties into operations can complicate matters, and most of the time, we only care about the properties of the object itself. So, try not to use for… In loop and use object.keys () instead.

Object.assign :

Without further discussion, enumerability was introduced just to introduce today’s highlight — Object.assign()

The object.assign () method is used to merge objects. It copies all the enumerable properties of the source Object to the target Object.

Parameters:

  • target

    Target object.

  • sources

    The source object.

Return value: target object.

The object.assign () method takes the first argument to the target Object and the rest to the source Object.

Note: If the target object has a property of the same name as the source object, or multiple source objects have a property of the same name, the later property overrides the previous property.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
​
const returnedTarget = Object.assign(target, source);
​
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
​
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
Copy the code

Object.assign() is a deep copy or a shallow copy?

Object.assign() copies property values. If the attribute value of the source object is a reference to an object, then it only refers to that reference. That is, if the attribute value of the Object is a simple type (e.g. String, number), assign({},srcObj); The resulting new object is a deep copy; If the attribute value is an object or some other reference type, it is actually shallow-copied for that object.

  • If I have only one parameter,Object.assign()This parameter is returned directly.
const obj = {a: 1};
Object.assign(obj) === obj // true
Copy the code
  • If the parameter is not an object, it is converted to an object and then returned.
typeof Object.assign(2) // "object"
Copy the code
  • Due to theundefinedandnullCannot be converted to objects, so if they are arguments, an error is reported.
Object.assign(undefined) // An error was reported object. assign(null) // An error was reportedCopy the code
  • If non-object arguments occur at the location of the source object (that is, non-first arguments), the rules are different. First, these parameters are converted to objects, and if they cannot, they are skipped.

This means that if undefined and null are not the first arguments, no error is reported.

let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
Copy the code
  • Other types of values (that is, values, strings, and booleans) do not take the first argument and will not report an error. However, none of the values have any effect except that the string is copied into the target object as an array.
const v1 = 'abc';
const v2 = true;
const v3 = 10;
​
const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
Copy the code

V1, v2, v3 are string, Boolean, and number, respectively. The result is that only the string is merged into the target object (in the form of a character array), and both the value and the Boolean are ignored. This is because only string wrapped objects produce enumerable properties.

Object(true) // {[[PrimitiveValue]]: true}
Object(10)  //  {[[PrimitiveValue]]: 10}
Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
Copy the code

[PrimitiveValue]], which cannot be copied by Object.assign(). Only the string wrapper object produces enumerable real sense properties, and those properties are copied.

Object.assign() copies only the source Object’s own properties (no inherited properties), and no non-enumerable properties (Enumerable: false).

Object.assign({b: 'c'},
  Object.defineProperty({}, 'invisible', {
    enumerable: false,
    value: 'hello'
  })
)
// { b: 'c' }
Copy the code

In the above code, the Object to be copied by object.assign () has only one non-enumerable attribute invisible, which is not copied.

The attribute named Symbol is also copied by object.assign ().

Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
// { a: 'b', Symbol(c): 'd' }
Copy the code

Practical application: Working with list data – copying the values of inner objects

The obtained object structure is as follows:

Copy the inner layer of the Object params attribute to the outer layer using object.assign () :

getProcessList(params).then(response => { this.processingList = response.rows.map(item => { let itemObj = Object.assign(item, { ... item.customerInfo }); return itemObj || {}; }); });Copy the code

The object structure is as follows:

InputDate is null. This is because the customerInfo Object contains the inputDate field. Using object. assign overwrites the original value.

Modify the code as follows:

getProcessList(params).then(response => { this.processingList = response.rows.map(item => { let inputDate = item.inputDate; let itemObj = Object.assign(item, { ... item.customerInfo, ... item.responseParams }); itemObj.inputDate = inputDate; return itemObj || {}; }); });Copy the code

The modified object structure is as follows: