JS中禁止对象属性扩展、密封对象、冻结对象

来源:互联网 发布:js只执行一次方法 编辑:程序博客网 时间:2024/04/28 01:11

几种特殊定义对象

  • 几种特殊定义对象
    • 禁止对象属性扩展密封对象冻结对象
      • 对象常量属性
      • 禁止属性扩展
      • 密封对象
      • 冻结对象

禁止对象属性扩展、密封对象、冻结对象

对象常量属性

  • 概念:将属性的writable和configurable设置为false;

    //将属性的writable和configurable设置为falsevar damu={};Object.defineProperty(damu,"wife",{    value:"fbb"})Object.defineProperty(damu,"wife",{    value:"fbb2"});//无法更改,无法删除。可以添加//console.log(damu);//报错,Cannot redefine propertydamu.wife="damu"delete damu.wife;console.log(damu);//{wife: "fbb"}damu.wife2="fbb2";console.log(damu);//{wife2: "fbb2", wife: "fbb"}

禁止属性扩展

  • 概念
    • 如果一个对象可以添加新的属性,则这个对象是可扩展的,让这个对象变的不可扩展,也就是不能再有新的属性;
    • 由于属性描述符是对属性的管理,所以想禁止对象扩展,不能使用属性描述符来控制,而是需要调用其他的对象的方法。
  • 两种有关对象属性扩展的对象方法:

    • Object.isExtensible 方法:Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

      • 语法: Object.isExtensible(obj)
      • 参数: obj 需要检测的对象;
      • 默认情况下,创建的对象默认是可扩展
        //新对象默认是可扩展的无论何种方式创建的对象//使用的是字面量方式var empty = {a:1};console.log(Object.isExtensible(empty) === true);//true//等价于 使用属性描述符empty = Object.create({},{    "a":{        value : 1,        configurable : true,//可配置        enumerable : true,//可枚举        writable : true//可写    }});console.log(Object.isExtensible(empty) === true);//true//创建属性的方式var damu={};Object.defineProperty(damu,"wife",{    value:"fbb"})console.log(Object.isExtensible(damu) === true);//true
    • Object.preventExtensions 方法:方法让一个对象变的不可扩展,也就是永远不能再添加新的属性,并且返回原对象。

      • 语法:Object.preventExtensions(obj);
      • 参数:obj 将要变得不可扩展的对象;

        var damu = {};Object.defineProperty(damu,'wife',{    value:'lbb'});console.log(damu);//{wife: "lbb"}Object.preventExtensions(damu);//  damu.age = 18;//  console.log(damu);//{wife: "lbb"} (function fail(){       "use strict";       damu.d = "4";//throws a TypeError   })();console.log(damu);//Cannot add property d, object is not extensible
      • 描述:

        • 如果一个对象可以添加新的属性,则这个对象是可扩展的。preventExtensions 可以让这个对象变的不可扩展,也就是不能再有新的属性。
        • 需要注意的是不可扩展的对象的属性通常仍然可以被删除。
        • 尝试给一个不可扩展对象添加新属性的操作将会失败,不过可能是静默失败(默认情况),也可能会抛出 TypeError 异常(严格模式)。
        • 注意:Object.preventExtensions 只能阻止一个对象不能再添加新的自身属性,仍然可以为该对象的原型添加属性。

