Javascript学习---属性的标识符和描述符

到目前为止,我们已经知道对象可以存储属性,属性以简单的键值对形式存储在对象中,但是对象的属性其实是一个复杂和可调的东西。


属性的标志

一个对象属性除了键和值外,还有三个特殊的属性,被叫做属性标识符:

(1)writable:如果为true,则该属性是可写的,否则为只读;

(2)enumerable:如果为true,则属性可以被循环列举出,否则则不能被列举;

(3)configurable:如果为true,则属性可以被删除或者属性值能够被修改,否则则不能;

默认情况下属性标识符都为true。


Object.getOwnPropertyDescriptor()

为了能够获得属性的标识符,我们可以使用Object.getOwnPropertyDescritor()来查看,它的语法如下:

let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);

其中,obj指的是需要获取属性信息的对象;propertyName是属性名。该方法返回的对象称之为属性描述对象,具体内容如下:

let user = {
  name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/* property descriptor:
{
  "value": "John",
  "writable": true,
  "enumerable": true,
  "configurable": true
}
*/


Object.defineProperty()

如果想添加属性并修改属性的标识符,我们可以使用Object.defineProperty()来操作,具体语法如下:

Object.defineProperty(obj, propertyName, descriptor)

其中descriptor参数指的是属性标识符的修改内容,下面是一个例子:

let user = {};

Object.defineProperty(user, "name", {
  value: "John"
});

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/*
{
  "value": "John",
  "writable": false,
  "enumerable": false,
  "configurable": false
}
 */

因为descriptor的内容只包含value值,故其余的三个属性标识为false


属性只读read-only

我们可以修改writable为false来设置属性为只读,这样就不能修改该属性的值了,否则会报错,例如:

let user = { };

Object.defineProperty(user, "name", {
  value: "Pete",
  // for new properties need to explicitly list what's true
  enumerable: true,
  configurable: true
});

alert(user.name); // Pete
user.name = "Alice"; // Error

属性不可列举non-enumerable

一般情况下,我们可以使用for...in来循环列举出对象的所有属性,例如:

let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

// By default, both our properties are listed:
for (let key in user) alert(key); // name, toString

但如果设置属性的enumerable为false后,该属性就不能被循环列举出,例如:

let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

Object.defineProperty(user, "toString", {
  enumerable: false
});

// Now our toString disappears:
for (let key in user) alert(key); // name

这里,toString()属性方法就不能没列举出来,同时使用Object.keys()也不能列举出来,如下:

alert(Object.keys(user)); // name

属性不可配置non-configurable

如果我们设置属性的configurable标识为false,那么那属性就不能被删除,甚至属性的值也不能修改,例如Math类的PI属性:

let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');

alert( JSON.stringify(descriptor, null, 2 ) );
/*
{
  "value": 3.141592653589793,
  "writable": false,
  "enumerable": false,
  "configurable": false
}
*/

这里可以看出,Math.PI是不可写、不可列举和不可配置的,如果我们要删除PI或者修改它,则会报错:

Math.PI = 3; // Error

// delete Math.PI won't work either

需要注意的是,一旦配置了configurable为false,在后面就不能设置该属性的标识符了,即便是使用defineProperty()也无法修改,例如:

let user = { };

Object.defineProperty(user, "name", {
  value: "John",
  writable: false,
  configurable: false
});

// won't be able to change user.name or its flags
// all this won't work:
//   user.name = "Pete"
//   delete user.name
//   defineProperty(user, "name", ...)
Object.defineProperty(user, "name", {writable: true}); // Error

Object.defineProperties()

Object.defineProperties()允许我们一次性添加属性并修改属性的描述符,它的语法如下:

Object.defineProperties(obj, {
  prop1: descriptor1,
  prop2: descriptor2
  // ...
});

这是例子:

Object.defineProperties(user, {
  name: { value: "John", writable: false },
  surname: { value: "Smith", writable: false },
  // ...
});


Object.getOwnPropertyDescriptors()

为了一次性获取对象所有属性的描述符,我们可以使用Object.getOwnPropertyDescriptors(),它返回对象所有属性的描述符,例如:

const obj = {
    [Symbol('foo')]: 123,
    get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));
 
// Output:
// { [Symbol('foo')]:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }
这里要注意的是,Object.getOwnPropertyDescriptors()返回的描述符包含了Symbol属性



猜你喜欢

转载自blog.csdn.net/Blue_Sky2015/article/details/79325108