_TANGTANG

导航

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);   //18
console.log(p._age);  //18
p.age=30;
console.log(p.age);  //18
console.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;

 

注:对于两种属性默认值的测试如下,并非书中说的默认为true,有的情况下默认为false:

 

 

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);  //2004
console.log(book.edition);  //1
book.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是访问器属性。所以最终打印出的结果如下:

 

所以看完这里,仍然不理解最初遇到的那种写法是为何,姑且当做是在字面量对象中创建了访问器属性,来读写数据属性吧。

 

posted on 2016-09-07 15:41  _TANGTANG  阅读(1195)  评论(4编辑  收藏  举报