密封对象

  • 概念:
    • 密封对象是指那些不可扩展的,且所有自身属性都不可配置的(non-configurable)对象。
    • 或者可以说,密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。
  • 可用方法:在禁止对象扩展(Object.preventExtensions(obj);的基础上把现有属性的configurable都调整为false;

    //设置对象即使不可扩展又不可配置var damu = {};Object.defineProperty(damu,'wife',{    value:'lbb'    //此时默认的configurable和writable都为false的。});console.log(damu);//{wife: "lbb"}Object.preventExtensions(damu);damu.age = 18;delete damu.wife;//{wife: "lbb"}console.log(damu);//{wife: "lbb"};//证明不可配置、不可扩展。但是这种设置的过程很麻烦,尝试使用简单的对象方法来设置密封对象。
  • 两种有关密封属性的方法

    • Object.isSealed 方法:方法判断一个对象是否是密封的(sealed)。

      • 语法 :Object.isSealed(obj);
      • 参数:obj 将要检测的对象;
      • 描述:如果这个对象是密封的,则返回 true,否则返回 false。
        //使用Object.preventExtensions设置为不可扩展,再设置不可配置,则成为密封了。var damu = {};Object.defineProperty(damu,'wife',{    value:'lbb'    //此时默认的configurable和writable都为false的。});Object.preventExtensions(damu);console.log(Object.isSealed(damu));//true
    • Object.seal() 方法:可以让一个对象密封,并返回被密封后的对象。

      • 语法:Object.seal(obj)
      • 参数:obj 将要被密封的对象

        var damu = {};Object.defineProperty(damu,'wife',{    value:'lbb'    //此时默认的configurable和writable都为false的。});console.log(Object.getOwnPropertyDescriptor(damu,"wife"));//{value: "lbb", writable: false, enumerable: false, configurable: false}Object.seal(damu);console.log(Object.isSealed(damu));//true//静默失败damu.d = 'd';delete damu.wife;console.log(damu);//{wife: "lbb"}console.log(Object.getOwnPropertyDescriptor(damu,"wife"))
      • 描述:

        • 通常情况下,一个对象是可扩展的(可以添加新的属性)。
        • 密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。
        • 属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。
        • 尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError 异常(严格模式)。
        • 不会影响从原型链上继承的属性。但 proto ( ) 属性的值也会不能修改。

冻结对象

  • 概念:
    • 一个对象是冻结的(frozen)是指它不可扩展,所有属性都是不可配置的(non-configurable),且所有数据属性(data properties,指那些没有取值器getter或赋值器setter的属性)都是不可写的(non-writable);
    • 或则说 冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。也就是说,这个对象永远是不可变的;
  • 可用方法:在密封对象(Object.seal(obj))的基础上把现有属性的writable都调整为false:

    //在密封对象(Object.seal(obj))的基础上把现有属性的writable都调整为falsevar damu = {};Object.defineProperty(damu,'wife',{    value:'lbb',    //writable:true});//密封Object.seal(damu);//防扩展Object.preventExtensions(damu);damu.age = 18;delete damu.wife;damu.wife = 'zdy';console.log(damu);//{wife: "lbb"};
  • 两种有关密封属性的方法

    • Object.isFrozen 方法:方法判断一个对象是否被冻结(frozen)。

      • 语法: Object.isFrozen(obj)
      • 参数:obj 被检测的对象
    • Object.freeze() 方法:可以冻结一个对象。

      • 语法:Object.freeze(obj);
      • 参数:obj 将要被冻结的对象;

        var damu = {wife:'lbb'};console.log(Object.getOwnPropertyDescriptor(damu,"wife"));//{value: "lbb", writable: true, enumerable: true, configurable: true}//冻结对象Object.freeze(damu);console.log(Object.getOwnPropertyDescriptor(damu,"wife"));//{value: "lbb", writable: false, enumerable: true, configurable: false}damu.age = 18;delete damu.wife;damu.wife = 'zdy';console.log(damu);//{wife: "lbb"}
      • 描述:

        • 冻结对象的所有自身属性都不可能以任何方式被修改。
        • 任何尝试修改该对象的操作都会失败,可能是静默失败,也可能会抛出异常(严格模式中)。
        • 数据属性的值不可更改,访问器属性(有getter和setter)也同样(但由于是函数调用,给人的错觉是还是可以修改这个属性)。
        • 如果一个属性的值是个对象,则这个对象中的属性是可以修改的,除非它也是个冻结对象。
          //浅不变形var damu={wifes:{wife1:"fbb",wife2:"lyf",wife3:"zdy"}};damu.wifes.wife1="lbb";console.log(damu);//wifes:{wife1: "lbb", wife2: "lyf", wife3: "zdy"}//深层次冻结var damu={    wifes:{wife1:"fbb",wife2:"lyf",wife3:"zdy"}};Object.freeze(damu);//遍历调用冻结方法,将对象属性内的对象全部冻结。for(item in damu){    Object.freeze(damu[item]);}damu.wifes.wife1="lbb";console.log(damu);//wifes:{wife1: "fbb", wife2: "lyf", wife3: "zdy"}