JavaScript Object. Use of defineproperty() method

Posted by toodi4 on Sun, 20 Feb 2022 10:25:17 +0100

Object. Use of defineproperty() method

Object. The defineproperty () method will directly define a new property on an object, or modify an existing property of an object and return the object.

Object.defineProperty(obj, prop, descriptor)

  • Parameters:

    • obj: object to define attribute
    • prop: the name or Symbol of the attribute to be defined or modified
    • Descriptor the property descriptor to define or modify
  • Return value: the object passed to the function

Object.defineProperty(object1, 'property1', {
  value: 42
});
console.log(object1.property1); // expected output: 42

There are two main forms of existing descriptors in objects: data descriptors and access descriptors.

A data descriptor is an attribute with a value that can or cannot be written

The properties described by the setter and getter access function descriptors. A descriptor can only be one of the two; Not both

Descriptor:

descriptor configurableenumerablevaluewritablegetset
Default valuefalsefalseundefinedfalseundefinedundefined
effectWhen and only when the configurable key value of the attribute is true, the descriptor of the attribute can be changed, and the attribute can also be deleted from the corresponding object.This attribute appears in the enumeration attribute of the object only if and only if the enumerable key value of this attribute is true.The value corresponding to this attribute. Can be any valid JavaScript value (value, object, function, etc.)If and only if the writable key value of the attribute is true, the value of the attribute, that is, the above value, can be changed by the assignment operator.Property. If there is no getter, it is undefined. This function is called when the property is accessed. No parameters are passed in during execution, but this object will be passed in (due to inheritance, this here is not necessarily the object that defines this attribute). The return value of this function is used as the value of the property.Property. If there is no setter, it is undefined. This function is called when the property value is modified. This method accepts a parameter (that is, the new value assigned) and passes in the this object at the time of assignment.

A descriptor is considered a data descriptor if it does not have any of the keys value, writable, get, and set. If a descriptor has both value or writable and get or set keys, an exception will be generated.

The key value that the descriptor can have

configurableenumerablevaluewritablegetset
Data descriptorsuresuresuresuremay notmay not
Access descriptorsuresuremay notmay notsuresure

Add multiple attributes and defaults

It is important to consider the default property values assigned to the property. Generally, point operators and object When defineproperty() assigns a value to an object's property, the default value of the property in the data descriptor is different, as shown in the following example.

var o = {};

o.a = 1;
// Equivalent to:
Object.defineProperty(o, "a", {
  value: 1,
  writable: true,
  configurable: true,
  enumerable: true
});


// on the other hand,
Object.defineProperty(o, "a", { value : 1 });
// Equivalent to:
Object.defineProperty(o, "a", {
  value: 1,
  writable: false,
  configurable: false,
  enumerable: false
});

Customize Setters and Getters

The following example shows how to implement a self archiving object. When the temperature property is set, the archive array receives log entries.

function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
      // this adds get and set methods to the temperature attribute on the constructor
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]

Inheritance properties

If the property of the visitor is inherited, its get and set methods will be called when the property of the child object is accessed or modified. If these methods use a variable to store a value, the value will be shared by all objects.

function myclass() {
}

var value;
// Add an x attribute to the mycalss prototype
Object.defineProperty(myclass.prototype, "x", {
  get() {
    return value;
  },
  set(x) {
    value = x;
  }
});

var a = new myclass();
var b = new myclass();
//  Both a and b share the x attribute on myclass
a.x = 1;
console.log(b.x); // 1

This can be solved by storing the value in another attribute.

In the get and set methods, this points to an object whose properties are accessed and modified.

function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  //  Change the location of attribute storage through this. Whoever calls this is the one
  get() {
    return this.stored_x;
  },
  set(x) {
    this.stored_x = x;
  }
});

var a = new myclass();
var b = new myclass();
// Call the set method of X on the prototype to add a property stored to its own instance object_ x = 1
a.x = 1;
// Call the get method of X on the prototype to find a property return stored in its own instance object_ x 
console.log(b.x); // undefined
console.log(a.x); // 1

Unlike visitor properties, value properties are always set on the object itself, not a prototype. However, if a non writable property is inherited, it can still prevent modifying the properties of the object.

function myclass() {
}

myclass.prototype.x = 1;
Object.defineProperty(myclass.prototype, "y", {
  writable: false,
  value: 1
});

var a = new myclass();
//  Add an x attribute of 2 to its own instance
a.x = 2;
console.log(a.x); // 2
console.log(myclass.prototype.x); // 1
a.y = 2; // Ignored, throws in strict mode
// Go to the prototype and find it. You don't have it
console.log(a.y); // 1
console.log(myclass.prototype.y); // 1

Topics: Javascript Front-end React Vue.js