Definition or function:

The efineProperty() method directly defines a new property on an object, or modifies an existing property of an object, and returns the object. This method allows you to add or modify attributes of an object precisely.

Usage:

Object.defineProperty(obj, prop, descriptor)

  • Obj: The object (also the return value) to which the attribute is to be defined
  • Prop: Property name /Symbol to define or modify
  • Descriptor: Property descriptor to define or modify
  • Definition/Modification:
let obj = {}
console.log(obj.a); // undefined
Object.defineProperty(obj,'a', {value:1
})
console.log(obj.a); / / 1
Copy the code
  • Return this object:
let obj = {}
let newObj = Object.defineProperty(obj,'a', {value:1
})
console.log(obj === newObj); // true
Copy the code

describe

This method allows you to add or modify attributes of an object precisely. Common attributes added by assignment operations are enumerable, and when enumerating object properties are enumerated to for… The in/object. keys method can change the values of these properties or delete them. This method allows you to modify the default additional options/configurations. By default, attribute values added using Object.defineProperty() cannot be modified.

  • Enumeration difference
let obj = {}
obj.a = 'test'
/ / a output
for(let k in obj){
  console.log('normal');
  console.log(k);
}
// A non-empty array
let objKeys = Object.keys(obj) // ['a']
console.log(objKeys);

let objSp = {}
Object.defineProperty(obj,'a', {value:1
}) 
// No output
for(let k in objSp){
  console.log('Object.defineProperty'); 
  console.log(k);
}
// Outputs an empty array
let objSpKeys = Object.keys(objSp) / / []
console.log(objSpKeys);
Copy the code
  • Extension of enumeration
let obj = {}

Object.prototype.b = '2'

Object.defineProperty(obj,'a', {value:1
})
// Iterates not only over its own, but also over the attributes of the prototype
for(let k in obj){
  console.log(k); // b
}
// Only iterate over attributes that can be enumerated by themselves
console.log(Object.keys(obj));
// Iterate over its attributes regardless of whether they can be enumerated
console.log(Object.getOwnPropertyNames(obj));
Copy the code
  • Change/Delete
// Can be modified and deleted
let obj = {}
obj.a = '1'
console.log(obj); // {a:"1"}
obj.a = '2'
console.log(obj); // {a:"2"}
delete obj.a
console.log(obj); / / {}

// Cannot be modified or deleted
let objSp = {}
Object.defineProperty(objSp,'a', {value:'1'
})
console.log(objSp); // {a:"1"}
objSp.a = '2'
console.log(objSp); // {a:"1"}
delete objSp.a
console.log(objSp); // {a:"1"}
Copy the code

Descriptor objects have two main forms of property descriptors: data descriptors and access descriptors. Data descriptors are properties that have values. A storage descriptor is a property described by getter and setter functions. A descriptor can only be one or the other, not both.

They share the following optional key values:

  • configurable: Only when the value is true, 1. The descriptor of the attribute can be changed, and 2. False by default.
// configurable
let objSp = {}
Object.defineProperty(objSp,'a', {configurable:true.value:"2"
})
console.log(objSp);
// Delete attributes
delete objSp.a
console.log(objSp); / / {}
// Change the descriptor
Object.defineProperty(objSp,'a', {configurable:true.value:"3"
})
console.log(objSp); // {a:"3"}

let objSpSecond = {}
Object.defineProperty(objSpSecond,'a', {configurable:false.value:"2"
})
console.log(objSpSecond);
// Delete attributes
delete objSp.a
console.log(objSpSecond); // {a:"2"}
// Change the descriptor
Object.defineProperty(objSpSecond,'a', {configurable:false.value:"3"
})
console.log(objSpSecond); / / an error
Copy the code
  • enumerable: can be enumerated only if it is true. False by default.
// enumerable
let objSp = {}
Object.defineProperty(objSp,'a', {enumerable:true.value:"2"
})
/ / a output
for(let k in objSp){
  console.log(k);
}
// A non-empty array
let objSpKeys = Object.keys(objSp) // ['a']
console.log(objSpKeys);
Copy the code
Data descriptor:
  • valueYou can try any valid JS value (numeric, object, function, etc.). The default is undefined.
