目录函数
对象是由多个名/值对
组成的无序的
集合。对象中每一个属性对应任意类型的值
。
定义对象可使用构造函数
或字面量
的形式:测试
var obj = new Object; obj.name = "张三"; //添加描述 obj.say = function(){}; //添加行为 或 var obj = { name: "张三", say: function(){ }, };
除了以上添加属性的方式,还可使用Object.defineProperty定义新属性或修改原有的属性。code
一、 语法:对象
Object.defineProperty(obj, prop, descriptor)
二、 参数说明:ip
obj:必需。目标对象 prop:必需。需定义或修改的属性的名字 descriptor:必需。目标属性所拥有的特性
三、返回值:get
传入函数的对象。即第一个参数obj
给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。原型
当修改或定义对象的某个属性的时候,给这个属性添加一些特性:it
var obj = { test:"hello" } //对象已有的属性添加特性描述 Object.defineProperty(obj,"test",{ configurable:true | false, enumerable:true | false, value:任意类型的值, writable:true | false }); //对象新添加的属性的特性描述 Object.defineProperty(obj,"newKey",{ configurable:true | false, enumerable:true | false, value:任意类型的值, writable:true | false });
数据描述中的属性都是可选的,来看一下设置每个属性的做用。io
var obj = {} //第一种状况:不设置value属性 Object.defineProperty(obj,"newKey",{ }); console.log( obj.newKey ); //undefined ------------------------------ //第二种状况:设置value属性 Object.defineProperty(obj,"newKey",{ value:"hello" }); console.log( obj.newKey ); //hello
var obj = {} //第一种状况:writable设置为false,不能重写。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false }); //更改newKey的值 obj.newKey = "change value"; console.log( obj.newKey ); //hello //第二种状况:writable设置为true,能够重写 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true }); //更改newKey的值 obj.newKey = "change value"; console.log( obj.newKey ); //change value
var obj = {} //第一种状况:enumerable设置为false,不能被枚举。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false }); //枚举对象的属性 for( var attr in obj ){ console.log( attr ); } //第二种状况:enumerable设置为true,能够被枚举。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:true }); //枚举对象的属性 for( var attr in obj ){ console.log( attr ); //newKey }
删除目标属性
或是否能够再次修改属性的特性
(writable, configurable, enumerable)。这个属性起到两个做用:console
//-----------------1. 测试目标属性是否能被删除------------------------ var obj = {} //第一种状况:configurable设置为false,不能被删除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //删除属性 delete obj.newKey; console.log( obj.newKey ); //hello //第二种状况:configurable设置为true,能够被删除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //删除属性 delete obj.newKey; console.log( obj.newKey ); //undefined //-----------------2. 测试是否能够再次修改特性------------------------ var obj = {} //第一种状况:configurable设置为false,不能再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //从新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey //第二种状况:configurable设置为true,能够再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //从新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //hello
除了能够给新定义的属性设置特性,也能够给已有的属性设置特性
//定义对象的时候添加的属性,是可删除、可重写、可枚举的。 var obj = { test:"hello" } //改写值 obj.test = 'change value'; console.log( obj.test ); //'change value' Object.defineProperty(obj,"test",{ writable:false }) //再次改写值 obj.test = 'change value again'; console.log( obj.test ); //依然是:'change value'
提示:一旦使用Object.defineProperty给对象添加属性,那么若是不设置属性的特性,那么configurable、enumerable、writable这些值都为默认的false
var obj = {}; //定义的新属性后,这个属性的特性中configurable,enumerable,writable都为默认的值false //这就致使了neykey这个是不能重写、不能枚举、不能再次设置特性 // Object.defineProperty(obj,'newKey',{ }); //设置值 obj.newKey = 'hello'; console.log(obj.newKey); //undefined //枚举 for( var attr in obj ){ console.log(attr); }
value: 设置属性的值 writable: 值是否能够重写。true | false enumerable: 目标属性是否能够被枚举。true | false configurable: 目标属性是否能够被删除或是否能够再次修改特性 true | false
当使用存取器描述属性的特性的时候,容许设置如下特性属性:
var obj = {}; Object.defineProperty(obj,"newKey",{ get:function (){} | undefined, set:function (value){} | undefined configurable: true | false enumerable: true | false });
注意:当使用了getter或setter方法,不容许使用writable和value这两个属性
当设置或获取对象的某个属性的值的时候,能够提供getter/setter方法。
在特性中使用get/set属性来定义对应的方法。
var obj = {}; var initValue = 'hello'; Object.defineProperty(obj,"newKey",{ get:function (){ //当获取值的时候触发的函数 return initValue; }, set:function (value){ //当设置值的时候触发的函数,设置的新值经过参数value拿到 initValue = value; } }); //获取值 console.log( obj.newKey ); //hello //设置值 obj.newKey = 'change value'; console.log( obj.newKey ); //change value
注意:get或set不是必须成对出现,任写其一就能够。若是不设置方法,则get和set的默认值为undefined
在ie8下只能在DOM对象上使用,尝试在原生的对象使用 Object.defineProperty()会报错。
const obj1 = { a:1, }; const obj2 = Object.freeze(obj1); console.log(obj1 === obj2); // true console.log(Object.isExtensible(obj2)); // false Object.getOwnPropertyDescriptor(obj2,'a'); // {value: 1, writable: false, enumerable: true, configurable: false}
(1)给对象设置,Object.preventExtension(obj1)
,
禁止更改原型
,禁止添加属性
,
(2)为对象的每个属性设置,writable:false
,
禁止更改属性值,
(3)为对象的每个属性设置,configurable:false
。
注:
禁止添加属性
,是Object.preventExtensions控制的,
而禁止删除属性
,是configuable:false控制的。
// 1. 禁止更改原型 Object.setPrototypeOf(obj2,{c:3}); // 非严格模式:Uncaught TypeError: #<Object> is not extensible // 严格模式:Uncaught TypeError: #<Object> is not extensible // 2. 禁止添加属性 obj2.b = 2; // 非严格模式,静默失败,obj2仍是{a:1} // 严格模式:Uncaught TypeError: Cannot add property b, object is not extensible // 3. 禁止更改属性值 obj2.a = 2; // 非严格模式,静默失败,obj2仍是{a:1} // 严格模式:Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>' // 4. 禁止删除已有属性 delete obj2.a; // 非严格模式,返回false // 严格模式:Uncaught TypeError: Cannot delete property 'a' of #<Object> /// 5. 禁止更改writable为true Object.defineProperty(obj2,'a',{ writable:true, }); // 非严格模式:Uncaught TypeError: Cannot redefine property: a // 严格模式:Uncaught TypeError: Cannot redefine property: a // 6. 禁止更改enumerable为false Object.defineProperty(obj2,'a',{ enumerable:false, }); // 非严格模式:Uncaught TypeError: Cannot redefine property: a // 严格模式:Uncaught TypeError: Cannot redefine property: a // 7. 禁止更改configuable为true Object.defineProperty(obj2,'a',{ configuable:true, }); // 非严格模式,静默失败,configuable仍是false // 严格模式:静默失败,configuable仍是false
注:
在严格模式下,更改configurable为true,一样是静默失败。
const obj1 = { a:1, }; const obj2 = Object.seal(obj1); console.log(obj1 === obj2); // true console.log(Object.isExtensible(obj2)); // false Object.getOwnPropertyDescriptor(obj2,'a'); // {value: 1, writable: true, enumerable: true, configurable: false}
(1)给对象设置,Object.preventExtension(obj1)
,
禁止更改原型,禁止添加属性,
(2)为对象的每个属性设置,configurable:false
,
禁止更改属性值,
注:
与Object.freeze不一样的是,Object.seal
后的对象是可写的writable:true
。
参考:
MDN-Object.defineProperty()
MDN-Object.seal()()
MDN-Object.freeze()()