Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象 vue
Object.defineProperty(obj, prop, descriptor)
被傳遞給函數的對象數組
詳細語法介紹請參考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyapp
本身簡單寫了個示例,方便理解Object.defineProperty函數
var data = { name: "jade", age: 18, } Object.keys(data).forEach(key=>{ var vl = data[key]; Object.defineProperty(data,key,{ get(){ console.log(key + "...get..."); return vl; }, set(value){ console.log(key + "...set... value is " + value); vl = value; } }); }) console.log("age:"+data.age); data.age = 20; data.name = "jake"; console.log("age:"+data.age);
在讀取屬性或者給屬性賦值時,會進入get和set方法,進而能夠派發出事件,通知監聽者。spa
Proxy雙向綁定
Proxy在ES2015規範中被正式發佈,它在目標對象以前架設一層「攔截」,外界對該對象的訪問,都必須先經過這層攔截,所以提供了一種機制,能夠對外界的訪問進行過濾和改寫,咱們能夠這樣認爲,Proxy是Object.defineProperty
的全方位增強版code
Object.defineProperty
只能遍歷對象屬性直接修改。攔截對象:對象
<input id="input" type="text"/> <p id="p"></p> <script> const input = document.getElementById('input'); const p = document.getElementById('p'); const obj = {}; const newObj = new Proxy(obj, { get: function(target, key, receiver) { console.log(`getting ${key}!`); return Reflect.get(target, key, receiver); }, set: function(target, key, value, receiver) { console.log(target, key, value, receiver); if (key === 'text') { input.value = value; p.innerHTML = value; } return Reflect.set(target, key, value, receiver); }, }); input.addEventListener('keyup', function(e) { newObj.text = e.target.value; }); </script>
攔截數組:blog
<ul id="list"> </ul> <input id="btn" value="test" type="button"/> <script> const list = document.getElementById('list'); const btn = document.getElementById('btn'); // 渲染列表 const Render = { // 初始化 init: function(arr) { const fragment = document.createDocumentFragment(); for (let i = 0; i < arr.length; i++) { const li = document.createElement('li'); li.textContent = arr[i]; fragment.appendChild(li); } list.appendChild(fragment); }, // 咱們只考慮了增長的狀況,僅做爲示例 change: function(val) { const li = document.createElement('li'); li.textContent = val; list.appendChild(li); }, }; // 初始數組 const arr = [1, 2, 3, 4]; // 監聽數組 const newArr = new Proxy(arr, { get: function(target, key, receiver) { console.log(key); return Reflect.get(target, key, receiver); }, set: function(target, key, value, receiver) { console.log(target, key, value, receiver); if (key !== 'length') { Render.change(value); } return Reflect.set(target, key, value, receiver); }, }); // 初始化 window.onload = function() { Render.init(arr); } // push數字 btn.addEventListener('click', function() { newArr.push(6); }); </script>