This is the 6th day of my participation in the August More Text Challenge

Object. DefineProperty syntax

⭐ should be directly in theObjectCall this method on the constructor object, not on any of themObjectType on an instance of the.

Object.defineProperty(obj, prop, descriptor)
Copy the code

parameter

This method takes three arguments

  • Obj: Target object to which attributes are defined or modified.

  • Prop: The name of the property to define or modify.

  • Descriptor: Property descriptor to define or modify.

Object.defineProperty()The three parameters received by the method are mandatory, and an error will be reported if any of them are not passed.propYou can pass an empty string, but it doesn’t seem to make sense.descriptorEmpty objects can be passed {}The default value of the property isundefined.

(() = > {
  // Define objects
  const myObject = {};
  // The third argument can be passed {}, but cannot be ignored
  Object.defineProperty(myObject, 'lastName'{});console.log('🚀 🚀 ~ myObject:', myObject);
  // The second argument can be passed ""
  Object.defineProperty(myObject, ' ', { value: 'hzw' });
  console.log('🚀 🚀 ~ myObject:', myObject); }) ()Copy the code

Object.defineProperty()The first argument received by the method can be an array, and the method adds a property to the array.

(() = > {
  // Define an empty array
  const myObject = [];
  Object.defineProperty(myObject, 'lastName', {
    value: '123'
  });
  console.log('🚀 🚀 ~ myObject:', myObject);
  console.log('🚀 🚀 ~ myObject. LastName:', myObject.lastName); }) ()Copy the code

Object.defineProperty()Method can only operate on objects that already exist. If an object does not exist, an error is reported instead of a new object being created.

(() = > {
  Object.defineProperty(myObject, 'firstName', {
    value: "han"}); }) ()Copy the code

Object.defineProperty()Methods directly define a new property on an object or modify an existing property of an object.

(() = > {
  // Define objects
  const myObject = {
    firstName: "ywly"
  };
  console.log('🚀 🚀 ~ init ~ myObject:', myObject);

  // Modify attributes
  Object.defineProperty(myObject, 'firstName', {
    value: "han"});console.log('🚀 🚀 ~ updataProp ~ myObject:', myObject);

  // Add attributes
  Object.defineProperty(myObject, 'lastName', {
    value: "zhiwei"});console.log('🚀 🚀 ~ addProp ~ myObject:', myObject); }) ()Copy the code

As you can see, I printed the original object, the modified object, and the added object. If the second parameter prop exists, it is an operation to modify the property; if prop does not exist, it is an operation to add the property.

Object.defineProperty()Method modifies the original object, and there is a return value, which is the modified object.

(() = > {
  const myObject = {};
  console.log('🚀 🚀 ~ init ~ myObject:', myObject);
  const result = Object.defineProperty(myObject, 'firstName', {
    value: "han"});console.log('🚀 🚀 ~ defineProperty ~ myObject:', myObject);
  console.log(' '🚀 🚀 ~ the result., result); }) ()Copy the code

You can see that I printed the original Object, the Object processed by Object.defineProperty(), and the return value result from the object.defineProperty () method.

Attribute descriptor

I mentioned earlier that the object.defineProperty () method receives a third parameter called a property descriptor, so what exactly is that?

There are two main forms of property descriptors that currently exist in objects: data descriptors and access descriptors, both of which are objects.

Data descriptor optional key value

value

Property, which can be any valid JavaScript value (numeric, object, function, etc.), and defaults to undefined if not set.

(() = > {
  // Define objects
  const myObject = {};
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'
  });
  Object.defineProperty(myObject, 'lastName'{});console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // han
  console.log('🚀 🚀 ~ myObject. LastName:', myObject.lastName); // undefined}) ()Copy the code

Writable

Writable is a Boolean value that determines whether the value of a target attribute can be changed.

⭐ When writable is set to true, the value of a property can be modified using either the assignment operator or object.defineProperty ().

(() = > {
  // Define objects
  const myObject = {};
  // Set writable to true
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.writable: true
  });
  console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // han
  myObject.firstName = 'wang'
  console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // wang
  Object.defineProperty(myObject, 'firstName', {
    value: 'zhang'});console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // zhang}) ()Copy the code

⭐ When writable is set to false, using the assignment operator to change the value of a property does not generate an error, but does not take effect.

(() = > {
  // Define objects
  const myObject = {};
  // Set writable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.writable: false
  });
  console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // han
  myObject.firstName = 'wang'
  console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // han}) ()Copy the code

⭐ If writable is set to false, using object.defineProperty () to change the value of the property will cause an error.

(() = > {
  // Define objects
  const myObject = {};
  // Set writable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.writable: false
  });
  Object.defineProperty(myObject, 'firstName', {
    value: 'wang'});console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); }) ()Copy the code

Access descriptor optional key value

get

