JavaScript.descriptor(属性描述符)

属性描述符是对JavaScript属性的描述,包括:value、writable、enumerable、configurable,除value其他默认为true。


本文包括:

  • 取得属性描述符、 Object.getOwnPropertyDescriptor( obj, "property-name" );
  • 属性描述符详解、

    1. writable[对象是否可以再赋值], enumerable[对象是否可以迭代], configurable[是否可以通过Object.defineProperty对对象再次配置]

  • 属性描述符应用、 writable: false  &&  configurable: false 产生对象常量
  • 其他相关:
  1. 禁止扩展:Object.preventExtensions(obj),阻止对象再添加属性,对象不可以扩展。
  2. 封装: Object.seal(obj),封装一个对象,对象上不能再添加新的属性、不能重新定义属性描述符、不能删除某个属性,

      等价于 Object.preventExtensions(obj),并设置现有的所有属性为 configurable:false。

  3.冻结:Object.freeze(obj),对象不能再做任何修改或者删除属性的操作,

    效果相当于调用了 Object.seal(obj) 并设置所有属性为 writable: false


1.取得属性描述符

var myObject = {
    a: 2
};
 
Object.getOwnPropertyDescriptor( myObject, "a" );
// { value: 2, writable: true, enumerable: true, configurable: true }

可以看到,对象myObject的属性a,除了拥有value描述符,还拥有writable、enumerable、configurable三个用于描述属性描述符。

var myObject = {};
 
Object.defineProperty( myObject, "a", {
    value: 2,
    writable: true,
    configurable: true,
    enumerable: true
} );
// 上面的定义等同于 myObject.a = 2; 
// 所以如果不需要修改这三个特性,我们不会用 `Object.defineProperty`
 
myObject.a; // 2

通过Object.defineProperty(obj,"propertyname",{})可以为对象添加属性,并且通过属性描述符为属性添加一些特性。


2.属性描述符详解

 

2.1 writable[对象是否可以再赋值]

// "use strict";
var myObject = {};
 
Object.defineProperty( myObject, "a", {
    value: 2,
    writable: false, // 不可写!
    configurable: true,
    enumerable: true
} );
 
myObject.a = 3; // 写入的值将会被忽略
 
myObject.a; // 2

/*
如果应用了 strict mode 的话,那么 myObject.a 将会抛出 TypeError,而不是仅仅忽略写入的值。
ES5 还引入了对象属性的 Getter 和 Setter,这里的 writable: false可以认为是和没有定义或者定义了没有任何操作的 setters 的情况大致等同。
当然了,如果是 strict mode 下,需要在 setters 里面抛出 TypeError 来完全模拟 writable: false 的情形。
*/

2.2 enumerable[对象是否可以迭代]

var myObject = {
    a: 2
};
 
myObject.a = 3;
myObject.a;                 // 3
 
Object.defineProperty( myObject, "a", {
    value: 4,
    writable: true,
    configurable: false,    // 不可配置!
    enumerable: true
} );
 
myObject.a;                 // 4
myObject.a = 5;
myObject.a;                 // 5
 
Object.defineProperty( myObject, "a", {
    value: 6,
    writable: true,
    configurable: true, //同样的,也不能用delete删除对象这个属性了
    enumerable: true
} ); // TypeError


/*
注意,一旦某个属性被指定为 configurable: false,
那么就不能从新指定为configurable: true 了,这个操作是单向,不可逆的。
*/

2.3 configurable[是否可以通过Object.defineProperty对对象再次配置]

var myObject = { };
 
Object.defineProperty(
    myObject,
    "a",
    // make `a` enumerable, as normal
    { enumerable: true, value: 2 }
);
 
Object.defineProperty(
    myObject,
    "b",
    // make `b` NON-enumerable
    { enumerable: false, value: 3 }
);
 
myObject.b; // 3
("b" in myObject); // true
myObject.hasOwnProperty( "b" ); // true
 
// .......
 
for (var k in myObject) {
    console.log( k, myObject[k] );
}
// "a" 2
 
myObject.propertyIsEnumerable( "a" ); // true
myObject.propertyIsEnumerable( "b" ); // false
 
Object.keys( myObject ); // ["a"]
Object.getOwnPropertyNames( myObject ); // ["a", "b"]


/*
这里可以看到,enumerable: false 使得该属性从对象属性枚举操作中被隐藏,
但Object.hasOwnProperty(...) 仍然可以检测到属性的存在。
另外,Object.propertyIsEnumerable(..) 可以用来检测某个属性是否可枚举,
Object.keys(...) 仅仅返回可枚举的属性,
而Object.getOwnPropertyNames(...) 则返回该对象上的所有属性,
包括不可枚举的。
*/

3.属性描述符应用

var myObject = {};
 
Object.defineProperty( myObject, "FAVORITE_NUMBER", {
    value: 42,
    writable: false,
    configurable: false
} );

/*
通过组合 writable: false 和 configurable: false,可以创建一个不能修改、重新定义或删除其属性的对象常量
这里对该对象属性的删除,修改操作会被忽略,不能再用Object.defineProperty(...) 来重新配置该属性的特性
*/

4.其他相关

4.1禁止扩展

/*
如果希望阻止新的属性被加入到对象,可以通过调用
Object.preventExtensions(...) 来做到这一点:
*/

var myObject = {
    a: 2
};
 
Object.preventExtensions( myObject );
 
myObject.b = 3;
myObject.b; // undefined

//在 strict mode 下,行为稍有不同,对属性的赋值会抛出 TypeError, 而不是仅仅忽略赋值操作

4.2封装

/*
可以通过 Object.seal(...) 来封装一个对象。在调用这个操作之后,
对象上不能再添加新的属性,也不能重新定义属性描述符或者删除某个属性:
*/
var myObject = {
    a: 2
};
Object.seal(myObject);
myObject.b = 'b';
console.log(myObject); // {a: 2}
 
myObject.a = 6;
console.log(myObject); // {a: 6}

/*
Object.seal(...) 
相当于调用了 Object.preventExtensions(..),并设置现有的所有属性为 configurable:false。
*/

4.3冻结

/*
调用 Object.freeze(...) 可以创建一个被冻结的对象,这个对象拥有不能再被做任何修改或者删除属性的操作
*/

var myObject = {
    a: 2
};
Object.seal(myObject);
myObject.b = 'b';
console.log(myObject); // {a: 2}
 
myObject.a = 6;
console.log(myObject); // {a: 2}

//相当于调用了 Object.seal(...) 并设置所有属性为 writable: false

原文

猜你喜欢

转载自www.cnblogs.com/luohaonan/p/9961915.html