zoukankan      html  css  js  c++  java
  • 《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

  • 相关阅读:
    2018.11.16 RX- IC
    第15.29节 PyQt(Python+Qt)入门学习:containers容器类部件QScrollArea滚动区域详解
    PyQt(Python+Qt)学习随笔:QTabWidget部件选项卡可用状态访问方法isTabEnabled、setTabEnabled
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件的tabBar、count、indexOf方法
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件的currentWidget和widget方法
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件移除选项卡的removeTab和clear方法
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件添加选项卡的addTab和insertTab方法
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件设置tabsClosable后不能关闭选项卡的原因
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件的documentMode属性作用
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件概述和属性介绍
  • 原文地址:https://www.cnblogs.com/mmlvj/p/4664071.html
Copyright © 2011-2022 走看看