【ES6(2015)】Proxy
文章目錄
- 1. 基本語法
- 2. 攔截操作場景
- 3. 常用操作
在 ES6 標準中新增的一個非常強大的功能是 Proxy,它可以自定義一些常用行為如查找、賦值、枚舉、函數調用等。通過 Proxy 這個名稱也可以看出來它包含了“代理”的含義,只要有“代理”的訴求都可以考慮使用 Proxy 來實現。
1. 基本語法
let p = new Proxy(target, handler)| target | 用 Proxy 包裝的目標對象(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理) |
| handler | 一個對象,其屬性是當執行一個操作時定義代理的行為的函數 |
第一個參數 target 就是用來代理的“對象”,被代理之后它是不能直接被訪問的,而 handler 就是實現代理的過程。
2. 攔截操作場景
let obj = {name: 'xiaoming',age: 18 } console.log(obj.telephone) // undefined當我們讀取 telephone 的時候返回的是 undefined,因為 obj 這個對象中沒有這個屬性。一般我們的做法是obj.telephone || '',這樣能保證不會輸出undefined,但如果都是這樣寫有點不太美觀。ES6 的 Proxy 可以讓我們輕松的解決這一問題:
let obj = {name: 'xiaoming',age: 18 } let handle = {get (obj, key) {return Reflect.has(obj, key) ? obj[key] : ''} } let p = new Proxy(obj, handle) console.log(p.telephone)場景1:從服務端獲取的數據希望是只讀,不允許在任何一個環節被修改
// ES5 遍歷設置只讀 for (let [key] of Object.entries(response.data)) {Object.defineProperty(response.data, key, {writable: false}) } // ES6 Proxy let data = new Proxy(response.data, {set(obj, key, value) {return false} })場景2:校驗,避免與業務邏輯耦合
// Validator.js export default (obj, key, value) => {if (Reflect.has(key) && value > 20) {obj[key] = value} }import Validator from './Validator' let data = new Proxy(response.data, {set: Validator })場景3:對讀寫進行監控
let validator = {set(target, key, value) {if (key === 'age') {if (typeof value !== 'number' || Number.isNaN(value)) {throw new TypeError('Age must be a number')}if (value <= 0) {throw new TypeError('Age must be a positive number')}}return true} } const person = {age: 27 } const proxy = new Proxy(person, validator) proxy.age = 'foo' // <- TypeError: Age must be a number proxy.age = NaN // <- TypeError: Age must be a number proxy.age = 0 // <- TypeError: Age must be a positive number proxy.age = 28 console.log(person.age) // <- 28// 添加監控 window.addEventListener('error',e => {console.log(e.message) // Uncaught TypeError: Age must be a number},true )3. 常用操作
get 攔截對象屬性的讀取
let arr = [7, 8, 9] arr = new Proxy(arr, {get(target, prop) {return prop in target ? target[prop] : 'error'} }) console.log(arr[1]) // 8 console.log(arr[10]) // errorset 攔截對象屬性的設置
let arr = [] arr = new Proxy(arr, {set(target, prop, val) {if (typeof val === 'number') {target[prop] = valreturn true} else {return false}} }) arr.push(5) arr.push(6) console.log(arr[0], arr[1], arr.length) // 5 6 2has 攔截propKey in proxy的操作
let range = {start: 1,end: 5 }range = new Proxy(range, {has(target, prop) {return prop >= target.start && prop <= target.end} }) console.log(2 in range) // true console.log(9 in range) // falseownKeys 攔截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循環,返回一個數組
let userinfo = {username: 'xiecheng',age: 34,_password: '***' } userinfo = new Proxy(userinfo, {ownKeys(target) {return Object.keys(target).filter(key => !key.startsWith('_'))} }) console.log(Object.keys(userinfo)) // ["username", "age"]deleteProperty 攔截delete proxy[propKey]的操作
let user = {name: 'xiecheng',age: 34,_password: '***' } user = new Proxy(user, {deleteProperty(target, prop) { // 攔截刪除if (prop.startsWith('_')) {throw new Error('不可刪除')} else {delete target[prop]return true}} }) delete user._password // Uncaught Error: 不可刪除apply 攔截 Proxy 實例作為函數調用的操作
let sum = (...args) => {let num = 0args.forEach(item => {num += item})return num }sum = new Proxy(sum, {apply(target, ctx, args) {return target(...args) * 2} }) console.log(sum(1, 2)) // 6 console.log(sum.call(null, 1, 2, 3)) // 12 console.log(sum.apply(null, [1, 2, 3])) // 12construct 攔截 Proxy 實例作為構造函數調用的操作
let User = class {constructor(name) {this.name = name} } User = new Proxy(User, {construct(target, args, newTarget) {console.log('construct') // constructreturn new target(...args)} }) console.log(new User('xiaoming')) // User {name: "xiaoming"}總結
以上是生活随笔為你收集整理的【ES6(2015)】Proxy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python线程安全的计数器_+ =运算
- 下一篇: c语言第一章节测试,计算机二级C语言教程