defineProperty Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象,也就是说,该方法允许精确地添加或修改对象的属性。
语法 Object.defineProperty(obj, prop, descriptor)obj: 要定义属性的对象。prop: 要定义或修改的属性的名称或Symbol。descriptor: 要定义或修改的属性描述符。
属性描述符 对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由getter函数和setter函数所描述的属性。一个描述符只能是数据描述符和存取描述符这两者其中之一,不能同时是两者。
属性描述符
configurable
enumerable
value
writable
get
set
数据描述符
可以
可以
可以
可以
不可以
不可以
存取描述符
可以
可以
不可以
不可以
可以
可以
如果一个描述符不具有value、writable、get和set中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有value或writable和get或set键,则会产生一个异常。 此外,这些选项不一定是自身属性,也要考虑继承来的属性。为了确认保留这些默认值,在设置之前,可能要冻结Object.prototype,明确指定所有的选项,或者通过Object.create(null)将 __proto__属性指向null。
configurable 当且仅当该属性的configurable键值为true时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除,默认为false,默认值是指在使用Object.defineProperty()定义属性时的默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , { configurable : true , value : 1 }); console .log (obj.key ); Object .defineProperty (obj, "key" , { enumerable : true }); delete obj.key ; console .log (obj.key );
1 2 3 4 5 6 7 8 9 10 11 12 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , { configurable : false , value : 1 }); console .log (obj.key ); Object .defineProperty (obj, "key" , { enumerable : true }); delete obj.key ; console .log (obj.key );
enumerable 当且仅当该属性的enumerable键值为true时,该属性才会出现在对象的枚举属性中,默认为 false。
1 2 3 4 5 6 7 8 9 10 11 "use strict" ;var obj = { a : 1 };Object .defineProperty (obj, "key" , { enumerable : true , value : 1 }); for (let item in obj) console .log (item, obj[item]);
1 2 3 4 5 6 7 8 9 10 "use strict" ;var obj = { a : 1 };Object .defineProperty (obj, "key" , { enumerable : false , value : 1 }); for (let item in obj) console .log (item, obj[item]);
value 该属性对应的值,可以是任何有效的JavaScript值,默认为undefined。
1 2 3 4 5 6 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , { value : 1 }); console .log (obj.key );
1 2 3 4 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , {});console .log (obj.key );
writable 当且仅当该属性的writable键值为true时,属性的值,才能被赋值运算符改变,默认为 false。
1 2 3 4 5 6 7 8 9 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , { value : 1 , writable : true }); console .log (obj.key ); obj.key = 11 ; console .log (obj.key );
1 2 3 4 5 6 7 8 9 10 11 12 13 "use strict" ;var obj = {};Object .defineProperty (obj, "key" , { value : 1 , writable : false , configurable : true }); console .log (obj.key ); obj.key = 11 ; Object .defineProperty (obj, "key" , { value : 11 }); console .log (obj.key );
get 属性的getter函数,如果没有getter,则为undefined。当访问该属性时,会调用此函数,执行时不传入任何参数,但是会传入this对象,由于继承关系,这里的this并不一定是定义该属性的对象。该函数的返回值会被用作属性的值,默认为undefined。
1 2 3 4 5 6 "use strict" ;var obj = { __x : 1 };Object .defineProperty (obj, "x" , { get : function ( ){ return this .__x ; } }); console .log (obj.x );
1 2 3 4 5 6 7 "use strict" ;var obj = { __x : 1 };Object .defineProperty (obj, "x" , { get : function ( ){ return this .__x ; } }); console .log (obj.x ); obj.x = 11 ;
set 属性的setter函数,如果没有setter,则为undefined。当属性值被修改时,会调用此函数,该方法接收一个参数,且传入赋值时的this对象,从而进行赋值操作,默认为undefined。
1 2 3 4 5 6 7 8 "use strict" ;var obj = { __x : 1 };Object .defineProperty (obj, "x" , { set : function (x ){ this .__x = x; }, get : function ( ){ return this .__x ; } }); obj.x = 11 ; console .log (obj.x );
1 2 3 4 5 6 7 8 9 "use strict" ;var obj = { __x : 1 };Object .defineProperty (obj, "x" , { set : function (x ){ console .log ("在赋值前可以进行其他操作" ); this .__x = x; } }); obj.x = 11 ;
相关 1 2 Js严格模式 https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/Js%E4%B8%A5%E6%A0%BC%E6%A8%A1%E5%BC%8F.md Js遍历对象 https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/Js%E9%81%8D%E5%8E%86%E5%AF%B9%E8%B1%A1%E6%80%BB%E7%BB%93.md
参考 1 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty