Object.defineProperty是ES5中的方法,它可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
语法:
Object.defineProperty(obj, prop, descriptor)
参数:
obj 要在其上定义属性的对象。 prop 要定义或修改的属性的名称。 descriptor 将被定义或修改的属性描述符。 descriptor 可以包含以下属性,默认情况下, writable, enumerable,configurable值为false
value:属性的值 writable:如果为false,属性的值就不能被重写,只能为只读了。 enumerable:是否能枚举,也就是否能在for...in循环中遍历出来或在Object.keys中列举出来。 configurable:如果为false,就不能再设置他的(value,writable,configurable)。 存取描述符同时具有以下可选键值:
get 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法 会被执行,方法执行时没有参数传入,但是会传入this对象
(由于继承关系,这里的this并不一定是定义该属性的对象)。
默认为 undefined。
set 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触 发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
默认为 undefined。
demo:
1.不能变更数据
`var a= {} Object.defineProperty(a,"b",{ value:111 }) console.log(a.b);//111 a.b=3 console.log(a.b);//111`复制代码
2.可以变更数据
` var a= {} Object.defineProperty(a,"b",{ value:111, writable:true }) console.log(a.b);//111 a.b=3 console.log(a.b);//3`复制代码
3.不可以枚举
`Object.defineProperty(a,"b",{ value:"save", writable:true }) Object.defineProperty(a,"c",{ value:222, writable:true }) console.log(Object.keys(a)); // []`复制代码
4.可以枚举
`Object.defineProperty(a,"b",{ value:"save", writable:true, enumerable:true }) Object.defineProperty(a,"c",{ value:222, writable:true, enumerable:true }) console.log(Object.keys(a)); // (2) ["c", "b"]for...in 同Object.keys一样`复制代码
5.s属性不可以进行配置变更
`Object.defineProperty(a,"s",{ value:888, writable:true, enumerable:true, configurable:false })`复制代码
6.s属性的writable:false可以重新定义
`Object.defineProperty(a,"s",{ value:888, writable:false, enumerable:true, configurable:false })`复制代码
7.s属性的除了writable设置为false ,defineProperty变量可以重新定义之外,其它的 value, enumerable, configurable都不可以变更其它内容
`Object.defineProperty(a,"s",{ value:888, writable:false, enumerable:true, configurable:false })`复制代码
8.set,get属性设置如果设置value和writable会报错,其它属性没关系, configurable为false后get,set之后不能再变更
` Object.defineProperty(a,"s",{ enumerable:true, configurable:false,get:function(){ return this.value},set:function(newdata){ this.value=newdata} })`复制代码
9.继承属性:
如果访问者的属性是被继承的,它的 get 和set 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。
`function myclass() {}var value;Object.defineProperty(myclass.prototype, "x", { get() { return value; }, set(x) { value = x; }});var a = new myclass();var b = new myclass();a.x = 1;console.log(b.x); // 1`复制代码
这可以通过将值存储在另一个属性中固定。在 get 和 set 方法中,this 指向某个被访问和修改属性的对象。
`function myclass() {}Object.defineProperty(myclass.prototype, "x", { get() { return this.stored_x; }, set(x) { this.stored_x = x; }});var a = new myclass();var b = new myclass();a.x = 1;console.log(b.x); // undefined`复制代码
不像访问者属性,值属性始终在对象自身上设置,而不是一个原型。然而,如果一个不可写的属性被继承,它仍然可以防止修改对象的属性。
`function myclass() {}myclass.prototype.x = 1;Object.defineProperty(myclass.prototype, "y", { writable: false, value: 1});var a = new myclass();a.x = 2;console.log(a.x); // 2console.log(myclass.prototype.x); // 1a.y = 2; // Ignored, throws in strict modeconsole.log(a.y); // 1console.log(myclass.prototype.y); // 1`复制代码
双向数据绑定的demo:
`const dataDemo = {};const demo = document.getElementById('demo');Object.defineProperty(dataDemo, 'content', { set(value) { demo.value = value; this.value = value; },get(value){ return this.value;}});demo.onchange = function(e) { dataDemo.content = this.value;}console.log(dataDemo.content);dataDemo.content="双向数据绑定新数据" //input文本框数据会跟着变化`复制代码