1. 程式人生 > 其它 >關於js的Object.defineProperty

關於js的Object.defineProperty

好久不見,甚是想念
今天你敲程式碼了嘛!?今天我們來聊聊js中的 Object.defineProperty方法,這個可是困擾了我半天,廢話不多說,讓我們來看看吧
首先先上一個連結https://developer.mozilla.org/zh-cn/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
MDN上面寫的挺詳細的,我也就是總結一些比較重要的方法

var obj ={}
object.defineProperty(obj,'a',{
     value:4
})
console.log(obj.a)

// 4

那麼上面這段程式碼與下面有什麼區別呢!

var obj ={}
obj.a =4 
console.log(obj.a)

//4

然後經過一番的研究
當你修改物件的a屬性時就會發現區別

var obj ={}
object.defineProperty(obj,'a',{
     value:4
})
console.log(obj.a)
obj.a = 6
console.log(obj.a)

//4
//4

這是因為Object.defineProperty裡面有個隱藏屬性叫writable
預設為 false
當且僅當該屬性的 writable 鍵值為 true 時,屬性的值,也就是上面的 value,才能被賦值運算子改變。

還有一些比較隱藏的方法,讓我們來看一下

enumerable 是否可以被列舉
預設為 false
當且僅當該屬性的 enumerable 鍵值為 true 時,該屬性才會出現在物件的列舉屬性中。

var obj ={}
Object.defineProperty(obj,'a',{
     value:6,
     enumerable:true
})
Object.defineProperty(obj,'b',{
     value:7,
     enumerable:false 
})
for(let n in obj){
   console.log(n)
}
//a

get 方法
屬性的 getter 函式,如果沒有 getter,則為 undefined

。當訪問該屬性時,會呼叫此函式。執行時不傳入任何引數,但是會傳入 this 物件(由於繼承關係,這裡的this並不一定是定義該屬性的物件)。該函式的返回值會被用作屬性的值。
預設為 [undefined]

Object.defineProperty(obj,'a',{
    get(){
      console.log('你正在試圖訪問obj的a屬性')
      return 4
    }
}

Object.defineProperty(obj,'a',{
    value:4
}
//console.log(obj.a)
//4
因此get方法 和 直接賦值 的效果是一樣的

但是要注意一件事就是 賦值和get、set方法不能同時使用

var obj ={}
Object.defineProperty(obj,'a',{
    value:7,
    get(){
      console.log('你正在試圖訪問obj的a屬性')
      return 4
    }
})
console.log(obj.a)

在這裡插入圖片描述
set方法
屬性的 setter 函式,如果沒有 setter,則為 undefined。當屬性值被修改時,會呼叫此函式。該方法接受一個引數(也就是被賦予的新值),會傳入賦值時的 this 物件。
預設為 **預設為 [undefined]

var obj = {}
Object.defineProperty(obj,'a',{
    get(){
      return 8
    },
    set(n){
        console.log('你正在試圖改變obj的a屬性',n)
    }
})
obj.a =10
console.log(obj.a)
//8

雖然set方法攔截到了 但是並沒有改變obj.a的值
這是因為
get並沒有返回 新設定的值
因此只要訪問obj.a 就會呼叫get方法,return 8

那麼如何解決這個問題呢!
引入一個變數

var obj = {}

var temp;
Object.defineProperty(obj,'a',{
    get(){
      console.log('你正在試圖訪問obj的a屬性')
      return temp
    },
    set(n){
        console.log('你正在試圖改變obj的a屬性',n)
        temp = n
    }
})
obj.a =10
console.log(obj.a)

//10

我們還可以將它封裝一下

var obj = {}

function defineReactive(data,key,val){

Object.defineProperty(data,key,{
    get(){
      console.log('你正在試圖訪問obj的a屬性')
      return val
    },
    set(n){
        console.log('你正在試圖改變obj的a屬性',n)
        if(val === n){
           return
        }
        val = n
    }
})
}

defineReactive(obj,'a',10)

obj.a =70;
console.log(obj.a)
//70