ES中保护对象的措施总结

 

 

必要性:  JS中的对象可随意修改属性值,可随意添加删除属性,太乱,数据安全得不到保障。

如何保护:

    保护属性: 保护对属性值的修改

      对象属性分为:

        命名属性: 可直接用.访问到的属性

          数据属性: 直接存储属性值的属性

            如何保护: 四大特性:

              value: 实际存储属性值

              writable: 控制属性是否可修改

              enumerable: 控制属性是否可被遍历

               仅控制遍历,无法控制用.访问

              configurable: 控制是否可删除属性

                       控制是否可修改其他两个特性

            强调: configurable经常作为前两个属性的双保险,且一旦设为false,不可逆!

            如果查看四大特性:

  

 Object.getOwnPropertyDescriptor(obj,"属性名")

            如何修改四大特性:

              Object.defineProperty(obj,"属性名",{

                 特性:值,

                 特性:值,

                    ... ...

})

问题: defineProperty一次只能修改一个属性

解决: 同时修改多个属性:

Object.defineProperties(obj,{

     属性名:{ 要修改的特性 },

  属性名:{ 要修改的特性 },

      ... : ...

})

 

          问题: 无法使用自定义逻辑保护属性

 

 解决:

          访问器属性: 不直接存储属性值

                     仅提供对其他数据属性的保护

          何时: 只要用自定义逻辑保护属性时

          如何: 2步:

            1. 定义一个隐藏的数据属性实际存储属性值

            2. 添加访问器属性保护隐藏的数据属性:

              Object.defineProperty(obj,"属性名",{

               get(){//在试图获取属性值时自动调用

                //返回受保护的数据属性值

},

set(val){//在试图修改属性值时自动调用

 //参数val会自动获得要修改的新值

 //如果验证val符合规则

                   //才将val赋值给受保护的属性

 //否则

    //报错!

},

enumerable:true,

configurable:false

})

        如何使用访问器属性: 同普通属性用法完全一致

          其中赋值时,自动调用set,取值时自动调get

        内部属性: 不能用.直接访问的隐藏属性

           __proto__

    防篡改: 保护对对象结构的修改

      3个级别:

      1. 防扩展: 禁止添加新属性

        Object.preventExtensions(obj)

        原理: 每个obj内部都有一个隐藏属性:

             Extensible,默认为true

        preventExtensions将obj的Extensible改为false

      2. 密封: 在防扩展基础上,进一步禁止删除现有属性

        Object.seal(obj)

        原理: 修改obj的Extensible为false

              将所有属性的configurable都改为false

      3. 冻结: 在密封基础上禁止修改任何值

        Object.freeze(obj)

        原理: 修改obj的Extensible为false

              将所有属性的configurable都改为false

              还将所有属性的writable都改为false

 

Object.create(): 可直接用一个父对象创建一个子对象。

  如何: var child=Object.create(father,{

         自有属性:{

           value:值,

           writable:true,

           enumerable:true,

           configurable:true,

},

... : {

  ...

}

});

  强调: 只要添加到对象中的属性,四大特性默认为false,必须显式写为true。

  

 

例子:

 "use strict";

  var emp={
    id:1001,     //禁止修改
    ename:"eric",//禁止删除
    salary:12000 //禁止遍历
  }
  //禁止修改id的值
  //禁止删除ename:
  //禁止遍历salary:
  Object.defineProperties(emp,{
    id:{
      writable:false,
      configurable:false
    },
    ename:{configurable:false},
    salary:{
      enumerable:false,
      configurable:false
    }
  });
//  Object.defineProperty(emp,"id",{
//    writable:false,
//    configurable:false//不可逆
//  });
//  Object.defineProperty(emp,"ename",{
//    configurable:false//不可逆
//  });
//  Object.defineProperty(emp,"salary",{
//    enumerable:false,
//    configurable:false//不可逆
//  });


//  Object.defineProperty(emp,"id",{
//    writable:true,
//    configurable:true
//  });
//  emp.id=1002;

//  delete emp.ename;
  console.dir(emp);
  for(var key in emp){
    console.log(key+":"+emp[key]);
  }
  console.log(emp.salary);
  console.log(
    Object.getOwnPropertyDescriptor(
      emp,"id"//ename//salary
    )
  );

 

"use strict";
  var config={
    IP:"192.168.0.100",
    PORT:27017,
    USER:"admin",
    PWD:"123456"
  }
  Object.freeze(config);
  //config.PORT=8080;
  delete config.PORT;

 

var emp={id:1001,ename:"eric",_age:23};
  Object.defineProperty(emp,"_age",{
    enumerable:false,
    configurable:false
  });
  //要求:age必须介于18~65之间
  Object.defineProperty(emp,"age",{
    get(){
      console.log("自动调用get");
      return this._age
    },
    set(val){
      console.log("自动调用set");
      if(val>=18&&val<=65)
        this._age=val;
      else
        throw new RangeError("年龄必须介于18~65之间")
    },
    enumerable:true,
    configurable:false
  });
  //访问器属性的用法和普通属性完全一致
  emp.age++;
  console.dir(emp);
  emp.age=-2;

 

  var father={
    bal:10000000000,
    car:"infiniti"
  }
  var hmm=Object.create(father,{
    phone:{
      value:"IPhone 8 Plus",
      writable:true,
      enumerable:true,
      configurable:true
    },
    bao:{
      value:"LV",
      writable:true,
      enumerable:true,
      configurable:true
    }
  });
  console.dir(hmm);

 

posted @ 2017-04-25 20:19  快乐的咸鱼  阅读(415)  评论(0编辑  收藏  举报