美文网首页深究JavaScript你不知道的JavaScript
《你不知道的JavaScript》之对象二

《你不知道的JavaScript》之对象二

作者: 弦五 | 来源:发表于2018-04-08 08:09 被阅读9次

    接下来继续讨论对象的主要内容

    一、属性描述符

    对于对象中的属性,我们一般都是直接调用,但是属性本身又有什么特性呢,该怎么去描述?属性描述符就扮演了这样一种角色。属性描述符是在ES5以后才有的,看下面的代码。


      var myobjec = {

          a:2,

          };

          var descriptor = Object.getOwnPropertyDescriptor(myobjec,"a")

          console.log(descriptor);

          //返回的结果为一个object对象:

    {

    configurable:true

    enumerable:true

    value:2

    writable:true

    }


    返回的对象中包含了四个描述符:configurable(可配置)、enumerable(可枚举)、value(值)、writable(可写入)。

    这些属性描述符可以修改吗?当然,我们可以用Object.defineProperty(...)来添加一个新的属性或是修改一个已有属性。

    1)writable

    决定了属性是否可以被修改。如果将其设置为false,那么对应的value是不能被修改的。



          var myobject = {

              a:2,

          };

          Object.defineProperty(myobject,"a",{

          writable:false,

          configurable:true,

          enumerable:true,

          value:2

          })

          myobject.a = 4;

          console.log(myobject.a);//2


    2)configurable(可配置)

    只要是可配置,就可以用defineProperty来修改属性描述符。


          var myobject = {

             a:2,

          };

          myobject.a = 3;

          console.log(myobject.a ); //3

          Object.defineProperty(myobject,"a",{

          writable:true,

          configurable:false,

          enumerable:true,

          value:4

          });

          console.log(myobject.a);//4

          myobject.a = 5;

          console.log(myobject.a);//5

          Object.defineProperty(myobject,"a",{

          writable:false,

          configurable:false,

          enumerable:true,

          value:6

          });  //Uncaught TypeError


    如果将configurable设置为false后,再去配置就会报“未捕获类型”错误。

    3)enumerable(可枚举)

    通常属性的这个描述符默认为true,比如在for循环中,便可以枚举此属性。如果你在循环遍历中不想让该属性出现,那么将它的configurable设置为false即可。

    二、属性不可变性

    很多时候,你都希望属性是不可变的,在ES5中可以通过很多方法来实现:

    1)将属性描述符writable和configurable设置为false即可;

    2)禁用:可以使用Object.preventExtensions(..)来禁止一个对象添加新属性并且保留已有属性;


        var myobject = {

           a:2,

          };

          Object.preventExtensions(myobject);

          myobject.b = 3;

          console.log(myobject.b);//undefined


    3)密封:Object.seal(...),调用这个方法时会调用preventExtention,并把所有的属性都标记为configurable:false,什么意思呢?就是说调用密封方法后,任何为对象添加、删除新属性的操作都是不允许的,但是属性值可以被修改,

    4)冻结:Object.freeze(),这个方法会调用seal方法,同时将writable标记为false,所以这个不能修改的级别就比较高了,不仅不能添加删除,而且也不能修改了。

    三、[[get]] 和  [[put]]操作

    在访问对象属性时,表面上我们只是获取了属性值这么简单,其实是在对象上进行了[[get]]操作,对象的内置方法 [[get]] 会查找对象中是否存在改属性,如果存在返回属性对应的值,如果不存在,其实会执行另外一种行为,就是查找[[ prototype ]]链,也就是原型链,这个后面会讲到。

    如果无论如何都找不到这个属性,那么就会返回undefined。


          var myobject = {

          a:2,

          };

          console.log(myobject.b);//undefined

          console.log(c); //Uncaught ReferenceError: c is not defined


    注意属性访问和变量访问的区别,如果对象中不存在属性,那么返回undefined,而变量在当前作用域中不存在的话,就会抛出 referenceError错误。原因就是属性访问调用了对象内置操作[[get]]。

    对于[[put]]操作,你可能认为一般是在属性赋值时被调用,但实际情况并不完全这样,触发的原因有很多。不过首先要看对象中是否存在这个属性,如果存在的话,那么一般会检查下面的内容:

    1)属性是否是属性描述符,如果是并且存在setter,就会调用setter,什么是setter呢,接下来会讲到;

    2)属性描述符writable是否是false,如果是的话,在非严格模式下静默失败,在严格模式下抛出typeError错误;

    3)如果上述情况都不是,那么将该值设置为属性值。

    如果对象中不存在这个属性,那么[[put]]操作会查找原型链,这个后面会讲到。

    四、getter 和  setter 操作

    ES5中的getter和setter操作会改变对象属性的默认操作,但是只能应用在单个属性上而不是整个对象上。有的同学会问到,平时好像没有看到这两个方法啊?这是因为它们都是隐藏函数,都是在属性的获取和赋值时默默的调用的。

    看下面这段代码:


    var myobject = {

          get a(){

          return 2;

          }

          };

          console.log(myobject.a);//2

          Object.defineProperty(myobject,'b',{

          get:function(){

          return this.a*2;

          }

          })

          console.log(myobject.b);//4


    上面两种定义getter的方法都使得在访问属性时调用了getter。不过既然有了getter,那么setter也不能少对吧。


    var myobject = {

          get a(){

               return this._a;

          },

          set a(val){ 

                this._a = val*2;

               }

          };   

          myobject.a = 2;

          console.log(myobject.a); //4


    到此为止,同上篇文章一起对对象的一些基本属性做了系列的讨论和讲解,相信勤奋好学的同学们有了更深刻的认识吧。

    相关文章

      网友评论

        本文标题:《你不知道的JavaScript》之对象二

        本文链接:https://www.haomeiwen.com/subject/ccsbcftx.html