Object.defineProperty()

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Object.defineProperty()相关的知识,希望对你有一定的参考价值。

Object.defineProperty( ) 这个方法在开发中并不会使用到,但是呢 这可是vue2响应式的核心 so~ 要不要学一学?

我们先来分析一下这个单词 defineProperty (define:定义、Property:属性)连起来读就是定义属性

既然说到了定义属性 并且呢 是Object上的方法,顾名思义往对象上定义属性呗~  那和我们之间定义属性有什么区别呢?

一、Object.defineProperty( ) 基本使用

在使用方法前呢 先看我们之间是怎么定义的 

    let obj =  a:1
    obj.b = 2

再来看 Object.defineProperty( )怎么定义的

定义格式:

Object.defineProperty(obj,c, )

Object.defineProperty(要定义属性的对象,要定义或修改的属性的名称, 要定义或修改的属性描述符(是一个对象形式))

   let obj =  a:1
   Object.defineProperty(obj,'b',value:2)

在上面的代码中就等于往obj对象里面加了一个属性名b 值是2,但是他们有什么区别呢?

扩展:如果你不写value 会拿到undefined 

 仔细看使用defineproperty定义的属性b是灰色的,这时候我们再看为什么是灰色的呢

我们接着执行下面的代码

  for (const key in obj) 
       console.log(obj[key]);
    

通过执行结果发现 使用obj.defineproperty方法定义的没有被循环出来,换句话说是不可枚举的,如果你想枚举就要加上一个enumerable的属性并且为true

  Object.defineProperty(obj1,'b',value:2,enumerable:true)

 这时候呢,颜色也会从浅色变成深色啦 
 enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。白话:是否可枚举 默认false

再来看第二个特点 执行同样的代码

 obj.b=3

注意哈 使用obj.definedProperty定义的属性没有被修改掉,不是我没写 o ~,官网又说啦 如果你想修改这个值 要加上writable这个属性并且也是true

writable 当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被改变。 默认为 false 白话:是否可修改 默认false

 Object.defineProperty(obj1,'b',value:2,writable:true)

 

 第三个特点 删除对象中定义的属性

delete obj.b

发现又是defineproperty定义的属性没有删掉 如果你想删除这个属性 要加上 configurable值为true

configurable:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false。白话:是否可删除 默认false

    Object.defineProperty(obj1,'b',value:2,configurable:true)

 总结一下:

enumerable:是否可以枚举,默认为false

writable:是否可写入,默认为false

configurable 是否可删除,默认为false

三、getter( ) 和 setter( )

第三个参数 除了可以设置 value、enumerable、writable、configurable属性 还有两个方法 一个是getter( ) 一个是 setter(  )

但是呢写这两个方法之前有一个注意事项:如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常。

这句话意思就是说,如果你有value 或者 writable  又使用了get或set方法 在控制台中会报一个错误

MDN中get的定义 : 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined

意思也就是说呀 只要你访问了当前属性就会执行get这个方法 并且呢要有一个return 代表要把当前属性设置的值是什么,如果你不写return 会得到一个 undefined

 再来看set( )方法

MDN中get的定义 : 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined

意思也就是说呀 只要你修改了当前属性就会执行set这个方法 这个函数里有一个参数 就是想修改的值

响应式小demo

这时候 可以做一个小案例哈  可以不可以根据num的值变化的时候 让obj里的b也跟着发生变化,而当 obj.b修改时num也跟着发送变化呢

let num = 2
    let obj = 
        a: 1
    
    Object.defineProperty(obj, 'b', 
        get()
             console.log('有人访问属性b啦')
            return num
        ,
        set(val)
            console.log('有人修改属性b啦,值是:',val)
            num=val
        
)

以上是关于Object.defineProperty()的主要内容,如果未能解决你的问题,请参考以下文章

关于vue的响应式原理

理解Object.defineProperty()

Object.defineProperty 方法

理解Object.defineProperty方法

242 Object.defineProperty

所有浏览器的 Object.defineProperty?