• 《js高级程序设计》6.1.1-6.1.3——数据属性、访问器属性


    数据属性:该属性包含了一个数据值的位置,它包含了4个描述行为的特性:
    1. [[Configurable]]:表示是否能通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性。
    2. [[Enumerable]]:表示能否用for-in循环返回。
    3. [[writable]]:表示能否修改属性的值。
    4. [[Value]]:包含这个属性的数据值。读取属性值的时候从这个位置读,写入属性值的时候更新到这个位置,默认值为undefined。

    直接在对象上定义的属性的数据特性默认如下:
    1. [[Configurable]]:true
    2. [[Enumerable]]:true
    3. [[writable]]:true
    4. [[Value]]:”xiaochang” (初始时的赋值)

    这些特性不能直接被访问,要修改属性的特性只能通过Object.defineProperty( )方法,该方法包含三个参数:属性所在的对象,属性的名字,描述符对象[configurable|enumerable|writable|value]。例如:

    var person = {
        age:100
    };
     
    Object.defineProperty(person,"name",{
        configurable:false,
        writable:false,
        value:"xiaochang"
    });
     
    Object.defineProperty(person,"tall",{
        value:160
    });
     
    for(attr in person){
            console.log(attr); //name,age
    }
    console.log(person.name);   //xiaochang
    person.name="CC";           //为name属性指定新值
    console.log(person.name);   //xiaochang
    delete person.name;         //删除name属性
    console.log(person.name);   //xiaochang
     
    console.log(person.age);    //100
    person.age=200;             //为age属性指定新值
    console.log(person.age);    //200
    delete person.age;          //删除age属性
    console.log(person.age);    //undefined
     
    console.log(person.tall);   //160
    person.tall = 160;          //修改tall属性的值
    console.log(person.tall);   //160
    delete person.tall;         //删除name属性
    console.log(person.tall);   //160
    

      分析例子可知直接在对象上定义的属性,如age,[[Configurable]],[[Enumerable]],[[writable]]都被设置为true。
    属性name的[[Configurable]],[[writable]]被设置为false,所以无法修改和删除。
    调用Object.defineProperty( )方法时,如果不显示指定configurable,enumerable,writable的值,就默认为false,如属性tall。
    另外需要注意的是当configurable设置为false后无法再将其改为true,且除了writable之外,无法修改其它特性。在configurable为true的情况下可多次调用Object.defineProperty( )修改同一属性。
    在非严格情况下修改无法配置的属性操作会被忽略,在严格模式下会抛出错误。

    访问器属性:包含getter和setter函数。读取访问器属性时,调用getter函数,返回有效的值;在写入访问器属性时,调用setter函数传入新值。它包含了4个特性:
    1. [[Configurable]]:表示是否能通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性。
    2. [[Enumerable]]:表示能否用for-in循环返回。
    3. [[Get]]:读取属性时调用的函数,默认undefined。
    4. [[Set]]:写入属性时调用的函数,默认undefined。

    getter和setter不一定要成对出现,只有getter函数证明该属性只读不可写,尝试写入在非严格模式下会被忽略,严格模式会抛出错误。相同,只有setter函数证明只写不能读,尝试读在非严格模式下返回undefined,严格模式则抛出错误。

    访问器属性无法直接定义,必须使用Object.defineProperty( )来定义,如下:

    var person = {
        _name:"xiaochang", //name属性只读不可写
        _age:100,          //age属性只写不可读
        _tel:123456      //tel属性可读可写
    };
    Object.defineProperty(person,"name",{
        get:function(){
            return this._name;
        }
    });
    Object.defineProperty(person,"age",{
        set:function(newage){
            this._age = newage;
        }
    });
    Object.defineProperty(person,"tel",{
        get:function(){
            return this._tel;
        },
        set:function(newtel){
            this._tel= newtel;
        }
    });
    console.log(person.name);   //"xiaochang"
    person.name = "CC";         //尝试修改name属性
    console.log(person.name);   //"xiaochang"
    console.log(person.age);    //不可读属性,undefined
    person.age = 200;           //修改age
    console.log(person._age);   //直接读取对象方法才能访问的属性,可以看到值已更新200
    console.log(person.tel);    //123456
    person.age = 654321;        //更新tel
    console.log(person.tel);    //654321
    

      

    属性前面的下划线表示只能通过对象方法访问的属性,当我们调用person.name时实际调用了name属性的getter函数(直接调用person._name可得到相同的结果,这样做访问器就没什么意义了)。通过上面例子中可以很清晰的看出属性与访问器之间的关系。

    支持Object.defineProperty( )方法的浏览器有IE9+(IE8是第一实现Object.defineProperty( )方法的浏览器,但仅限于DOM对象,且只能创建访问器属性)、Firefox4+、Safari5+,Opera12+、Chrome。在不支持Object.defineProperty( )方法的浏览器中不能修改[[Configurable]],[[Enumerable]]。

    在Object.defineProperty( )方法之前,要创建访问器属性,一般使用非标准的方法:__defineGetter__() 和__defineSetter__(),这两个方法最初在Firefox引入,后来chrome1和Opera9.5也支持。改写上面的tel属性访问器如下:

    person.__defineGetter__("tel",function(){
        return this._tel;
    });
    person.__defineSetter__("tel",function(newtel){
        this._tel = newtel;
    

      ECMAScript 5还定义Object.defineProperties( )方法,该方法包含两个参数:属性所在的对象,多个属性的名字和其描述符对象组成的对象。其作用于Object.defineProperty( )相同,区别是可一次性定于多个属性。支持该方法的浏览器有IE9+、Firefox4+、Safari5+,Opera12+、Chrome。上面的例子可以改写如下:

    var person = {
        _name:"xiaochang", //name属性只读不可写
        _age:100,          //age属性只写不可读
        _tel:123456      //tel属性可读可写
    };
    Object.defineProperties(person,{
        name:{
            get:function(){
                return this._name;
            }
        },
        age:{
            set:function(newage){
                this._age = newage;
            }
        },
        tel:{
            get:function(){
                return this._tel;
            },
            set:function(newtel){
                this._tel= newtel;
            }
        }
    });
    

      对于上述讲到的属性特性,ECMAScript 5 给出了可以取得给定属性的描述符的方法Object.getOwnPropertyDescriptor(),该方法包含两个参数:属性所在的对象,要读取其描述符的属性名称。方法返回一个对象。如针对上面的例子可得:

    var descriptor = Object.getOwnPropertyDescriptor(person,"tel");
    for(attr in descriptor ){
        console.log(attr+":"+descriptor[attr]);
    }
     
    运行结果如下:
    get:function (){return this._tel;}
    set:function (newtel){this._tel= newtel;}
    enumerable:false
    configurable:false
    

      原文:http://www.2cto.com/kf/201504/393319.html

  • 相关阅读:
    欧拉公式
    isap的一些想法
    错误合集
    Hello World
    PAT (Advanced Level) Practice 1068 Find More Coins
    PAT (Advanced Level) 1087 All Roads Lead to Rome
    PAT (Advanced Level) 1075 PAT Judge
    PAT (Advanced Level) 1067 Sort with Swap(0, i)
    PAT (Advanced Level) 1017 Queueing at Bank
    PAT (Advanced Level) 1025 PAT Ranking
  • 原文地址:https://www.cnblogs.com/mmlvj/p/4664071.html
Copyright © 2020-2023  润新知