JavaScript: The Definitive Guide, Sixth Editio javaScript权威指南(第6版) pdf 文字版-文字版, javascript电子书, 和javascript 有关的电子书:

6.7 Property Attributes

6.7 Property Attributes


In addition to a name and value, properties have attributes that specify whether they can be written, enumerated, and configured. In ECMAScript 3, there is no way to set these attributes: all properties created by ECMAScript 3 programs are writable, enumerable, and configurable, and there is no way to change this. This section explains the ECMAScript 5 API for querying and setting property attributes. This API is particularly important to library authors because:

For the purposes of this section, we are going to consider getter and setter methods of an accessor property to be property attributes. Following this logic, we’ll even say that the value of a data property is an attribute as well. Thus, we can say that a property has a name and four attributes. The four attributes of a data property are value, writable, enumerable, and configurable. Accessor properties don’t have a value attribute or a writable attribute: their writability is determined by the presence or absence of a setter. So the four attributes of an accessor property are get, set, enumerable, and configurable.

The ECMAScript 5 methods for querying and setting the attributes of a property use an object called a property descriptor to represent the set of four attributes. A property descriptor object has properties with the same names as the attributes of the property it describes. Thus, the property descriptor object of a data property has properties named value, writable, enumerable, and configurable. And the descriptor for an accessor property has get and set properties instead of value and writable. The writa ble, enumerable, and configurable properties are boolean values, and the get and set properties are function values, of course.

To obtain the property descriptor for a named property of a specified object, call Object.getOwnPropertyDescriptor(): // Returns {value: 1, writable:true, enumerable:true, configurable:true} Object.getOwnPropertyDescriptor({x:1}, "x");

// Now query the octet property of the random object defined above. // Returns { get: /*func*/, set:undefined, enumerable:true, configurable:true} Object.getOwnPropertyDescriptor(random, "octet");

// Returns undefined for inherited properties and properties that don't exist. Object.getOwnPropertyDescriptor({}, "x"); // undefined, no such prop Object.getOwnPropertyDescriptor({}, "toString"); // undefined, inherited

As its name implies, Object.getOwnPropertyDescriptor() works only for own properties. To query the attributes of inherited properties, you must explicitly traverse the prototype chain (see Object.getPrototypeOf() in §6.8.1 ).

6.7 Property Attributes | 131

To set the attributes of a property, or to create a new property with the specified attributes, call Object.defineProperty(), passing the object to be modified, the name of the property to be created or altered, and the property descriptor object:

var o = {}; // Start with no properties at all // Add a nonenumerable data property x with value 1. Object.defineProperty(o, "x", { value : 1,

writable: true, enumerable: false, configurable: true});

// Check that the property is there but is nonenumerable o.x; // => 1 Object.keys(o) // => []

// Now modify the property x so that it is read-only Object.defineProperty(o, "x", { writable: false });

// Try to change the value of the property

o.x= 2; // Fails silently or throws TypeError in strict modeo.x// => 1// The property is still configurable, so we can change its value like this: Object.defineProperty(o, "x", { value: 2 });o.x// => 2// Now change x from a data property to an accessor property Object.defineProperty(o, "x", { get: function() { return 0; } });o.x// => 0

The property descriptor you pass to Object.defineProperty() does not have to include all four attributes. If you’re creating a new property, then omitted attributes are taken to be false or undefined. If you’re modifying an existing property, then the attributes you omit are simply left unchanged. Note that this method alters an existing own property or creates a new own property, but it will not alter an inherited property.

If you want to create or modify more than one property at a time, use Object.define Properties(). The first argument is the object that is to be modified. The second argument is an object that maps the names of the properties to be created or modified to the property descriptors for those properties. For example:

var p = Object.defineProperties({}, {

x: { value: 1, writable: true, enumerable:true, configurable:true },

y: { value: 1, writable: true, enumerable:true, configurable:true },

r: { get: function() { return Math.sqrt(this.x*this.x + this.y*this.y) }, enumerable:true, configurable:true

} });

This code starts with an empty object, then adds two data properties and one read-only accessor property to it. It relies on the fact that Object.defineProperties() returns the modified object (as does Object.defineProperty()).

We saw the ECMAScript 5 method Object.create() in §6.1 . We learned there that the first argument to that method is the prototype object for the newly created object. This method also accepts a second optional argument, which is the same as the second argument to Object.defineProperties(). If you pass a set of property descriptors to Object.create(), then they are used to add properties to the newly created object.

Object.defineProperty() and Object.defineProperties() throw TypeError if the attempt to create or modify a property is not allowed. This happens if you attempt to add a new property to a nonextensible (see §6.8.3 ) object. The other reasons that these methods might throw TypeError have to do with the attributes themselves. The writable attribute governs attempts to change the value attribute. And the configurable attribute governs attempts to change the other attributes (and also specifies whether a property can be deleted). The rules are not completely straightforward, however. It is possible to change the value of a nonwritable property if that property is configurable, for example. Also, it is possible to change a property from writable to nonwritable even if that property is nonconfigurable. Here are the complete rules. Calls to Object.defineProperty() or Object.defineProperties() that attempt to violate them throw TypeError:

Example 6-2 included an extend() function that copied properties from one object to another. That function simply copied the name and value of the properties and ignored their attributes. Furthermore, it did not copy the getter and setter methods of accessor properties, but simply converted them into static data properties. Example 6-3 shows a new version of extend() that uses Object.getOwnPropertyDescriptor() and Object.defineProperty() to copy all property attributes. Rather than being written as a function, this version is defined as a new Object method and is added as a nonenumerable property to Object.prototype.

6.7 Property Attributes | 133

Example 6-3. Copying property attributes

/*

*Add a nonenumerable extend() method to Object.prototype.*This method extends the object on which it is called by copying properties*from the object passed as its argument. All property attributes are*copied, not just the property value. All own properties (even non*enumerable ones) of the argument object are copied unless a property*with the same name already exists in the target object. */

Object.defineProperty(Object.prototype,

"extend", // Define Object.prototype.extend

{

writable: true,

enumerable: false, // Make it nonenumerable

configurable: true,

value: function(o) { // Its value is this function

// Get all own props, even nonenumerable ones

var names = Object.getOwnPropertyNames(o);

// Loop through them

for(var i = 0; i < names.length; i++) {

// Skip props already in this object

if (names[i] in this) continue;

// Get property description from o

var desc = Object.getOwnPropertyDescriptor(o,names[i]);

// Use it to create property on this

Object.defineProperty(this, names[i], desc);

} } });

欢迎转载,转载请注明来自一手册:http://yishouce.com/book/1/27645.html
友情链接It题库(ittiku.com)| 版权归yishouce.com所有| 友链等可联系 admin#yishouce.com|粤ICP备16001685号-1