zoukankan      html  css  js  c++  java
  • javascript中的属性类型

      ECMA-262第5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特性。ECMA-262定义这些特性是为了实现javascript引擎用的,因此在javascript中不能直接访问它们。为了表示特性是内部值,该规范把它们放在了两对方括号中,例如[[Enumerable]]。

      ECMAScript中有两种属性:数据属性和访问器属性

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

        [[Configurable]]: 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。直接在对象上定义的  属性,它们的这个特性默认值为true。

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

        [[Writable]]:表示能否修改属性的值。直接在对象上定义的属性,它们的这个特性默认值为true。

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

      例如:

        var person = {name:"zcybb"};

      像这样直接在对象上定义的属性,它们的[[Configurable]],[[Enumerable]],[[Writable]]特性都被设置为true,而[[Value]]特性被设置为指定的值。

      要修改属性默认的特性,必须使用ECMAScript 5的Object.defineProperty()方法。这个方法接收三个参数:属性所在的对象,属性的名字和一个描述符对象,设置其中的一或多个值,可以修改对应的特性值。

      例如:

        var person = {};

        Object.defineProperty(person,"name",{

          writable:false,

          value:"bbzcy"

        });

      这个例子创建了一个名为name的属性,它的"bbzcy"是只读的,这个属性的值是不可修改的,如果尝试为它指定新值,在非严格模式下,赋值操作将被忽略,在严格模式下,赋值操作将会导致抛出错误。

      把configurable设置为false,表示不能从对象中删除属性。而且一旦把属性定义为不可配置的,就不能再把它变回可配置的了,此时再调用Object.defineProperty()方法修改除了writable之外的特性,都会导致错误。

      也就是说,可以多次调用Object.defineProperty()方法修改同一个属性,但在把 configurable特性设置为false之后就会有限制了。

      在调用Object.defineProperty()方法创建一个新的属性时,如果不指定,configurable,enumerable和writable特性的默认值都是false。

      

      2、访问器属性

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

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

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

        [[Get]]:在读取属性时调用的函数,默认值为undefined。

        [[Set]]:在写入属性时调用的函数,默认值为undefined。

      访问器属性不能直接定义,必须使用Object.defineProperty()方法来定义。如下例子:

      var book = {

        _year:2004,

        edition:1

      };

      Object.defineProperty(book,"year",{

        get:function(){

          return this._year;

        },

        set:function(newValue){

          if(newValue>2004){

            this._year = newValue;

            this.edition +=newValue-2004;

          }

        }

      })

      

      在这个方法之前,要创建访问器属性,一般都使用两个非标准的方法:

      book.__defineGetter__("year",function(){

        return this._year;

      });

      

      book.__defineSetter__("year",function(newValue){

        if(newValue > 2004){

          this._year = newValue;

          this.edition +=newValue-2004;

        }

      });

      定义多个属性:

      

      var book = {};

      Object.defineProperty(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;

            }

          }

        }

      }

    )

  • 相关阅读:
    软件安装的list(0918)
    putty配色备份
    曹工谈Spring Boot:Spring boot中怎么进行外部化配置,一不留神摔一跤;一路debug,原来是我太年轻了
    使用Hystrix的插件机制,解决在使用线程隔离时,threadlocal的传递问题
    曹工谈并发:Synchronized升级为重量级锁后,靠什么 API 来阻塞自己
    曹工力荐:调试 jdk 中 rt.jar 包部分的源码(可自由增加注释,修改代码并debug)
    曹工杂谈--只用一个命令,centos系统里装了啥软件,啥时候装的,全都清清楚楚
    曹工说Redis源码(7)-- redis server 的周期执行任务,到底要做些啥
    曹工说Redis源码(6)-- redis server 主循环大体流程解析
    曹工说Redis源码(5)-- redis server 启动过程解析,以及EventLoop每次处理事件前的前置工作解析(下)
  • 原文地址:https://www.cnblogs.com/zhangcybb/p/6533223.html
Copyright © 2011-2022 走看看