js对象中的属性类型
2016-05-26 00:00
477 查看
摘要: 设置js对象的属性类型可以控制该对象的读写
ECMA-262在第五版定义只有内部才有的特性时,描述了属性的各种特征,这些特性时为了实现javascript引擎用的,因此在javascript中不能直接访问他们.
ECMAScript中有两种属性,数据属性跟访问器属性.
1.数据属性
数据属性包含一个数据值的位置.在这个位置可以读取和写入值,数据属性有4个描述其行为的特性.
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,即更改该属性的其他特性,或者能否把属性修改为访问器属性,默认值为true.值得一说的是,一旦将该属性设置成false之后,就无法重新设置成true.
[[Enumerable]]:表示能否通过for-in循环返回属性,默认为true.
[[Writable]]:表示能否修改属性的值,默认为true
[[Value]]:属性的值,读取属性值的时候,从这个属性读,写入属性值的时候,把新值保存在这个位置,默认值为undefined.
name跟age 都设置了不可写,所以返回结果还是之前定义的值,age设置了不可循环出来,所以最终循环出来的结果,把age跳过去了.
因为name并没有设置不可配置,所以这个时候可以更改name的数据属性,达到重新写入的目的,而因为job设置了不可配置,所以,再操作任何job的数据属性,都会抛出一个错误
上述写法,太麻烦?是的.设置单一属性的时候用defineProperty,而设置多属性的时候,可以直接用defineProperties,也建议这么写,这样代码维护的时候也比较方便,以上代码可以写作
2.访问器属性
访问器属性不包含数据值,包含一对getter和setter函数,两个函数都不是必要的,默认值均为undefined,在读取访问器属性时,会先调用getter函数,在写入访问器属性时,会先调用setter函数,并传入新值,类似某些语言的魔术方法__GET跟__SET,只是这里只控制单一属性.同样的,访问器属性,也有4个特性,其中Configurable跟Enumerable跟数据特性一样,这里不再细说.
先看一段错误代码:
如果代码这么写的话,会报出堆栈溢出,原因在于,读name的时候,会访问get,get中继续读了this.name,就会无限读,造成堆栈溢出,所以,一般用一个替代的属性处理,习惯性的用_+属性名表示.,用于表示只能通过对象方法访问的属性
这里还有一点需要提出来 ,在申明对象是,如果在自变量中声明了属性,则这个属性的数据特性都是默认true,即使更改其中某一项,其他的还是true,而如果在声明对象的时候,自变量中没有定义的属性,则均默认为false;
查看属性特性的方法为Object.getOwnPropertyDescriptor()
ECMA-262在第五版定义只有内部才有的特性时,描述了属性的各种特征,这些特性时为了实现javascript引擎用的,因此在javascript中不能直接访问他们.
ECMAScript中有两种属性,数据属性跟访问器属性.
1.数据属性
数据属性包含一个数据值的位置.在这个位置可以读取和写入值,数据属性有4个描述其行为的特性.
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,即更改该属性的其他特性,或者能否把属性修改为访问器属性,默认值为true.值得一说的是,一旦将该属性设置成false之后,就无法重新设置成true.
[[Enumerable]]:表示能否通过for-in循环返回属性,默认为true.
[[Writable]]:表示能否修改属性的值,默认为true
[[Value]]:属性的值,读取属性值的时候,从这个属性读,写入属性值的时候,把新值保存在这个位置,默认值为undefined.
[code=language-javascript]var person = { name : "Rainn", age : 25, job : "IT" }; Object.defineProperty(person,"name",{ writable : false, }); Object.defineProperty(person,"age",{ writable : false, enumerable : false, }); Object.defineProperty(person,"job",{ configurable : false }) person.name = "test"; person.age = 18; person.job = "Singer"; alert(person.name); //Rainn alert(person.age); //25 alert(person.job); //Singer for(var p in person){ console.log(person[p]) } //Rainn //Singer
name跟age 都设置了不可写,所以返回结果还是之前定义的值,age设置了不可循环出来,所以最终循环出来的结果,把age跳过去了.
因为name并没有设置不可配置,所以这个时候可以更改name的数据属性,达到重新写入的目的,而因为job设置了不可配置,所以,再操作任何job的数据属性,都会抛出一个错误
[code=plain]Object.defineProperty(person,"name",{ writable : true }); person.name = "test"; alert(person.name); //test Object.defineProperty(person,"job",{ configurable : true }); //Uncaught TypeError: Cannot redefine property: job
上述写法,太麻烦?是的.设置单一属性的时候用defineProperty,而设置多属性的时候,可以直接用defineProperties,也建议这么写,这样代码维护的时候也比较方便,以上代码可以写作
[code=plain]Object.defineProperties(person,{ name : { writable : false, configurable : false }, age : { writable : false, enumerable : false }, job : { configurable : false } })
2.访问器属性
访问器属性不包含数据值,包含一对getter和setter函数,两个函数都不是必要的,默认值均为undefined,在读取访问器属性时,会先调用getter函数,在写入访问器属性时,会先调用setter函数,并传入新值,类似某些语言的魔术方法__GET跟__SET,只是这里只控制单一属性.同样的,访问器属性,也有4个特性,其中Configurable跟Enumerable跟数据特性一样,这里不再细说.
先看一段错误代码:
[code=plain]var person = { name : "Rainn", age : 25 } Object.defineProperties(person,{ name : { get : function(){ return "hello! I'm " + this.name; }, set function(newValue){ this.name = newValue + "(changed)"; } }, age : { get : function(){ return "18 forever"; }, set : function(){ this.age -= 1; } } });
如果代码这么写的话,会报出堆栈溢出,原因在于,读name的时候,会访问get,get中继续读了this.name,就会无限读,造成堆栈溢出,所以,一般用一个替代的属性处理,习惯性的用_+属性名表示.,用于表示只能通过对象方法访问的属性
[code=plain]var person = {}; Object.defineProperties(person,{ _name : { value : "Rainn", writable : true, }, _age : { value : 25, writable : true, }, name : { get : function(){ return this._name; }, set : function(newValue){ this._name = newValue + '(used)'; } }, age : { get : function(){ return '18 forever'; }, set : function(){ this._age -= 1; } } }); alert(person.name); //Rainn person.name = "Tom"; alert(person.name); //Tom(used) alert(person.age); //18 forever person.age = 18; person.age = 18; alert(person._age); //23
这里还有一点需要提出来 ,在申明对象是,如果在自变量中声明了属性,则这个属性的数据特性都是默认true,即使更改其中某一项,其他的还是true,而如果在声明对象的时候,自变量中没有定义的属性,则均默认为false;
查看属性特性的方法为Object.getOwnPropertyDescriptor()
[code=plain]var person = { name : "rainn" }; Object.defineProperties(person, { name : { writable : false }, _age : { value : 25 } }) var nameDes = Object.getOwnPropertyDescriptor(person,'name'); var ageDes = Object.getOwnPropertyDescriptor(person,'_age'); console.log(nameDes); //{value: "rainn", writable: false, enumerable: true, configurable: true} console.log(ageDes); //{value: 25, writable: false, enumerable: false, configurable: false}
相关文章推荐
- js 数组的push 方法和 join方法
- JavaScript 从 HTML 中抽取指定图片地址
- JavaScript预编译
- ExtJs中,ID属性最好少使用
- 看看国外的 JS 题,你能全部做对吗?
- js常用函数
- JSP编译指令和动作指令
- javascript 笔记
- JNI中很有用的jstring 与 const char* 的相互转换函数
- phaser.js显示对象篇
- jsp自定义标签(时间格式化包括Long转时间)
- js内置对象-Date对象
- Js高程笔记->引用类型
- JavaScript的事件处理
- js获取字符串字节长度
- JavaScript DOM 中当将一个元素添加到其他的元素中时,原来的元素被删除
- JavaScript DOM 中当将一个元素添加到其他的元素中时,原来的元素被删除
- JavaScript DOM 中当将一个元素添加到其他的元素中时,原来的元素被删除
- JavaScript DOM 中当将一个元素添加到其他的元素中时,原来的元素被删除
- JavaScript DOM 中当将一个元素添加到其他的元素中时,原来的元素被删除