在介绍Object.defineProperty和Object.defineProperties方法之前,我们先来学习一下对象属性的特性描述符,你也可以理解为对象属性的属性。这个跟文件的属性为-rw-r-r等类似,属性的属性用来表示属性的一些读写修改的特性。
{ configurable:false, enumerable:false, writable:false, value:"mooshine", get:function() { return this.vv; }, set:function(){ this.vv="mooshine"; } }
一个对象属性有上面这写个属性,其中value,和get,set是用来定义属性值的,这两种定义方式只能采取一种,不能同时出现。
剩下的configurable,enumerable,writable用来描述一个对象属性的读写特性。这三个都是boolean值。
configurable表示可配置性,enumerable表示可枚举性,writable表示可修改性。
configurable表示属性定义后,是否还可以通过Object.defineProperty来修改属性的特性,为false时,再次调用Object.defineProperty方法修改属性特性会报错。并且为false时,是不能通过delete操作符删除此属性的。只有为true时才可以修改或者删除。
enumerable表示的是此属性是否可以进行枚举,为false时,在for...in循环,Object.keys()中都不会出现此属性。为true时,才可以通过遍历获得此属性。
writable表示此属性是否可以被修改赋值,为false时,修改属性值无效,严格模式下会报错的。
这三个读写配置属性的默认值都为false。
学习了上面对象属性的特征描述符后,我们来看Object.defineProperty方法,这个方法用来在对象上定义添加一个属性,或者修改一个属性。
var obj={}; Object.defineProperty(obj,"name",{ value:"mooshine", configurable:true, enumerable:false, writable:false });
通过Object.defineProperty()方法给对象添加属性,可以设置属性的读写特征描述符。然后我们之后想要将name属性的writable改为true,可以像下面这样写:
Object.defineProperty(obj,"name",{ writable:true });
对于对象已有属性使用Object.defineProperty方法,会修改这个属性的值或者相应的特征描述符。二次使用Object.defineProperty方法有点像$.extend对象赋值方式。
Object.defineProperty方法十分简单,就是用来添加或者修改对象属性的,并且可以通过属性特征描述符来控制属性的可配置性,可枚举性,可修改性。
Object.defineProperties和Object.defineProperty的关系就如同他们的名字一样,是单数和复数的关系。Object.defineProperty一次只能定义一个属性,而Object.defineProperties一次可以定义多个属性:
Object.defineProperties(obj, props)
语法上,Object.defineProperties只有两个参数,比Object.defineProperty少了一个参数。
Object.defineProperties的第二个参数是一个属性集合对象。
var obj={} Object.defineProperties(obj,{ name:{ value:"mooshine", writable:false }, age:{ value:26, writable:true }, money:{ value:"many many many much", configurable:false, enumerable:true, writable:false } });
通过以上的代码形式,使用Object.defineProperties可以一次定义或修改对象上N多个属性,是为了给Object.defineProperty提供方便而生的。
总结还是提一下Object.defineProperty和Object.defineProperties的兼容性,可用性。这两个属性在IE9+浏览器中都支持。所以是可以放心使用的。目前,有很多公司已经抛弃了对IE8的支持。不只是公司,就连一些框架都抛弃了对IE8的兼容了。jQuery-2.x已经不支持IE8了,angularJs,vue.js等也不提供对IE8的支持了。所以,我觉得有时我们的项目也该放弃IE8浏览器了。如果考虑IE8,好多新特性都就没有用武之地了。不只是本文的两个方法,就连H5中博眼球的SVG,canvas也是IE9才支持的。当然,你可以使用IE中的vml技术来兼容SVG,但那就是为了一个版本的浏览器而要多付出一半的代码时间,有点事倍功半,得不偿失的意味。
所以,还在兼容IE8,你out了。