defineProperty詳解

擱置了幾天我仍是決定再次重寫!html

下邊咱們來具體聊聊先從defineProperty開始提及vue

defineproperty

//defineproperty 有個定義object屬性的功能,應該沒幾我的用,由於相對於obj.a = 1這種方式簡直不能再難用。

//一般咱們定義obj屬性
let obj = {
      a:1
}
obj.b = 2
obj['c'] = 3
console.log(obj)//{a: 1, b: 2,c: 3}  

Object.defineProperty(obj,'d',{
      value: 4
})

console.log(obj)//{a: 1, b: 2,c: 3,d:4}  //defineProperty能夠定義對象屬性

//也能夠修改
Object.defineProperty(obj,'b',{
      value: 5
})
console.log(obj)//{a: 1, b: 5, c: 3, d: 4}

//對你沒看錯defineProperty有這個功能,不知能夠定義新的屬性還能夠修改,這麼逆天難用的功能爲何還要造出來?說這個有什麼用?別急往下看segmentfault

descriptor詳解

defineProperty 接收三個參數
  • object (必須有 操做的對象自己 這個很容易理解不傳它操做誰?)
  • propertyname (必須有 屬性名 添加修改屬性得有屬性名)
  • descriptor (必須有 官方說的我理解不了,我理解的是 屬性描述
    一、簡單點就是 設置屬性的值value,
    二、是否可操做屬性值 writable,
    三、是否可修改配置configurable若是值爲false descriptor內的屬性都不可操做
    四、是否可枚舉enumerablespa

    *descriptor內配置無關緊要,value默認undefind,其他默認爲false

先作了介紹咱們下邊來證實下雙向綁定

writable
//栗子仍是這個栗子
        let obj = {
            a: 1
        }
        Object.defineProperty(obj, 'b', {
            value: 2,
            writable: false//不可修改
        })

        obj.b = 3
        console.log(obj) //{a: 1, b: 2} 還真是不能夠
        //難道是姿式不對?
        Object.defineProperty(obj, 'b', {
            value: 3
        })
        console.log(obj)//{a: 1, b: 2} 同樣的效果 和姿式無關。
configurable

//configurable 這個比較厲害 控制descriptor內屬性都不可改變不知道是否是真的code

//仍是這個栗子htm

let obj = {
            a: 1
        }
        Object.defineProperty(obj, 'b', {
            value: 2,
            //writable: false//不可修改
            configurable: false
        })
        obj.b = 5
        console.log(obj)//[1,2]
enumerable

對否可枚舉對象

let obj = {
            a: 1
        }
        Object.defineProperty(obj, 'b', {
            value: 2,
            //writable: false//不可修改
            //configurable: false
            enumerable: false
        })
        //obj.b = 5
        console.log(Object.keys(obj))//["a"]

接了下來講到重點: set和get這也是vue3.0前observe的實現原理ip

let obj = {
            a: 1
        }

        let newValue = 45
        Object.defineProperty(obj, 'b', {
            get(value) {
                console.log('獲取')
                return value
            },
            set(newValue) {
                console.log('設置')
                value = newValue
            }
        })
        obj.b = 6 //設置

        obj.b //獲取

知道用法了咱們來實踐一下rem

//html
      <div></div>
      <input type="text">
      //js
      //相似 vue的data
        let obj = {}

        /*
         *obj      要劫持的對象
         *name     要劫持對象的屬性
         *callback 劫持之後的操做
         */
        function watch(obj, name, callback) {
            let value = obj.name
            Object.defineProperty(obj, name, {
                set(msg) {
                    // 觸發setter給obj賦值
                    value = msg
                        //執行劫持後的操做
                    callback(value)
                },
                get() {
                    //返回獲取屬性值
                    return value
                }
            })
        }

        //
        function doSomething(value) {
            document.querySelector('div').innerHTML = value
            document.querySelector('input').value = value
        }
        //監聽input變化 
        //能夠參考全兼容版:https://segmentfault.com/a/1190000017524278
        document.querySelector('input').addEventListener('input', (e) => {
            obj['msg'] = e.target.value
        })

        watch(obj, 'msg', doSomething)

效果:
一、input輸入改變div內容
image.png
二、改變obj name屬性
image.png
三、獲取改變後的obj屬性name
image.png

簡單的用defineProperty實現了雙向綁定

歡迎吐槽!您的點贊是我繼續的動力!謝謝

相關文章
相關標籤/搜索