这种创建Object的方法有一个缺点:用同一个借口创建很多对象,会产生大量的重复代码
语法:
Object.defineProperty(obj, prop, descriptor)
1、数据属性
实例1:单个属性的建立
var person = {}; Object.defineProperty(person,'name',{ value:'zhangsan',//属性的值 writable:false,//不能更改 configurable:false,//不能删除 enumerable:false //不能for-in遍历 });
默认情况下:true
writable:false||true
configurable:false||true
enumerable:false||true
实例2:多个属性的建立
var person = {}; Object.defineProperties(person,{ name:{ value:'zhangsan', writable:false,//||true configurable:false,//||true enumerable:false,//||true }, sex:{ value:'nan', writable:false,//||true configurable:false,//||true enumerable:false,//||true }, age:{ value:23, writable:false,//||true configurable:false,//||true enumerable:false,//||true } });
实例3:
描述符:descriptor
再通俗一点,比如你在 面向对象 编程中 定义一个(没有定义方法)类:class person , 在这个类里面,有name,age, heigth, weight,等等属性, 这个类就可以看作一个对 person 的描述符,而具体的实例则是具体的“被描述物”
描述符可同时具有的键值
configurable | enumerable | value | writable | get | set | |
数据描述符 | Yes | Yes | Yes | Yes | No | No |
存取描述符 | Yes | Yes | No | No | Yes | Yes |
如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
实现原理:
var obj = {}; var descriptor = Object.create(null);//创建一个比较干净的对象 //没有任何的writable configurable enumerable value 继承 descriptor.value = 'static'; Object.defineProperty(obj,'key',descriptor); //显示 Object.defineProperty(obj,'key',{ value:'static', configurable:false, enumerable:false, writable:false }); function withValue(value){ var d = withValue.d ||( withValue.d = { enumerable: false, writable: false, configurable: false, value: null }); d.value = value; console.log(d); return d; }; Object.defineProperty(obj, "key", withValue("static")); var a = (Object.freeze||Object)(Object.prototype); //如果freeze()函数可用,返回一个冻结的Object.prototype console.log(a);
2、访问器属性
Set和get
实例1:get和set的作用
var person = { smoke:0, health:100 }; Object.defineProperty(person,'_smoke',{ get:function(){ return this.smoke; }, set:function(newValue){ if (newValue > 0) { this.smoke = newValue; this.health -= newValue; } } }); console.log(person._smoke);//触发了get,在读取属性时触发 person._smoke = 3;// 触发了set,在写入属性时触发 console.log(person.health);//97
对象字面量形式:
var person = { smoke:0, health:100, get _smoke(){//_smoke为要更改的属性 return this.smoke; }, set _smoke(newValue){//_smoke为要更改的属性 if (newValue > 0){ this.smoke = newValue; this.health -= newValue; } } }; console.log(person._smoke); person._smoke = 3; console.log(person.health)
实例2:创建一个自增的对象
function addArr(){ var num = null; var Arr = []; Object.defineProperty(this,'num1',{ // get:function(){ console.log('Get!'); return num; }, set:function(value){ num1 = value; Arr.push({vel:num1}); } }); this.getArr = function(){ return Arr; } } var arr1 = new addArr(); arr1.num1; arr1.num1 = 23; arr1.num1 = 56; console.log( arr1.getArr() );
读取属性的特性:
实例1:
var person = {}; Object.defineProperties(person,{ name:{ value:'zhangsan', writable:true }, sex:{ value:'nan', writable:true }, age:{ value:23, writable:true }, _age:{ get:function(){ console.log('今年的年龄是:'+this.age); }, set:function(newValue){ this.age = newValue; console.log('改过的年龄是:'+this.age); } } }); console.log(person); person._age; person._age = 26; console.log(person); console.log( Object.getOwnPropertyDescriptor(person,'age') ); console.log( Object.getOwnPropertyDescriptor(person,'_age') );
另一种创建对象:访问器属性和对象属性的方法
字面量的形式:
实例:
var person = { name:'zhangsan', age:23, sex:'nan', get _age() { console.log('今年的年龄:'+this.age); }, set _age(newValue){ this.age = newValue; console.log('现在的年龄:'+this.age); } } console.log(person); person._age; person._age = 56;
get和set与变量之间的空格不能省略