Object.defineProperty() 方法可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
value、writable、enumerable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var obj = {name :'张三' , age :19 };var new_obj = Object .defineProperty (obj, "name" , { value :'李四' })console .log (obj === new_obj)console .log (obj.name )var obj2 = {name :'张三' , age :19 , id :1101 };var new_obj = Object .defineProperty (obj2, "id" , { writable :false })console .log (obj2); obj2.id = 100 ;console .log (obj2);
给对象某一个属性设置writable属性为false后,修改该属性不会生效(该属性无法被修改)
enumerable 默认情况下Object.defineProperty新添加的属性是不可修改的(不能用obj3.address=”湖南”这种方式进行修改),且不能被for…in和Object.keys方法进行遍历到的。但通过属性赋值操作添加的普通属性是可以被枚举的例如var o = {a:1};o.b=2;那么对象o的b属性是可以被枚举出来的,但用Object.defineProperty添加的新属性默认是不能被枚举和修改的。
1 2 3 4 5 6 7 8 9 10 11 var obj3 = {name :'王五' , age :29 , id :1102 };var new_obj = Object .defineProperty (obj3, "address" , { writable :false , enumerable :false , value :"上海" })console .log (obj3); obj3.address = "北京" ;console .log (obj3);
用Object.defineProperty添加的新属性默认是不能被枚举和修改的
setter、getter 下面这种调用方式会造成无限递归,最终导致栈溢出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var obj = {name :'张三' , age :19 };var new_obj = Object .defineProperty (obj, "name" , { get : function ( ){ console .log ("调用了get方法" ); return obj['name' ]; }, set : function (value ){ console .log ("调用了set方法" ); obj['name' ] = value; } })console .log (obj === new_obj) new_obj.name ; obj.name = "李四"
下面这种方式是一种正确使用get、set访问器属性的案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function Archiver (temp_init ) { let _temperature = temp_init; const archive = []; Object .defineProperty (this , "temperature" , { get : function ( ) { console .log ("get" ); return _temperature; }, set : function (value ){ console .log ("set" ); _temperature = value; archive.push ({val :value}) } }) this .getArchive = () => archive; }const arc = new Archiver (30 );console .log (arc) arc.temperature = 31 ;console .log (arc.temperature )
set和get的正确使用方法