前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

我的JavaScript学习笔记:对象属性类型

在ECMAScript中属性分两种类型:数据属性和访问属性

1.数据属性

数据属性有四个描述其行为的特性个:[[Configurable]]、[[Enumerable]]、[[Writable]]、[[Value]]。

  • [[Congigurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否将数据属性改为访问属性,默认值为true
  • [[Enumerable]]表示属性是否可枚举,即使用for in 返回属性,默认值为true
  • [[Writable]]表示是否能修改属性值,默认值为true
  • [[Value]]表示包含属性的数据值,读取属性时,从这个位置读取属性,写入新的属性时将新的属性保存在这个位置,默认值是undefined
let obj={
             name:"JSindexHTML"
};

在上面的代码中,我们定义了一个对象obj,属性名为name,属性值为JSindexHTML。在这个对象的数据属性 [[Value]] 值就被设置为 JSindexHTML。对属性 name 的任何修改都会相应的改变这个对象的数据属性 [[Value]] 的值。

如果要修改数据属性的特性,我们可以使用 Object.defineProperty() 方法。这个方法接收三个参数:属性所在的对象,属性名(属性名需要加引号),描述符对象。其中描述符对象的属性必须是:configurable、enumerable、writable 和 value且为小写。

Object.defineProperty(obj,"name",{
                                                       writable:false,
                                                           value:"JSindexHTML"
                                                       })
obj.name="Jack";
console.log(obj.name);//JSindexHTML

在上面的代码中,我们将对象的数据属性 [[Writable]]修改为 false,即禁止修改对象的属性值。此时name 属性是只读的,修改name值,严格模式下会抛出错误,非严格模式忽略。所以当我们将对象obj的name属性值修改为Jack时,console.log(obj.name) 的结果是 JSindexHTML。

如果我们把[[Writable]]修改为 true:

Object.defineProperty(obj,"name",{
                                                     writable:true,
                                                          value:"JSindexHTML"
                                                       })
obj.name="Jack";
console.log(obj.name);//Jack

当我们将 writable更改为true后,更改 obj 的 name 属性值:obj.name="Jack",console.log(obj.name)的结果为修改后的 name 的属性值 Jack。

上面的规则也适用于配置属性:

Object.defineProperty(obj,"name",{
                                                     configurable:false,
                                                          value:"JSindexHTML"
                                                       })

console.log(obj.name);//Jack

在上面的代码中,我们对象的数据属性 configurable 设置为false,所以不使用 delete 删除我们的对象属性。所以console.log(obj.name)的结果为 JSindexHTML。

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

2.访问属性

访问属性不包含数据值而是包含一对儿 get和 set函数,但这两个函数不是必须的。在读取访问属性时会调用getter函数,这个函数负责返回有效值;在写入访问属性时,会调用setter函数并传入新值,这个函数决定如何处理数据。访问属性有以下四个特性:

  • [[Congigurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否将数据属性改为访问属性,默认值为true
  • [[Enumerable]]表示属性是否可枚举,即使用for in 返回属性,默认值为true
  • [[getter]]在读取访问属性时调用的函数
  • [[setter]]在写入访问属性时调用的函数
  • 访问属性不能直接定义,必须使用Object.definedProperty()方法定义。

    let book={
                  _year:2019,
                  edition:1
                   }
    Object.defineProperty(book,"year",{
                                          get:function(){
                                            return this._year
    },
      set:function(newValue){
                       if(newValue>2019){
                         this._year=newValue;
                         this.edition+=newValue-2019;
                       }
                }
    }
      )
      book.year=2020;
    console.log(book.edition);//2

    在上面的代码中,我们定义了 book 对象,并给这个对象添加了两个属性 _year 和 edition。_year前面的下划线是一种常用几号,用于表示只能通过对象方法访问的属性。访问器属性year包含了两个属性setter 和 getter 函数,getter函数获取_year 的值,而setter函数通过计算确定正确的版本。因此当我们把year属性修改为2020的时候,_year就会变成2019,而 edition 变为 2。这是使用访问器属性常见的方式,即设置一个属性的值也会导致其他属性值发生变化。

    为了兼容旧版本的浏览器,我们可以使用两个非标准方法创建访问属性器:__defineGetter__ 和 __defineSetter__。注意,这两个方法的前后的下划线是分别是由两条组成。

    let book={
                  _year:2019,
                  edition:1
                   }
    book.defineGettet=function(){
    return this._year;
    }
    book.defineSetter=function(newValue){
     if(newValue>2019){
                         this._year=newValue;
                         this.edition+=newValue-2019;
                       }
    }
     book.year=2020;
    console.log(book.edition);//2

    在不支持Object.defineProperty()方法的浏览器中不能修改[[Confirguable]] 和 [[Enumerable]].

    发表评论:

    控制面板
    您好,欢迎到访网站!
      查看权限
    网站分类
    最新留言