let objSp = {}
Object.defineProperty(objSp,'a', {value:"2"
})
console.log(objSp); // {a:"2"}
Copy the code
  • writable: When true, value can be modified by the copy operator, that is, the value of an attribute can be modified. False by default.
let objSp = {}
Object.defineProperty(objSp,'a', {value:"2".writable:true
})
console.log(objSp); // {a:"2"}
objSp.a = '3'
console.log(objSp); // {a:"3"}
Copy the code
  • getThis function is called when the: property is accessed, and is executed without passing any arguments, passing this object. The return value is undefined by default.
  • setThis function is executed when the property is modified, taking an argument (the new value being assigned) and passing this object. The return value is undefined by default.
let objSp = {}
let value = null
Object.defineProperty(objSp,'a', {get(){
    console.log('Check the value of A');
    return value
  },
  set(newVal){
    console.log('Change the value of A');
    value = newVal
  }
})
console.log(objSp.a); // Check the value of a
objSp.a = 2 
console.log(objSp.a);
Copy the code

Has the Boolean value key: configurable, enumerable, writable default value is false

The default values of attribute values and function keys: value,get, and set fields are undefined

Note: Descriptors cannot have both value/writable and GET /set keys, otherwise an error will be reported. If you have a get or a set, you can’t have a value or a writable, and vice versa.

Front knowledge

  • return
ififThere is areturnIf so, it will not be executed againifIt's the back function out therefunction setDataProp(data,dataDefine){
  // console.log(data,dataDefine);
  // Judge the incoming data
  if(typeofdata ! = ='object' || data === null) {console.log('test');
    throw TypeError('we need object or array')}// Because if there is a return inside it, it will not go to the following code!
  if(!Array.isArray(data)){
    return strictData(data,dataDefine)
  }
  // The first return is a function, the second is a map
  return data.map((obj) = >{
    return strictData(obj,dataDefine)
  })
}
Copy the code

Application of the method

Requirement: To accurately control the attributes of the data by preprocessing the attributes of the data, and also to provide a way to modify the descriptor.

Data returned:

{name: "ZXX ", age: 21, job:" front-end engineer ", key: 45,}, {name: "PLW ", age: 18, job:" UI Engineer ", key: 46,}, {name: "ZXX ", age: 21, job:" front-end engineer ", key: 45,}, {name: "PLW ", age: 18, job:" UI Engineer ", key: 46,}, {name: "Test ", age: 24, job:" backend engineer ", key: 47,},];Copy the code

Set the property value:

export default {
  name:{
    configurable:true,
    enumerable:true,
    writable:false
  },
  age:{
    configurable:true,
    enumerable:true,
    writable:false
  },
  job:{
    configurable:true,
    enumerable:true,
    writable:true
  },
  key:{
    configurable:true,
    enumerable:false,
    writable:false
  }
}
Copy the code

Index. Js:

; (() = >{
  // handle the function
  let res = setDataProp(data,dataDefine)
})()
Copy the code

Processing functions:

Function setDataProp(data,dataDefine){// If (typeof data! == 'object' || data === null){ console.log('test'); throw TypeError('we need object or array') } if(! IsArray (data)){return strictData(data,dataDefine)} // The first return is return data.map((obj)=>{return strictData(obj,dataDefine) }) } function strictData(obj,dataDefine){ // console.log(obj,dataDefine); let keys = Object.keys(dataDefine) // console.log(keys); // Use the new object here, Let newObj = new CreateNewObj() key.foreach ((key)=>{object.defineProperty (newObj,key,{  value:obj[key], ... dataDefine[key] }) }) return newObj }Copy the code

Constructor:

// Note that the constructor can only be written in another file, because the import will execute the js once. // If written in the original page, the method of mounting the prototype will be executed later. For subsequent business requirements differ / / on mount a prototype method can modify the properties of true/false CreateNewObj. Prototype. SetConfig = function (key, prop, value) { Object.defineproperty (this,key,{[prop]:value})} Using "for in" will iterate over the prototype object, Function CreateNewObj(){let keys = object.keys (createnewobj. prototype) keys.map((key)=>{  Object.defineProperty(CreateNewObj.prototype,key,{ configurable:false, enumerable:false, Writable :false})})}Copy the code