The introduction

Each object has its own properties that describe the information and characteristics of the object. The attributes of these objects also have their own attributes, that is, attributes of object attributes (or features), which describe the characteristics of an attribute in the object, such as whether an attribute can be enumerated, modified, deleted, and so on.

Note: In the following sections, the properties of an object are referred to as properties and the properties of an object attribute are referred to as characteristics of the attribute for ease of distinction.

1 The type of the attribute

There are two types of attributes:

  1. Data attribute: Holds values. This is the most common type of attribute. For example, the name attribute of the person object is a data attribute:

    let person = {
        name: 'Yuri'
    };
    Copy the code
  2. Accessor property: a function that determines how a property is read or writed. the function name is the name of the property to be read or writed. the function that reads the property is defined by get followed by the property name, and the function that writes the property is defined by set followed by the property name. For example, if the accessor property is named age, the syntax for defining it is:

    /* If the accessor attribute is named age, the syntax is: */
    let person = {
        xxx: 99.// Define the function to read
        get age(){
            // do something;
            return this.xxx;  // XXX will be returned when age is read
        },
    
        // Define the function to write to
        set age(value){
            this.xxx = value;  // Actually set the property value of XXX to value}}Copy the code

    In fact, get and set are free to handle external read and write requests. We can return a true value or give a false value to the external.

These two types of attributes are defined differently, but are accessed the same way. They can both be accessed through periods or brackets, for example:

// Read the name value
console.log(person.name);  // Yuri
// Write the name value
person.name = 'new name';
console.log('The value of the modified name property is' + person.name);  // The modified name attribute value is new name

// Read the age value
console.log(person.age);  / / 99
// Write the age value
person.age = 1;
console.log('The modified age property value is' + person.age); // The age property is 1
Copy the code

1.1 The relationship between the two attributes

Although both properties can set and read the values stored in them, they have different effects.

If all you need to do is save and read data, you can do it with data attributes; you don’t need to use accessor attributes. But if you need to change the default behavior of reading or writing, you should define the property as an accessor property in the manner of an accessor, and then do whatever you want.

When defining accessor properties, you don’t have to define both set and GET. When only GET is defined, the property becomes read-only and cannot be written; If only set is defined, the property can only be written, not read.

The accessor property has a higher priority. When an attribute name is defined by both a data attribute and an accessor attribute, the accessor attribute takes effect and the data attribute is ignored:

let person = {
    name: 'Yuri'.// Set name to the data property
    xxx: 99,

    get name(){ // Set name to the accessor property
        // do something;
        return this.xxx;
    },

    // Define the function to write to
    set name(value){ // Set name to the accessor property
        this.xxx = 'This is the value set via the accessor property:'+ value; }}// Read the name value
console.log(person.name);  / / 99
// Write the name value
person.name = 'new name';
console.log(person.name);  // This is the value set through the accessor property: new name
Copy the code

2 Attributes of attributes (features)

As mentioned in the introduction, the attribute of an object not only has value, but also features that describe the attribute, such as readability and configurability. These features are stored by an object, which is called the description object of the attribute. All attributes have a description object to describe their features.

The property’s description object is generated when the property is created, and JavaScript automatically creates it and assigns it a default value. Of course, it is also possible to manually specify the characteristics of an attribute when it is created, as discussed in Section 2.2.

The two attributes mentioned above (data attribute and accessor attribute) have two common characteristics, but due to different functions and characteristics, they also have their own unique characteristics, which will be discussed separately below.

We can modify these attributes manually. For example, if a property is set to non-enumerable, neither for in nor object.keys () will get the property.

The way to change the characteristics of a property is object.defineProperty (obj, propertyName, Descriptor); , the parameters are defined as follows:

  1. obj: The object of the property
  2. propertyName: The name of the property, which is a string
  3. descriper: The object that describes the characteristics of a property, which can be modified by modifying this object

The above object.defineProperty () function can only change the characteristics of one attribute at a time. If you want to change the characteristics of multiple attributes at once, you need to use object.defineProperties (obj, descriptor). The first parameter is also the object of the property to be modified. The second parameter is also a feature description object, but in this object, the characteristics of multiple properties can be modified at the same time.

The following sections will use the two methods mentioned above to change the characteristics of attributes. By reading the following sections, you can learn both the meaning of each attribute and the use of the two functions.

2.1 General characteristics

The so-called general characteristics are the characteristics of both the data attribute and the accessor attribute. There are two such characteristics:

  1. Enumerable: This attribute describes whether a property is enumerable or not. It takes a Boolean if it is true, it can be enumerable, otherwise it cannot. Non-enumerable properties cannot be obtained by the for in method or the object.keys () method. Each of our self-defined Enumerable properties defaults to True, which means they are enumerable.

    let obj = {
        name: 'Yuri'
    };
    // The default name attribute is enumerable. You can get the name attribute from the object. keys method
    console.log(Object.keys(obj));  // ["name"]
    
    Object.defineProperty(obj, 'name', {
        enumerable: false  // Set to not enumerable
    });
    
    // The name attribute is not included in the result of object. keys
    console.log(Object.keys(obj));  // [] Empty array
    Copy the code
  2. Signals: specifies whether this property can be configured, and carries a Boolean value. Configurable means that the descriptor of the property describes whether the object can be modified, and also determines whether the property can be deleted. The default value of each property is true, which allows you to modify and delete any additional information.

    First try to delete an object property by default:

    let obj = {
        name: 'Yuri'
    };
    
    // Attempted to remove the name attribute, successfully
    console.log(obj.name);  // Yuri
    delete obj.name;
    console.log(obj.name);  // undefined, obj has no name attribute
    Copy the code

    By default, any property we add to the object can be deleted, because the property is configured with a different value of true.

    The deletion operation fails if the 64x property is set to false.

    Object.defineProperty(obj, 'name', {
        configurable: false  // Set it to unconfigurable
    });
    
    delete obj.name;
    console.log(obj.name);  // Yuri, obj object still has the name attribute
    Copy the code

2.2 Unique features of data attributes

Data attributes have two characteristics that accessor attributes do not:

  1. Writable: defines whether the value of a property can be modified. The Boolean value can be modified if it is true. Otherwise, it cannot be modified. The default value is true.

    let obj = {
        name: 'Yuri'
    };
    
    console.log(obj.name);  // Yuri
    obj.name = 'Yuri`s Revenge';
    console.log(obj.name);  // Yuri's Revenge succeeds because writable defaults to true
    
    Object.defineProperty(obj, 'name', { 
        writable: false  // Disable the modification
    });
    obj.name = 'Red alert';
    console.log(obj.name);  // Yuri's Revenge fails to change the original value
    Copy the code
  2. Value: It holds the value of the property. When we want to retrieve the value of the property, we actually retrieve the value that the value holds. For example, when we use obj.name to get the value of the name attribute, we get the value of value:

let obj = {
    name: 'Yuri'
};

console.log(obj.name);  // Yuri

Object.defineProperty(obj, 'name', {
    value: 'This is the value modified by the value feature'
});

console.log(obj.name);  // This is the value modified by the value feature
Copy the code

It is even possible to create and assign a value to an object that does not already exist by assigning the value of the attribute:

// Create an object with no age attribute
let obj = {
    name: 'Yuri'
};

console.log(obj.age);  // undefined, undefined because there is no age attribute

// Use object.defineProperty to set the age property value for the Object
Object.defineProperty(obj, 'age', { 
    value: 99
});

console.log(obj.age);  // 99 has the age attribute successfully assigned
Copy the code

In fact, the code above performs the following steps: see if the object has an age attribute, create one, and assign value to it.

* * * note: * * *, when using this method to create objects, remember can’t set the value attribute, but also explicitly set the other three attributes (enumerable, configurable, writable) value, otherwise the three characteristics of the value will be set to false by default, namely do not traverse, configuration, do not write. This is different from other ways of creating properties.

2.3 Unique characteristics of accessor attributes

Accessor properties also have two unique features. Because accessor properties do not need to store values, they do not have writable and value features. Their unique features are: GET and set features.

This seems to duplicate the accessor properties discussed in Section 1, because accessor properties are also data access methods defined in terms of GET and set. The difference is that accessor properties can only be defined at object creation time, whereas get and set features can be used to change properties at any time, eliminating the need to create a new object.

For example, changing the get and set characteristics of an accessor property that has been defined:

let person = {
    _age: 99,

    get age(){
        return this._age;
    },

    set age(value){
        this._age = value; }};Object.defineProperty(person, 'age', { 
    get(){  Get age(){get age(){get age(){... }
        return this._age * 2;
    },
    set(value){  Set age(){... set age(){... }
        this._age = 0;  // Whatever value the outside world wants to set name to, ignore it}});console.log(person.age);  // 198 is 99 * 2
person.age = 18;
console.log(person.age);  / / 0
Copy the code

Note: When only GET is set, this property is read-only; When only set is set, this property is write-only.

2.4 Use Object.defineProperties() to set the characteristics of multiple attributes at once

The Object. DefineProperties (Object, descriptors) method focuses on the definition of the characteristic descriptors. In the second parameter Descriptors you can define individual descriptors for multiple attributes. Otherwise, the effect is the same as object.defineProperty. Examples are as follows:

let game = {
    name: 'Yuri`s Revenge'
};

console.log(game.name);  // Yuri`s Revenge

Object.defineProperties(game, {
    name: {  // Modify the feature description object for the name attribute
        value: 'Red Alert'.configurable: false.writable: false
    },
    
    creater: {  // Create a new property and provide only the get method, then the creater property is read-only
        get(){
            return 'West Wood'
        },
        configurable: false.enumerable: true}});console.log(game.name);  // Red Alert
game.name = 'Command & Conquer';
console.log(game.name);  // Red Alert

console.log(game.creater); // West Wood
game.creater = 'EA';
console.log(game.creater); // West Wood
Copy the code

3 Obtain the feature description object of the attribute

If you want to know what the characteristics of a property are now, you can call object.defineproperties (Object, propertyName), where the first argument Object is the Object of the property and the second argument propertyName is the propertyName. The return result is the attribute description object for this property. For example, get the name and creater properties of the game object from the previous example:

console.log(Object.getOwnPropertyDescriptor(game, 'name'));
// {value: "Red Alert", writable: false, enumerable: true, configurable: false}

console.log(Object.getOwnPropertyDescriptor(game, 'creater'));
// {get: ƒ, set: undefined, Enumerable: true, different: false}
// Get: f = function
Copy the code

conclusion

Objects have two types of properties: data properties and accessor properties.

In addition to attribute values, object attributes also have their own characteristics, such as traversability and configurability.

Data attributes and accessor attributes both have four characteristics, and in addition to two common characteristics, each has two unique characteristics of its own. It can be summed up in a picture:! [](D: NOTES IN GIT\blogs\ attribute.png)