• 《JS权威指南学习总结--6.7属性的特性》


    内容要点:

    一.ES5中查询和设置属性的API

          1.可以通过这些API给原型对象添加方法,并将它们设置成不可枚举的,这让它们看起来更像内置方法。

          2.可以通过这些API给对象定义不能修改或删除的属性,借此 "锁定" 这个对象。

          3.数据属性的4个特性: 值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)。

          4.存取器属性不具有值特性和可写性,它们的可写性是由setter方法存在与否决定的。因此存取器属性的4个特性是:读取(get)、写入(set)、可枚举性(numberable)和可配置性(configurable)。

          其中writable、enumerable和configurable都是布尔值,当然,get属性和set属性是函数值。

    二.Object.getOwnPropertyDescriptor()

          1.通过调用Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符:

          例如:

             //返回{ value : 1,writable : true,enumerable:true,configurable:true }

             Object.getOwnPropertyDescriptor({x:1},"x");

            //查询上文中定义的random对象的octet属性

            //返回{get:/*func*/,set:undefined,enumerable:true,configurable:true}

           Object.getOwmPropertyDescriptor(random,"octet");

           //对于继承属性和不存在的属性,返回undefined

            Object.getOwnPropertyDescriptor({},"x"); //undefined,没有这个属性

            Object.getOwnPropertyDescriptor({},"toString"); //undefined,继承属性

            Object.getOwnPropertyDescriptor()只能得到自有属性的描述符。要想获得继承属性的特性,需要遍历原型链

    三.Object.definePeoperty()

           传入要修改的对象,要创建或修改的属性的名称以及属性描述符对象。

           var o = {}; //创建一个空对象

           //添加一个不可枚举的数据属性x,并赋值为1

            Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true});

          //属性是存在的,但不可枚举

            o.x; //=>1

             Object.keys(o) //=>[]

          //现在对属性x做修改,让它变为只读

            Object.defineProperty(o,"x",{writable:false});

         //试图更改这个属性的值

           o.x = 2; //操作失败但不报错,而在严格模式中抛出类型错误异常

           o.x=1;

          //属性依然是可配置的,因此可以通过这种方式对它进行修改

            Object.defineProperty(o,"x",{value:2});

            o.x //=>2

          //现在将x从数据属性修改为存取器属性

           Object.defineProperty(o,"x",{get:function(){return 0;}});

           o.x //=>0

          传入Object.defineProperty()的属性描述符对象不必包含所有4个特性。对于新创建的属性来说,默认的特性值是false或undefined。对于修改的已有属性来说,默认的特性值没有做任何修改。注意:这个方法要么修改已有属性要么新建自有属性,但不能修改继承属性。

    四.Object.defineProperties()

           同时修改或创建多个属性。第一个参数是要修改的对象,第二个参数是一个映射表,它包含要新建或修改的属性的名称,以及它们的属性描述符

           例如:

           var p = Object.defineProperties({},{

                  x:{value:1,writable:true,enumerable:true,configurable:true},

                  y:{value:1,writable:true,enumerable:true,configurable:true},

                  r:{  

                        get:function(){ return Math.sqrt(this.x*this.x+this.y*this.y) },

                         enumerable:true,

                         configurable:true

                      }

             });

             这段代码从一个空对象开始,然后给它添加了两个数据属性和一个只读存储器属性,最终Object.defineProperties()返回修改后的对象

    五.

          对于那些不允许创建或修改的属性来说,如果用Object.defineProperty()和Object.defineProperties()返回修改后的对象(新建或修改)就会抛出类型错误异常,

          比如,给一个不可扩展的对象新增属性就会抛出类型错误异常。造成这些方法抛出类型错误异常的其他原因则和特性本身相关。

          可写性控制着特性的修改,可配置性控制着对其他特性的(包括属性是否可以删除)的修改。然而规则远不止这么简单:

          例如,如果属性是可配置的话,则可以修改不可写属性的值。同样,如果属性是不可配置的,仍然可以将可写属性修改为不可写属性。

          下面是完整的规则,任何对Object.defineProperty()或Object.defineProperties()违反规则的使用都会抛出类型错误异常

                1.如果对象是不可扩展的,则可以编辑已有的自有属性,但不能给它添加新属性

                2.如果属性是不可配置的,则不能修改它的可配置性和可枚举性。

                3.如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性

                4.如果数据属性是不可配置的,则不能将它转换为存取器属性

                5.如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但可以从true修改为false。

                6.如果数据属性是不可配置的且不可写的,则不能修改它的值。然而可配置但不可写属性的值是可以修改的(实际上是先将它标记为可写的,然后修改它的值,最后转换为不可写的)

    六.

        上节中实现了extend()函数,这个函数把一个对象的属性复制到另一个对象中。这个函数只是简单地复制属性名和值,没有复制属性的特性,而且也没有复制存取器属性的getter和setter方法,只是将它们简单地转换为静态的数据属性。

         下例给出了改进的extend(),它使用Object.getOwnPropertyDescriptor()和Object.defineProperty()对属性的所有特性进行复制。新的extend()作为不可枚举属性添加到Object.prototype中,因此它是Object上定义的新方法,而不是独立的函数。

          /*给Object.prototype添加一个不可枚举的extend()方法 

           *这个方法继承自调用它的对象,将作为参数传入的对象的属性一一复制

           *除了值之外,也复制属性的所有特性,除非在目标对象中存在同名的属性

           *参数对象的所有自有对象(包括不可枚举的属性)也会一一复制      

           */    

           Object.defineProperty(Object.prototype,

              "extend",

              {

                  writable: true,

                  enumerable:false,              //将其定义为不可枚举的

                  configurable:true,

                  value:function(o){            //值就是这个函数

                        //得到所有的自有属性,包括不可枚举属性

                        var names = Object.getOwnPropertyNames(o);

                        //遍历它们

                        for(var i = 0; i <names.length; i++){

                              //如果属性已经存在,则跳过

                              if(names[i] in this) continue;

                             //获得o中的属性的描述符

                             var desc = Object.getOwnPropertyDescriptor(o,names[i]);

                             //用它给this创建一个属性

                             Object.defineProperty(this,names[i],desc);

                      }

                  }

           });

  • 相关阅读:
    数据库概念
    Java编程练习01
    MySQL基本操作
    Tomcat配置
    JDK配置
    云谷分布式端口扫描与代理验证系统(一)简介
    测试平台系列(91) 编写oss管理页面
    测试平台系列(88) 完成邮件通知功能(附赠精美邮件模板)
    测试平台系列(90) 编写oss客户端
    测试平台系列(89) 编写执行测试计划功能
  • 原文地址:https://www.cnblogs.com/hanxuming/p/5795441.html
Copyright © 2020-2023  润新知