zoukankan      html  css  js  c++  java
  • Javascript之【对象】的深入理解

      对象

                 ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”

                 于是,我们可以将对象想象成散列表:就是一些名值对,其中值可以是数据或函数

          1.理解对象及其内部机制

                 我们先来创建一个最简单的Object实例,同时为它添加属性和方法:

    1 var person=new Object();
    2 person.name="Sleipnir";
    3 person.age=23;
    4 person.job="Software Enginner";
    5 
    6 person.sayname=function(){
    7    alert(this.name);
    8   };

               有时候这种直接赋值的方式太繁琐,我们还可以用对象字面量的方式来赋值:

    1  var person={
    2        name:"Sleipnir",
    3        age:23,
    4        job:"Software Enginner",
    5 
    6        sayname:function(){
    7            alert(this.name);
    8      }
    9    };

                   这两种创建对象的效果都是一样的,下面,我们来深入对象内部,来探讨属性类型

           2.属性类型

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

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

                  Configurable:表示能否通过delete来删除从而重新定义属性,它的默认值为true;

                  Enumerable:表示属性能否被使用for-in来遍历,默认值为true;

                  Writable:表示能否被修改,默认值为true;

                  Value:包含属性的数据值,默认值为underfined

                  像在上面对象中直接定义的属性,它们的configurable,enumerable,writable都默认是true,value就是设置的“Sleipnir”这个值

                  想查看特性的值,就需要用到Object.getOwnPropertyDescriptor()这个方法:

                  在上面的对象的基础上,我们来查看属性的特性:

    1 var aa=Object.getOwnPropertyDescriptor(person,"name");
    2 console.log(aa.configurable);  //true
    3 console.log(aa.enumerable);  //true
    4 console.log(aa.writable);  //true
    5 console.log(aa.value);  //"Sleipnir"

                 要想修改默认的特性,就要用到Object.defineProperty()这个方法,概念不说太多,我们直接来举个栗子:

                 在上面的对象的基础上,我们来修改属性的特性:

     1 Object.defineProperty(person,"name",{
     2        writable:false,
     3        enumerable:false,
     4        value:"xiaoxiao",
     5        configurable:false
     6       });
     7 
     8 console.log(person.name);  //"xiaoxiao"
     9 person.name="love";
    10 console.log(person.name);  //"xiaoxiao"

                从上面的代码可以看出,当writable从默认的true被修改成false后,你再给name赋值就无法成功了,它还是显示默认的“xiaoxiao”

               然而,有一点要注意,当把confugurable设置成false后,就没办法把属性设置回可设置状态了,换句话说,是不可逆的,当把confugurable设成false后,再用              Object.defineProperty()修改除writable之外的特性,都会导致错误

               这里有个坑,你直接在对象上定义的属性,它的数据属性值都默认是true,但是如果你是用Object.defineProperty()给对象创建的属性,configurable、enumerable和writable特性的默认值都是false

               当然了,一个一个属性修改太麻烦了,于是还有个Object.defineProperties(),能同时修改多个属性:

     1 Object.defineProperties(person,{
     2        name: {
     3              writable:true,
     4              value:"long"
     5               },
     6        age: {
     7               writable:true,
     8               value:25
     9               },
    10         job: {
    11               writable:true,
    12               value:"gongren"
    13               }
    14        });
    15           

           2.2 访问器属性:跟数据属性一样,它也有4个特性:configurable,enumerable,get,set

            前两个特性不用赘述,后两个get和set分别是读取/写入属性时调用的函数,默认值都是underfined

            访问器属性没法直接定义,必须使用Object.defineProperty()来定义,举个栗子:

     1 var book={  _year:2017,
     2                   edition:1
     3                 };
     4 Object.defineProperty(book,"year",{
     5              get: function(){
     6                  return this._year;
     7                  },
     8              set: function(newValue){
     9                       if(newValue>2017){
    10                      this._year=newValue;
    11                      this.edition+=newValue-2017;
    12                     }
    13                  }
    14          });
    15 
    16 book.year=2018;
    17 console.log(book.edition);    //2

             这里就是比较有意思的地方,我们加入的属性“year”,在加入时并没有赋值,而是定义了get和set函数,用来处理在外部赋给year的值,我们在外面赋值2018,然后给year定义的get和set函数就利用2018来修改_year和edition的值。这就是使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化

              看到这里,可能有的同学有个问题:不是说用Object.defineProperty()方法定义的属性的特征值包括writable都是false吗?为什么“book.year=2018”还能生效呢?

           其实原因是,你用Object.getOwnPropertyDescriptor()取得特征值查看会发现,它的writable显示为“underfined”,所以可以这样想,year并不是和_year,edition一样的属性,是个定义了用来修改其他属性的属性,地位相当于后勤部长。

        

          

                                                                                                                                                                

                                                                                                                                                                

                                                                                                                                                              

            

              

             

  • 相关阅读:
    Qt编写控件属性设计器12-用户属性
    C#中通过三边长判断三角形类型(三角形测试用例)
    C#中通过Selenium定位<a>标签的问题
    SharePoint自动化系列——Manage "Site Subscriptions" using PowerShell
    SharePoint API测试系列——Records.BypassLocks测试
    SharePoint API测试系列——对Recorded Item做OM操作(委托的妙用)
    放松时刻——C#分割字符串
    链表——PowerShell版
    栈——PowerShell版
    队列——PowerShell版
  • 原文地址:https://www.cnblogs.com/sleipnir-0430/p/8543770.html
Copyright © 2011-2022 走看看