Property that is called when the property is accessed. No arguments are passed, but this object is passed (because of inheritance, this is not necessarily the object that defines the property). The return value of this function is used as the value of the property. Undefined if no getter is defined.

set

Property, which is called when the property value is modified. This method takes an argument (that is, the new value being assigned) and passes in the this object at the time of assignment. Undefined if no setter is defined.

(() = > {
  // Define objects
  const myObject = {};
  Object.defineProperty(myObject, 'firstName', {
    get() {
      console.log('🚀🚀~ read myObject.firstName:');
      return this.value;
    },
    set(newValue) {
      console.log('🚀🚀~ modified myObject.firstName:');
      this.value = newValue; }}); myObject.firstName ='wang'
  console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); }) ()Copy the code

The Shared key values

The following two are the keys that access descriptors and data descriptors are allowed to have together.

Enumerable Enumerable

Enumerable is a Boolean that states the target attribute in for.. Whether in, Object.keys, and json. stringify are traversable.

⭐ When Enumerable is set to true, the target property can be iterated.

(() = > {
  // Define objects
  const myObject = {
    age: "23".sex: "boy"
  };
  // Set Enumerable to true
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.enumerable: true});for (const key in myObject) {
    console.log('🚀 🚀 ~ for the in', key);
  }
  console.log('🚀 🚀 ~ Object. Keys:'.Object.keys(myObject));
  console.log('🚀 🚀 ~ JSON. Stringify:'.JSON.stringify(myObject)); }) ()Copy the code

⭐ If Enumerable is set to false, the target property cannot be iterated.

(() = > {
  // Define objects
  const myObject = {
    age: "23".sex: "boy"
  };
  // Set Enumerable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.enumerable: false});for (const key in myObject) {
    console.log('🚀 🚀 ~ for the in', key);
  }
  console.log('🚀 🚀 ~ Object. Keys:'.Object.keys(myObject));
  console.log('🚀 🚀 ~ JSON. Stringify:'.JSON.stringify(myObject)); }) ()Copy the code

⭐ for… The in loop includes inherited properties; the object. keys method does not. If you need to get all the attributes of the Object itself, whether can traverse, you can use the Object. The getOwnPropertyNames method.

Configurable, works without any additional control system.

A 64x / 64x is a Boolean value that determines whether the property description object can be modified and whether the property can be deleted through delete.

⭐ If the configured information is false, the delete command cannot delete the freely configured information.

(() = > {
  // Define objects
  const myObject = {};
  // Sets the signals to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: false});// 设置 configurable 为 true
  Object.defineProperty(myObject, 'lastName', {
    value: 'zhiwei'.configurable: true});console.log('🚀🚀 before delete ~ myObject.firstName :', myObject.firstName);
  console.log('🚀🚀 before delete ~ myObject.lastName :', myObject.lastName);
  delete myObject.firstName
  delete myObject.lastName
  console.log('🚀🚀 after delete ~ myObject.firstName :', myObject.firstName);
  console.log('🚀🚀 after delete ~ myObject.lastName :', myObject.lastName); }) ()Copy the code

If the 64x property is set to false, the DELETE property does not send an error, but does not take effect.

If the configured information is true, the DELETE property takes effect and changes to undefined.

⭐ The modification of the value through the assignment operator takes effect only when the 64x and writable are set to true.

(() = > {
  // Define objects
  const myObject = {};
  // Sets the signals to true and writable to false by default
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: true});// Sets the different information to true and writable
  Object.defineProperty(myObject, 'lastName', {
    value: 'zhiwei'.configurable: true.writable: true});console.log('🚀🚀 before change ~ myObject.firstName :', myObject.firstName); //han
  myObject.firstName = 'zhang'
  console.log('🚀🚀 after change ~ myObject.firstName :', myObject.firstName); // Han did not take effect

  console.log('🚀🚀 before change ~ myObject.lastName :', myObject.lastName); //zhiwei
  myObject.lastName = 'san'
  console.log('🚀🚀 after change ~ myObject.lastName :', myObject.lastName); / / SAN effect}) ()Copy the code

⭐ If either 6464x and writable is true, the property value can be modified by using the object.defineProperty () method.

(() = > {
  // Define objects
  const myObject = {};
  // Sets the different information to true and writable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: true.writable: false
  });
  Object.defineProperty(myObject, 'firstName', {
    value: 'wang'});console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // wang}) ()Copy the code
(() = > {
  // Define objects
  const myObject = {};
  // Sets the different information to false and writable to true
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: false.writable: true
  });
  Object.defineProperty(myObject, 'firstName', {
    value: 'wang'});console.log('🚀 🚀 ~ myObject. FirstName:', myObject.firstName); // wang}) ()Copy the code

⭐, enumerable, can not be modified without any additional control system.

(() = > {
  // Define objects
  const myObject = {};
  // Set Enumerable to true
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: false.enumerable: true});// Set Enumerable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'wang'.configurable: false.enumerable: false});console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

