• js中属性类型:数据属性与访问器属性


    js中属性类型分为两种:数据属性和访问器属性

    在js中,对象都是由名值对构成的,名:就是我们所说的属性名,值就是属性对应的值(基本值、对象、方法)。

    ECMA-262第5版定义了只有内部才用的特性,描述了属性的各种特征,比如,这个属性能否被删除、能否被枚举、能否被修改、以及读取属性的值。

    这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问他们。

    1、先来说一下数据属性

    数据属性:包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性

    Configurable:表示能否通过delete删除属性,从而重新定义属性,能否修改属性的特性,或则能否把属性修改为访问器属性。我们一般在对象上自定义的属性,它们的这个特性一般为true。

    Enumberable:表示能否通过for-in循环返回属性(枚举),自定义的对象属性,默认值为true。

    Writable:表示能否修改属性的值,自定义对象的属性,这个特性值默认为true。

    Value:包含这个属性的数据值,读取属性值的时候从这个读,写入属性值的时候,把新值保存在这个位置。这个特性的默认值为undefined。

    ECMAScript5定义了一个修改属性的这些默认特性的方法:Object.defineProperty();

    这个方法接收三个参数:属性所在的对象、属性的名字(字符串形式)、一个描述符对象。其中描述符对象的属性必须是:configurable、enumberable、writable、value,设置其中的一个或多个值,可以修改对应的特性值。例如:

        var person={};
        Object.defineProperty(person,"name",{
            writable:false,
            value:"Nicholas"
        });
        console.log(Object.getOwnPropertyDescriptor(person,"name"));//读取属性的特性的方法,后面会介绍
        console.log(person.name);//Nicholas
        person.name="Greg";
        console.log(person.name);//Nicholas

    上面,对name属性的两个特性writable、value进行了设置,可见,我们更改name属性的值是无效的,在严格模式下会报错;

    当用Object.defineProperty()创建一个新属性时,若不指定configurable、enumberable、writable这些特性时,都是false,若果在原来设置过的基础上设置其中的一个或多个,则无此限制。

    另外,当设置configurable为false后,也就是把该属性变成不可设置的,除delete不能删除该属性外,再次用Object.defineProperty()方法设置除writable特性外的其它特性时,在非严格模式时什么都不会发生,在严格模式时会报错。(同时configurable特性也设置不了true了!!!);

    2、访问器属性:

    访问器属性不包含数据值,他们包含一对儿getter和setter函数(不过,这两个函数都不是必须的)。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下4个特性

    configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或则能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为true。

    enumberable:表示能否通过for-in来循环返回属性。对于直接在对象上定义的属性,这个特性的默认值为true。

    get:读取属性时调用的函数。默认值为undefined

    set:在写入属性时调用的函数。默认值为undefined

    访问器属性不能直接定义,必须使用Object.defineProperty()来定义。请看下面的例子:

        var book={
            _year:2004,
            edition:1
        };
        //下边给book对象设置一个year(访问器属性)
        Object.defineProperty(book,"year",{
            get:function(){
                return this._year;
            },
            set:function(newValue){
                if(newValue>2004){
                    this._year=newValue;
                    this.edition=newValue - 2004;
                }
            }
        });
        book.year =2005;
        console.log(book.edition);//1
        console.log(book._year);//2005
        console.log(book.year);//2005
        console.log(book);//{_year: 2005, edition: 1}

    可见,创建的访问器属性,用console是打印不出来的,我们常见的使用访问器属性的方式就是上述这种方式,修改访问器属性,会导致其他属性变化!!!

    当然,不一定非要指定get和set,只指定get就是只能读,不能写,只指定set就是不能读。

    当然也可以同时定义多个属性,用:Object.defineProperties()方法,利用这个方法可以通过描述符一次定义多个属性,这个方法接收两个参数,第一个参数是要添加和修改其属性的对象,第二个参数(对象:描述符)的属性与第一个对象中要添加或修改的属性要一一对应。如:

        var book={};
        Object.defineProperties(book,{
            _year:{//定义一个数据属性,其它为指定的特性值为false
                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;
                    }
                }
            }
        });
        book.year=2003;
        console.log(book);//{_year: 2004, edition: 1}
        book.year=2005;
        console.log(book);//{_year: 2005, edition: 1}
        // Object.getOwnPropertyDescriptor();用来读取给定属性的描述符,这个方法有两个参数,属性所在的对象和要读取其描述符的属性名,返回一个对象。
        var descriptor=Object.getOwnPropertyDescriptor(book,"_year");//数据属性
        var descriptor2=Object.getOwnPropertyDescriptor(book,"year");//访问器属性
        console.log(descriptor);//{value: 2005, writable: true, enumerable: false, configurable: false}
        console.log(descriptor2);//{get: ƒ, set: ƒ, enumerable: false, configurable: false}
    Object.getOwnPropertyDescriptor();用来读取给定属性的描述符,这个方法有两个参数,属性所在的对象和要读取其描述符的属性名,返回一个对象。这个方法可以在任何浏览器使用。
  • 相关阅读:
    数据结构 【实验 串的基本操作】
    Ioc容器依赖注入-Spring 源码系列(2)
    定时任务管理中心(dubbo+spring)-我们到底能走多远系列47
    jvm内存增长问题排查简例
    Ioc容器beanDefinition-Spring 源码系列(1)
    SPI机制
    java工厂-积木系列
    java单例-积木系列
    利用spring AOP 和注解实现方法中查cache-我们到底能走多远系列(46)
    java 静态代理-积木系列
  • 原文地址:https://www.cnblogs.com/fqh123/p/10388445.html
Copyright © 2020-2023  润新知