SoFunction
Updated on 2025-04-13

Detailed explanation of the complete guide example

() Complete Guide

1. Basic concepts

The () method allows precise addition or modification of an object's properties. By default, properties added using this method are not modifiable.

1.1 Basic syntax

(obj, prop, descriptor)

Parameter description:

  • obj: The object to define the attribute
  • prop: The attribute name to define or modify
  • descriptor: attribute descriptor object

2. Attribute descriptor

2.1 Data descriptor

const obj = {};
(obj, 'name', {
  value: 'John',          // Attribute value  writable: true,         // Is it possible to write  enumerable: true,       // Is it enumerable  configurable: true      // Is it configurable});

2.2 Accessor descriptor

const obj = {
  _name: 'John'
};
(obj, 'name', {
  get() {
    return this._name;
  },
  set(value) {
    this._name = value;
  },
  enumerable: true,
  configurable: true
});

3. Practical application examples

3.1 Data Hijacking (Vue2 Responsive Principle)

function observe(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return;
  }
  (obj).forEach(key => {
    defineReactive(obj, key, obj[key]);
  });
}
function defineReactive(obj, key, val) {
  // Recursively process nested objects  observe(val);
  (obj, key, {
    get() {
      (`Get${key}property`);
      return val;
    },
    set(newVal) {
      if (val === newVal) return;
      (`set up${key}property为${newVal}`);
      val = newVal;
      // Trigger update    }
  });
}
// Use exampleconst data = {
  name: 'John',
  age: 20
};
observe(data);
 = 'Mike'; // Set the name attribute to Mike(); // Getnameproperty Mike

3.2 Private attribute simulation

function Person(name) {
  let _name = name;
  (this, 'name', {
    get() {
      return _name;
    },
    set(value) {
      if (typeof value !== 'string') {
        throw new Error('Name must be a string');
      }
      _name = value;
    }
  });
}
const person = new Person('John');
(); // John
 = 'Mike'; // Normal settings = 123; // Throw an error

3.3 Computational attribute implementation

function computed(obj, key, computeFunc) {
  let value = computeFunc();
  (obj, key, {
    get() {
      return value;
    },
    set() {
      (`${key} is a computed property, cannot be modified`);
    }
  });
}
const obj = {
  a: 1,
  b: 2
};
computed(obj, 'sum', () =>  + );
(); // 3
 = 10; // warn:sum is a computed property, cannot be modified

4. Precautions and limitations

4.1 Unscalable Objects

const obj = {};
(obj);
// This will throw an error(obj, 'name', {
  value: 'John'
});

4.2 Inheritance attributes

const parent = {};
(parent, 'name', {
  value: 'John',
  writable: false
});
const child = (parent);
// This will throw an error = 'Mike';

4.3 Attribute descriptor limitations

const obj = {};
// Cannot specify value/writable and get/set at the same time(obj, 'name', {
  value: 'John',
  get() {
    return 'John';
  }
}); // Throw an error

5. Performance considerations

5.1 Large number of attribute processing

// Not recommendedconst obj = {};
for (let i = 0; i < 1000; i++) {
  (obj, `prop${i}`, {
    value: i,
    writable: true
  });
}
// recommendconst descriptors = {};
for (let i = 0; i < 1000; i++) {
  descriptors[`prop${i}`] = {
    value: i,
    writable: true,
    configurable: true,
    enumerable: true
  };
}
(obj, descriptors);

5.2 Accessor Performance

// Avoid complex calculations in the accessor(obj, 'name', {
  get() {
    // Not recommended    return complexCalculation();
  }
});
// Recommended: cache calculation resultslet cachedValue;
(obj, 'name', {
  get() {
    if (cachedValue === undefined) {
      cachedValue = complexCalculation();
    }
    return cachedValue;
  }
});

6. Best Practices

Descriptor default value

// Remember that the default values ​​are false(obj, 'name', {
  value: 'John'
  // writable: false
  // enumerable: false
  // configurable: false
});