⭐ When the 64x is set to false, the writable can be changed from true to false. However, the writable cannot be changed from false to true. Otherwise, an error will be reported.

(() = > {
  // Define objects
  const myObject = {};
  // Set writable to true
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'.configurable: false.writable: true
  });
  // Set writable to false
  Object.defineProperty(myObject, 'firstName', {
    value: 'wang'.configurable: false.writable: false});console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

⭐ With the 64x set to false, the getter and setter methods cannot be modified.

(() = > {
  // Define objects
  const myObject = {};
  Object.defineProperty(myObject, 'firstName', {
    configurable: false.get() {
      console.log('🚀🚀~ read myObject.firstName:');
      return this.value;
    },
    set(newValue) {
      console.log('🚀🚀~ modified myObject.firstName:');
      this.value = newValue; }});Object.defineProperty(myObject, 'firstName', {
    configurable: false.get() {
      console.log('🚀🚀~ read myObject.firstName:');
      return this.value + 'y';
    },
    set(newValue) {
      console.log('🚀🚀~ modified myObject.firstName:');
      this.value = newValue + 'y'; }}); }) ()Copy the code

Descriptor default value

Properties are defined literally

(() = > {
  / / configurable writable enumerable default is true
  const myObject = {
    firstName: "han"
  };
  console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

Attributes are defined as constructors

(() = > {
  / / configurable writable enumerable default is true
  function Obj(firstName) {
    this.firstName = firstName;
  }
  let myObject = new Obj("han");
  console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

Define attributes with new Object()

(() = > {
  const myObject = new Object(a); myObject.firstName ="han";
  console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

Define attributes with Object.defineProperty ()

(() = > {
  const myObject = {};
  / / configurable writable enumerable default is false
  Object.defineProperty(myObject, 'firstName', {
    value: 'han'});console.log(' '🚀 🚀 ~ Descriptor..Object.getOwnPropertyDescriptor(myObject, 'firstName')); }) ()Copy the code

Summary of property descriptors

The key values that the descriptor can have

configurable enumerable value writable get set
Data descriptor Square root Square root Square root Square root X X
Access descriptor Square root Square root X X Square root Square root

⭐ A descriptor can only be one of these two, not both.

⭐ A descriptor is considered a data descriptor if it does not have any of the keys of value, writable, GET, and set.

⭐ An exception is raised if a descriptor has both value or writable and get or set keys.

Implement a simple bidirectional binding

//html
<body>
  <h1>Object.defineProperty</h1>
  <input type="text" id="input" />
  <div id="div"></div>
</body>

//js
(() = > {
  const obj = {};
  const inputVal = document.getElementById("input");
  const div = document.getElementById("div");

  Object.defineProperty(obj, "name", {
    set: function(newVal) { inputVal.value = newVal; div.innerHTML = newVal; }}); inputVal.addEventListener('input'.(e) = >{ obj.name = e.target.value; }); }) ()Copy the code

Other related methods

Object.defineProperties()

Define multiple properties, and the inner loop calls Object.defineProperty.

Object.prototype.propertyIsEnumerable()

The propertyIsEnumerable() method returns a Boolean value indicating whether the specified propertyIsEnumerable.

Object.entries()

The object.entries () method returns an array of key-value pairs for the given Object’s own enumerable properties, arranged in the same order as for… The in loop returns the same order as it iterates through the object (the difference is that for-In also enumerates the properties in the prototype chain).

Object.values()

The object.values () method returns an array of all the enumerable property values of a given Object itself, in the same order as the values used for… The in loop has the same order (the difference is that for-In loops enumerate properties in the stereotype chain).

Object.keys()

The object.keys () method returns an array of a given Object’s own enumerable properties in the same order as the property names would be returned if the Object were iterated through normally.

Object.freeze()

The object.freeze () method freezes an Object. A frozen object can no longer be modified. If you freeze an object, you cannot add new attributes to the object, delete existing attributes, modify the enumerability, configurability, writability of existing attributes of the object, or modify the value of existing attributes.

Object.isFrozen()

The object.isfrozen () method determines whether an Object isFrozen.

Object.getOwnPropertyDescriptors()

Object. GetOwnPropertyDescriptors () method is used to get all the own properties of an Object descriptor.

Object.preventExtensions()

The object.preventExtensions () method makes an Object unextensible, meaning new properties can never be added.

Object.isExtensible()

The object.isextensible () method determines whether an Object isExtensible(whether new properties can be added to it).

Object.isSealed()

The object.issealed () method determines whether an Object isSealed.

Object.seal()

The object.seal () method seals an Object, preventing the addition of new properties and marking all existing properties as unconfigurable. The value of the current property can be changed as long as it was previously writable.

reference

Compatibility 👉👉 Can I use

MDN Object.defineProperty()