属性描述对象
何为属性描述对象
就是用来描述对象属性的对象,其作用就是规定了属性的行为,即拥有属性和方法
一共有6个控制属性的属性;在介绍前必须先熟悉操作和访问属性描述对象的方法
Object.getOwnPropertyDescriptor()
此方法用于获取自身(继承的不行,也就是不能越级)属性的属性描述对象,两个参数,第一个参数是目标对象,
第二个参数是字符串,目标对象的属性名
```
var obj = {name : 123};
obj.getOwnPropertyDescriptor(obj, "name");
//{value: 123, writable: true,
//enumerable: true, configurable: true}
```
Object.defineProperty(),Object.defineProperties()
-
Object.defineProperty()
Object.defineProperty(object, propertyName, attributesObject)用于设置一个属性的属性描述对象,
object:目标对象
propertyName:目标对象属性
attributesObject:要设置的属性描述对象var obj = Object.defineProperty({}, "p", { value : "aaa", writable : false, enumerable : true, configurable : false, })
-
Object.defineProperties()
Object.defineProperties()可以一次性设置多个属性的属性描述对象var obj ={}; Object.defineProperties(obj1, { a : {value : 123}, b : {value : 456, enumerable : true}, }) console.log(obj); //{b : 456, a : 123}
Object.prototype.propertyIsEnumerable()
Object.prototype.propertyIsEumerable(elem),作用为该属性是否可以枚举,填入一个字符串,(值为属性名),返回一个布尔值;这是一个实例方法
var obj = [1, 2];
obj.name = "arr";
obj.propertyIsEnumerable("name"); //true
obj.propertyIsEnumerable("length"); //false
obj.propertyIsEnumerable("0"); //true
6大元属性
能控制属性的属性称为元属性
-
value
设置该属性的属性值,默认值为undefinedvar obj = Object.defineProperty({}, "p", {value : 123}); obj["p"]; //123
-
writable
表示属性值(value)外部能否直接赋值,writable是一个布尔值,默认值是true
在用defineProperty()设置属性时,writable默认值为fasle;同理enumerable,configurable也是如此var obj = Object.defineProperty({}, 'p', {value : 123}); Object.getOwnPropertyDescriptor(obj, 'p'); //{ value: 123, writable: false, enumerable: false, configurable: false} var obj1 = {p :123}; Object.getOwnPropertyDescriptor(obj1, 'p'); //{ value: 123, writable: true, enumerable: true, configurable: true}
如值为false,外部无法直接赋值改变
var obj = {a : 1}; Object.defineProperty(obj, "a", {writable : false}); obj.a = 2; console.log(obj.a); //1,严格模式下这么做会报错
-
enumerable
表示该属性是否可以枚举,即是否可以遍历默认是值为true,如值为false,则无法被for-in,JSON.stringify以及Object.keys()var obj = { a : 1, b : 2, c : 3, }; Object.defineProperty(obj, "a", {enumerable: false}); for(var i in obj) { console.log(i); } //b //c
-
configurable
其值为布尔值,决定来是否可以修改属性描述对象,也就是当值为false时,enumerable,configurable,这两者不能再被修改,不然会报错:TypeError注意点
-
writable只有当false改为true时会把错,由true改为false时不会报错
var obj = Object.defineProperty({}, "a", { value : 123, //writable : false, writable : true enumerable : true, configurable : false, }); //Object.defineProperty(obj, "a", {writable : true}) 报错 Object.defineProperty(obj, "a", {writable :false}); //可以修改
- value值只有在writable和configurable至少一个为true时才能修改不然报错
-
configurable为false时则属性不能被删除
var obj = { a : 1, b : 2, }; Object.defineProperty(obj, "b", {configurable : false}); delete obj.a; delete obj.b; console.log(obj); //{b : 2}
-
-
get,set
get:取值,在对象取值时会跳用getter函数,默认值undefined,例如obj.a
set:存值,在对象赋值时会调用setter函数,默认值undefined,例如obj.a = 123;
注意点:当设置了set或者get元属性时,若设置了writable,或者设置value 属性,会报错:Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute,var obj = Object.defineProperty({}, "a", { get : function () { return "getter" } set : function (value) { console.log(value); }, })
写法2:
var obj = { get a() { return "getter"; }, set a(value) { console.log(value); } } obj.a = 123;
控制对象的状态
Object.preventExtensions:能删除修改旧属性,不能添加新属性
Object.seal:不能删除旧属性,但能赋值修改旧属性,不能添加新属性,相当于把configurable:false
Object.freeze:不能删除修改旧属性,不能添加新属性,相当于对象变为常量
var obj1 = {a : 1};
var obj2 = {a : 1};
var obj3 = {a : 1};
Object.preventExtensions(obj1); //旧属性能删除,能修改属性对象value,能外部直接赋值
//obj1.a = 2;
//delete obj1.a;
//Object.defineProperty(obj1, "a", {value : 3});
//obj1.b = 2; //新属性不能进行赋值
//Object.defineProperty(obj1, "b", {value : 3}); //不能添加新的属性描述对象,会保错
Object.seal(obj2); //旧属性不能删除,能修改属性对象value,能外部直接赋值
// obj2.a = 2;
//delete obj2.a;
// Object.defineProperty(obj2, "a", {value : 3});
//obj2.b = 2; //新属性不能进行赋值
//Object.defineProperty(obj2, "b", {value : 3}); //不能添加的新属性描述对象,会保错
Object.freeze(obj3); //旧属性不能删除,不能修改属性对象value,不能外部直接赋值
obj3.a = 2;
//delete obj3.a;
//Object.defineProperty(obj3, "a", {value : 3});
//obj3.b = 2; //新属性不能进行赋值
//Object.defineProperty(obj3, "b", {value : 3}); //不能添加的新属性描述对象,会保错
注意点:
-
冻结的是对象自身的属性,但是可以通过给原型添加属性来实现
var obj = {a :1}; Object.freeze(obj); console.log(obj.b); //undefined var obj0 = Object.getPrototypeOf(obj); obj0.b = 2; console.log(obj.b); //2
-
当然我们可以冻结原型
var obj = {a :1}; Object.freeze(obj); console.log(obj.b); //undefined var obj0 = Object.getPrototypeOf(obj); Object.freeze(obj0); obj0.b = 2; console.log(obj.b); //undefined
-
但是对于属性值为object类型的,我们冻结的是它的地址不变,但其内容还是可以变得
var obj = {a :{b : 1}}; Object.freeze(obj); console.log(obj.a); //{b : 1} obj.a.b = 2; console.log(obj.a); //{b : 2} obj.a.c = 3; console.log(obj.a); //{b : 2, c : 3}
三个检测是否冻结的方法
Object.isExtensible:能否为对象添加新属性
Object.isSealed:是否使用了Object.seal()
Object.isFrozen:是否使用了Object.freeze()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。