Home  >  Article  >  Web Front-end  >  Detailed explanation of attribute descriptors in ECMAScript 5_Basic knowledge

Detailed explanation of attribute descriptors in ECMAScript 5_Basic knowledge

WBOY
WBOYOriginal
2016-05-16 16:11:521218browse

Property descriptors are a new concept in ES5. Their function is to add more control to the properties of objects.

Object.defineProperty

To study property descriptors, we must first talk about the Object.defineProperty method. The purpose of this method is to define new properties for the object or modify existing properties. Its prototype is as follows:

Copy code The code is as follows:

Object.defineProperty(obj, prop, descriptor)

Usage example:
Copy code The code is as follows:

var obj = { };
Object.defineProperty(obj, 'attr', { value: 1 });

The above piece of code adds an attribute named attr with a value of 1 to the obj object. Equivalent to:
Copy code The code is as follows:

var obj = { };
obj.attr = 1;

In comparison, the writing method of Object.defineProperty seems to be more complicated. However, its biggest secret lies in its third parameter.

Data Descriptor

Suppose we want attr to be a read-only attribute, we can add the writable data descriptor:

Copy code The code is as follows:

var obj = { };
Object.defineProperty(obj, 'attr', {
Value: 1,
writable: false
});
console.log(obj.attr);
obj.attr = 2; // fail
console.log(obj.attr);

By executing the above program, you can find that the value of attr printed twice is 1, which means that the writing of the attribute failed. However, such a result would be a bit puzzling, because the assignment statement failed to execute without exception. Just imagine if such a problem occurs in a large piece of code, it will be difficult to troubleshoot. In fact, just running the code in strict mode will produce an exception:
Copy code The code is as follows:

'use strict'; // Enter strict mode
var obj = { };
Object.defineProperty(obj, 'attr', {
Value: 1,
writable: false
});
obj.attr = 2; // throw exception

Let's take a look at another data descriptor enumerable, which can control whether the property can be enumerated. If you simply define an attribute, this attribute can be enumerated in a for...in loop:
Copy code The code is as follows:

var obj = { };
obj.attr = 1;
for (var i in obj) { console.log(obj[i]); }
enumerable can "hide" it:

var obj = { };
Object.defineProperty(obj, 'attr', {
Value: 1,
enumerable: false
});
for (var i in obj) { console.log(obj[i]); }


When you execute the above code, you will find that the console outputs nothing because the attr attribute cannot be enumerated at this time.

At this point, you may have a question, can the attribute descriptor be modified? For example, can a read-only property be defined as writable again? In fact, this depends on another data descriptor configurable, which controls whether the property descriptor can be changed.

Copy code The code is as follows:

var obj = { };
Object.defineProperty(obj, 'attr', {
Value: 1,
writable: false,
configurable: true
});
Object.defineProperty(obj, 'attr', {
writable: true
});
obj.attr = 2;

The above code first defines attr as a read-only attribute, and then redefines it as writable. So the writing to attr is successful.

Access Descriptor

Access descriptors are similar to get/set accessors in object-oriented.

Copy code The code is as follows:

var obj = { };
Object.defineProperty(obj, 'attr', {
set: function(val) { this._attr = Math.max(0, val); },
Get: function() { return this._attr; }
});
obj.attr = -1;
console.log(obj.attr); // 0

In the above piece of code, access to attr actually becomes access to _attr, and the minimum value is limited to 0 in the set function.

Get attribute descriptor

The above is all about setting attribute descriptors, so how to get the set descriptors? Object.getOwnPropertyDescriptor does the job.

Copy code The code is as follows:

var obj = { };
Object.defineProperty(obj, 'attr', {
Value: 1,
writable: false,
configurable: true
});
var desc = Object.getOwnPropertyDescriptor(obj, 'attr');
console.dir(desc);

Object Control

The Object.defineProperty mentioned earlier operates on the properties of the object, while the three methods mentioned below operate on the object directly.

Object.preventExtensions can prevent objects from having new properties:

Copy code The code is as follows:

var obj = { };
obj.attr = 1;
Object.preventExtensions(obj);
obj.attr2 = 2; //fail

Object.seal can make the object only have attribute values ​​that can be modified (if the attribute is read-only, even the attribute values ​​cannot be modified):
Copy code The code is as follows:

var obj = { };
obj.attr = 1;
Object.seal(obj);
obj.attr = 1.5;
delete obj.attr; // fail

Object.freeze can make the object completely unmodifiable:
Copy code The code is as follows:

var obj = { };
obj.attr = 1;
Object.freeze(obj);
obj.attr = 1.5; // fail
obj.attr2 = 2; //fail

Then you may ask, how do you know whether an object has been preventedExtensions, sealed or frozen? The answer is to call Object.isExtensible, Object.isSealed, and Object.isFrozen respectively. The usage of these three functions is relatively simple and is no longer cumbersome.

In general, objects can be further strictly controlled through attribute descriptors and the rigor of program logic can be strengthened. The only shortcoming is that ES5 is only basically implemented in IE9 (IE9 does not yet support strict mode). Considering that domestic IE8 Although the share is still relatively high, this set of things can currently only be used in mobile browsers and Node.js.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn