() 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!