首页 > 代码库 > JS中的get & set
JS中的get & set
之前在看《Javascript 高级程序设计》一书中遇到过getter和setter,但因当时难于理解,且觉得用处较小,没有细看,今日突然遇到了一种使用get&set读写对象属性的方式。
//字面量创建对象var p={ //对象的成员:属性&方法 name:"cj", work:function(){ console.log("working...."); }, _age:18, //一般常用下划线开头,表示该属性只能有对象的方法进行访问。 //get读取p._age get age(){ return this._age; }, //set设置p._age set age(val){ if(val<0||val>150){ throw new Error("invalid value"); }else{ this._age=val; } }};console.log(p.age); //18console.log(p._age); //18p.age=30;console.log(p.age); //18console.log(p._age); //18
然后在网上搜到了一组类似的用法:
//创建一个类 var Person = function() { //属性:姓名,注意要属性名与get和set的名称不能重复否则会报错 this._username = ‘unknown‘; this._age = 0; } //在原型中给set和get方法 //在原型中get和set方法的名称是一样的,方便调用 Person.prototype = { set username(name) { // console.log(‘调用username的set方法‘); this._username = name; }, get username() { // console.log(‘调用了username的get方法‘); return this._username; } } var p = new Person(); console.log(p); console.log(p.username); //unknown p.username; p.username = ‘foo‘; console.log(p.username); //foo
但是没能查找到更多关于get和set的信息,只能琢磨一下getter和setter:
ECMAScript中有两种属性:数据属性和访问器属性。
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。
1、数据属性:在使用字面量形式创建的对象中,直接定义在对象上的属性,包含四个默认的属性:
(1)[[configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。该特性默认值为true。
(2)[[enumerable]]:表示能否通过for-in循环返回属性。该特性默认值为true。
(3)[[writable]]:表示能否修改属性的值。该特性默认值为true。
(4)[[value]]:包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置上,该特性默认值为undefined。
如果需要修改数据属性,需要使用ECMAScript5中的object.defineProperty()方法。
var p={ name:"nicole"};Object.defineProperty(p,"name",{ value:"abc"})console.log(p.name); //abc
2、访问器属性:不包含数据值;他们包含一对儿getter&setter函数,有如下4个特性:
(1)configurable:表示能否通过delete删除属性从而定义新的属性,能否修改属性的特性,或者能否把属性修改为数据属性。该特性默认值为true。
(2)enumerable:表示能否通过for-in循环返回属性。该特性默认值为true。
(3)get:在读取属性时调用的函数。该特性默认值为undefined;
(4)set:在写入属性时调用的函数。该特性默认值为undefined;
tip:_ 下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。
var book={ _year:2004, edition:1};Object.defineProperty(book,"year",{ //跟数据属性不一样,此处的year是访问器属性,_year是数据属性。 get:function(){ return this._year; }, set:function(newValue){ if(newValue>2004){ this._year=newValue; this.edition+=newValue-2004; } }}) book.year=2005;alert(book.edition); //2
支持这种方法的浏览器有:IE9+(IE8只是部分实现),Firefox4+,Safari5+,Opera12+,Chrome.旧版创建访问器属性,一般都是用两个非标准的方法:_defineGetter_()和_defineSetter_()
3、定义多个属性
var book={};Object.defineProperties(book,{ _year:{ writable:true, value:2004 }, edition:{ writable:true, value:1 }, year:{ get:function(){ return this._year; }, set:function(newValue){ if(newValue>2004){ this._year=newValue; this.edition+=newValue-2004; } } }})console.log(book._year); //2004console.log(book.edition); //1book.year=2005;console.log(book.edition); //2
使用ECMAScript5的Object.getOwnPropertyDescriptor(属性所在的对象,属性名称),可以取得给定属性的描述符,返回一个对象,对象包含相应的属性。
如果是数据属性,这个对象的属性有:configurable,enumerable,writable,value;
如果是访问器属性,这个对象的属性有:configurable,enumerable,get,set;
支持这个方法的浏览器有:IE9+,Firefox4+,Safari5+,Opera12+,Chrome。
++++var descriptor=Object.getOwnPropertyDescriptor(book,"_year");console.log(descriptor);var descriptor2=Object.getOwnPropertyDescriptor(book,"year");console.log(descriptor2);
第一个_year是数据属性,第二个year是访问器属性。所以最终打印出的结果如下:
所以看完这里,仍然不理解最初遇到的那种写法是为何,姑且当做是在字面量对象中创建了访问器属性,来读写数据属性吧。
JS中的get & set