不可枚举属性

237 阅读1分钟

一、什么是不可枚举属性

eg:Object.prototype的如下属性都是不能通过Object.keys()或者for循环遍历打印出来的 image.png

  1. 给Object.prototype添加一个属性'c'
  2. 遍历Object.prototype的属性,并打印
    Object.prototype.c = function(){
        console.log('c')
    }
    console.log(Object.keys(Object.prototype)
    for(let key in Object.prototype){
        console.log(key)
    }
    //打印结果:c,并没有打印出toString等属性

二、不可遍历对象的特点,为什么能打印出属性'c',其它的不可以打印

  1. 观察属性的“描述符”对象,使用Object.getOwnPropertyDescriptor(obj,key)输出对应属性的“描述符”对象
  2. 分别打印出'c'和'toString'的描述符对象,发现toString的enumerable:flase
    var desc = Object.getOwnPropertyDescriptor(Object.prototype,'c')
    var desc2 = Object.getOwnPropertyDescriptor(Object.prototype,'toString')
    /*eg:
        value: ƒ ()   =>属性的值
        configurable:  true => 表示属性描述符本身是否可以被修改
        enumerable: true =>可遍历的
        writable: true =>可修改,重新赋值
    */

三、怎么让属性变为不可遍历属性

  1. 通过Object.defineProperty(obj,key,descriptorObj)的方式定义
    Object.defineProperty(Object.prototype,'c',{
        value:'我不是Function',
        configurable:true,
        enumerable:false,
        writable:true
    })
    
    console.log(Object.keys(Object.prototype))  //结果为[]

2.如果将writable:false,表示属性的值不可以被修改

     Object.defineProperty(Object.prototype,'c',{
        value:'我不是Function',
        configurable:true,
        enumerable:true,
        writable:false
    })
    Object.prototype.c = 'hello'
    console.log(Object.prototype.c)  //结果为依然为 “我不是Function”

3.如果将configurable:false,表示该属性的描述符对象不可以被修改

     Object.defineProperty(Object.prototype,'c',{
        value:'我不是Function',
        configurable:false,
        enumerable:true,
        writable:true
     })
     //再次修改C的属性描述符对象
     Object.defineProperty(Object.prototype,'c',{
        value:'我是修改后的C',
        configurable:true,
        enumerable:true,
        writable:true
     })
    console.log(Object.prototype.c)  //报错:Cannot redefine property

报错:

image.png

四、修改自带的不可遍历的属性(toString)

  1. 打印toString的描述符对象,发现它的描述符对象是可以修改的
  2. 修改toString的描述符对象
    var num = 222222 
    var desc2 = Object.getOwnPropertyDescriptor(Object.prototype,'toString')
    console.log(desc2)
     Object.defineProperty(Object.prototype,'toString',{
        //value:'变种toString',
        configurable:true,
        enumerable:true,  //变为可遍历的
        writable:true
     })
     console.log(Object.keys(Object.prototype))  //['toString']
     console.log(num.toString()) // '222222'