摘要:主要原因應該是在處理數組響應是會存在缺陷。構造函數其中表示生成一個實例,為需要代理的對象,則是一個對象,定義了各種代理行為。對于滿足條件的屬性以及其他屬性,直接保存報錯報錯攔截的操作,返回一個布爾值。
前言
https://segmentfault.com/a/11...
Vue3.0應該馬上就要發布正式版了。聽說在新版本中,Proxy取代了Object.defineProperty進行雙向綁定。主要原因應該是Object.defineProperty在處理數組響應是會存在缺陷。
let demo = {}; let arr = []; Object.defineProperty(demo, "arr", { get: function() { return arr; }, set: a => { console.log("hear set"); arr = a; }, configurable: true, enumerable: true }); demo.arr = [1, 2, 3, 4]; // => "hear set"; console.log(arr === demo.arr); // => true /* 通過索引修改數組,無法觸發set */ demo.arr[2] = null; // => 沒有輸出hear set。 console.log(arr === demo.arr); // => true /* 通過push,pop,sort等方法同樣無法觸發set */ demo.arr.push("13"); // => 沒有輸出hear set。Proxy
http://es6.ruanyifeng.com/#do...示例
Proxy原意為代理,在實際操作中,可以理解為,在目標數據前增加一個攔截器。通過攔截器,可以實現監聽、修改目標數據。
let obj = new Proxy( {}, { set: function(target, key, receiver) { console.log(`set key ${key}`); return Reflect.set(target, key, receiver); }, get: function(target, key, receiver) { console.log(`get key ${key}`); return Reflect.get(target, key, receiver); } } ); obj.count = 1; // => set key count; obj.count++; // => get key count; // => set key count;構造函數
let obj = new Proxy(target, handler)
其中new Proxy表示生成一個Proxy實例,target為需要代理的對象,handler則是一個對象,定義了各種代理行為。
如果handler為空對象,訪問proxy與訪問target效果相同。
get方法用于攔截某個屬性的讀取操作,可以接受三個參數,依次為目標對象、屬性名和 proxy 實例本身(嚴格地說,是操作行為所針對的對象),其中最后一個參數可選。
var person = { name: "張三" }; var proxy = new Proxy(person, { get: function(target, property) { if (property in target) { return target[property]; } else { throw new ReferenceError("Property "" + property + "" does not exist."); } } }); proxy.name // "張三" proxy.age // 拋出一個錯誤set()
set方法用來攔截某個屬性的賦值操作,可以接受四個參數,依次為目標對象、屬性名、屬性值和 Proxy 實例本身,其中最后一個參數可選。
let validator = { set: function(obj, prop, value) { if (prop === "age") { if (!Number.isInteger(value)) { throw new TypeError("The age is not an integer"); } if (value > 200) { throw new RangeError("The age seems invalid"); } } // 對于滿足條件的 age 屬性以及其他屬性,直接保存 obj[prop] = value; } }; let person = new Proxy({}, validator); person.age = 100; person.age // 100 person.age = "young" // 報錯 person.age = 300 // 報錯has()
has(target, propKey)攔截propKey in proxy的操作,返回一個布爾值。
deleteProperty()deleteProperty(target, propKey)攔截delete proxy[propKey]的操作,返回一個布爾值。
ownKeys()ownKeys(target)攔截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循環,返回一個數組。該方法返回目標對象所有自身的屬性的屬性名,而Object.keys()的返回結果僅包括目標對象自身的可遍歷屬性。
getOwnPropertyDescriptor()getOwnPropertyDescriptor(target, propKey)攔截Object.getOwnPropertyDescriptor(proxy, propKey),返回屬性的描述對象。
defineProperty()defineProperty(target, propKey, propDesc)攔截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一個布爾值。
preventExtensions()preventExtensions(target)攔截Object.preventExtensions(proxy),返回一個布爾值。
getPrototypeOf()getPrototypeOf(target)攔截Object.getPrototypeOf(proxy),返回一個對象。
isExtensible()isExtensible(target)攔截Object.isExtensible(proxy),返回一個布爾值。
setPrototypeOf()setPrototypeOf(target, proto)攔截Object.setPrototypeOf(proxy, proto),返回一個布爾值。如果目標對象是函數,那么還有兩種額外操作可以攔截。
apply()apply(target, object, args)攔截Proxy實例作為函數調用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct()construct(target, args)攔截Proxy實例作為構造函數調用的操作,比如new proxy(...args)。
Reflecthttp://es6.ruanyifeng.com/#do...簡介
Reflect對象與Proxy對象一樣,也是 ES6 為了操作對象而提供的新 API。其目的是:
將Object對象的一些明顯屬于語言內部的方法(比如Object.defineProperty),放到Reflect對象上。
修改某些Object方法的返回結果,讓其變得更合理。
讓Object操作都變成函數行為。
Reflect對象的方法與Proxy對象的方法一一對應
使用Proxy監聽數組const queuedObservers = new Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, { set }); function set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); queuedObservers.forEach(observer => observer()); return result; } const person = observable({ name: "Amber", age: 18 }); function print() { console.log(`${person.name}, ${person.age}`); } observe(print);使用Proxy、Reflect實現觀察者模式
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/100820.html
摘要:返回一個布爾值攔截操作符,返回一個布爾值攔截操作符,返回一個布爾值攔截遍歷器,返回一個遍歷器攔截,返回一個布爾值攔截,返回一個數組。 Proxy 對象 Proxy 用來修改某些默認操作,等同于在語言層面做出修改。所以屬于一種元編程(meta programming), 即對編程語言進行編程。字面理解為Proxy代理了某些默認的操作。其使用格式如下: var proxy = new Pr...
摘要:查找并返回對象的屬性例例屬性部署了讀取函數返回的是的參數對象注意如果的第一個參數不是對象,則會報錯。它返回一個布爾值,表示是否操作成功用于返回對象的所有屬性使用和實現觀察者模式請參考觀察者模式 1、什么是Reflect?為操作對象而提供的新API 2、為什么要設計Reflect?(1)將Object對象的屬于語言內部的方法放到Reflect對象上,即從Reflect對象上拿Object...
摘要:是中新增的特性。首先來說,的提出是為了整合之前中存在的一些不太合理的地方。表示當前對象是否可擴展,返回一個布爾值。更完美的枚舉很多代碼使用字符串普通或凍結的對象作為枚舉。通過記錄這些訪問和修改信息,能記錄下對這個對象的所有操作記錄。 Reflect Reflect 是ES6中新增的特性。它是一個普通對象,下面有13個靜態方法(enumerate在最終的發布版中被移除),可以再全局下訪問...
摘要:與學習的新語法糖既能學習到新東西,又能使得自己的代碼更加優雅,逼格更高,爽與之間的運用就是對對象的操作觸發的攔截是對對象進行代理,通過生成的對象間接操作原本對象,最常見的就是與語法形式是需要操作的對象,而是包含操作對象的一些方法的對象是能夠 Proxy與Reflect 學習es6的新語法糖既能學習到新東西,又能使得自己的代碼更加優雅,逼格更高,爽proxy與Reflect之間的運用就是...
摘要:使用陷阱驗證屬性用于接收屬性代理的目標的對象要寫入的屬性鍵被寫入的屬性的值操作發生的對象通常是代理屬性必須是數字拋錯用陷阱驗證對象結構屬性不存在拋出錯誤使用陷阱隱藏已有屬性可以用操作符來檢測給定對象中是否包含有某個屬性,如果自有屬性或原型屬 使用set陷阱驗證屬性 let target = { name: target } let proxy = new Proxy(targe...
閱讀 2221·2019-08-30 15:54
閱讀 1958·2019-08-30 13:49
閱讀 678·2019-08-29 18:44
閱讀 832·2019-08-29 18:39
閱讀 1116·2019-08-29 15:40
閱讀 1536·2019-08-29 12:56
閱讀 3148·2019-08-26 11:39
閱讀 3103·2019-08-26 11:37