Use TypeScript

interface PropertyDescriptor {
  configurable?: boolean;
  enumerable?: boolean;
  value?: any;
  writable?: boolean;
  get?(): any;
  set?(v: any): void;
}

Error handling

function safeDefineProperty(obj, prop, descriptor) {
  try {
    (obj, prop, descriptor);
    return true;
  } catch (error) {
    (`Failed to define property ${prop}:`, error);
    return false;
  }
}

7. Summary

Key points of ():

Use scenarios

  • Data hijacking
  • Private attribute simulation
  • Computational attribute implementation
  • Attribute access control

Things to note

  • Descriptor type limitation
  • Performance considerations
  • Inheritance relationship processing
  • Error handling

Best Practices

  • Use cache reasonably
  • Avoid complex calculations
  • Note the default value
  • Do a good job of error handling

8. Deep understanding ()

8.1 Detailed explanation of basic concepts

() is a method in JavaScript used to define new properties on objects or modify existing properties. It allows precise control of the properties of properties.

// Basic syntax(obj, prop, descriptor)
// Parameter description// obj: The object to define the attribute// prop: The attribute name to define or modify// descriptor: Attribute descriptor object

8.2 Detailed explanation of attribute descriptors

Attribute descriptors are divided into two types: data descriptors and accessor descriptors.

Complete options for data descriptors:

const obj = {};
(obj, 'name', {
  value: 'John',          // Attribute value  writable: true,         // Is it possible to write  enumerable: true,       // Is it enumerable  configurable: true      // Is it configurable});

Complete options for accessor descriptors:

const obj = {
  _name: 'John'
};
(obj, 'name', {
  get() {
    ('Getting value');
    return this._name;
  },
  set(value) {
    ('Setting value to', value);
    this._name = value;
  },
  enumerable: true,
  configurable: true
});

8.3 Common usage scenarios

Read-only properties:

const obj = {};
(obj, 'readonly', {
  value: 'I am read-only',
  writable: false,
  enumerable: true,
  configurable: false
});
 = 'New value'; // Invalid();  // 'I am read-only'

Non-enumerable attributes:

const obj = {};
(obj, 'hidden', {
  value: 'You cannot see me',
  enumerable: false
});
((obj)); // []
();       // 'You cannot see me'

Calculate properties:

const person = {
  firstName: 'John',
  lastName: 'Doe'
};
(person, 'fullName', {
  get() {
    return `${} ${}`;
  },
  set(value) {
    [, ] = (' ');
  }
});
();    // 'John Doe'
 = 'Jane Smith';
();   // 'Jane'
();    // 'Smith'

Vue two-way binding implementation:

function observe(obj) {
  if (!obj || typeof obj !== 'object') return;
  // Iterate through each property of the object  (obj).forEach(key => {
    let value = obj[key];
    let dep = new Dep(); // Dependency collector    (obj, key, {
      get() {
        // Collect dependencies        if () {
          ();
        }
        return value;
      },
      set(newValue) {
        if (value === newValue) return;
        value = newValue;
        // Notify all dependencies to update        ();
      }
    });
    // Recursive Observer Properties    if (typeof value === 'object') {
      observe(value);
    }
  });
}
// Use exampleconst data = {
  user: {
    name: 'John',
    age: 20
  }
};
observe(data);
// Now data All properties of an object are responsive

8.4 Notes and Best Practices

Descriptor Limitation:

// Cannot use data descriptors and accessor descriptors at the same time(obj, 'prop', {
  value: 123,
  get() { return 123; } // mistake!});

Performance optimization:

// Batch define attributes(obj, {
  prop1: {
    value: 123,
    writable: true
  },
  prop2: {
    get() { return this.prop1 * 2; }
  }
});

Default value processing:

// All descriptor attributes default to false(obj, 'prop', {
  value: 123
  // writable: false
  // enumerable: false
  // configurable: false
});

This is all about this article about the full guide of () and for more related () full guide, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!