1、Proxy 用於修改某些操作的默認行為,等同於在語言層面做出修改,所以屬於一種“元編程”(meta programming),即對編程語言進行編程。
2、Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
3、ES6 原生提供 Proxy 構造函數,用來生成 Proxy 實例。
var proxy = new Proxy(target, handler);
Proxy 對象的所有用法,都是上面這種形式,不同的只是handler
參數的寫法。其中,new Proxy()
表示生成一個Proxy
實例,target
參數表示所要攔截的目標對象,handler
參數也是一個對象,用來定制攔截行為。
4、一個技巧是將 Proxy 對象,設置到object.proxy
屬性,從而可以在object
對象上調用。
var object = { proxy: new Proxy(target, handler) };
5、get方法用於攔截某個屬性的讀取操作。下面是一個攔截讀取操作的例子。
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 // 拋出一個錯誤
6、set方法用來攔截某個屬性的賦值操作。
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 // 報錯
7、apply方法攔截函數的調用、call和apply操作。apply方法可以接受三個參數,分別是目標對象、目標對象的上下文對象(this)和目標對象的參數數組。
var twice = { apply (target, ctx, args) { return Reflect.apply(...arguments) * 2; } }; function sum (left, right) { return left + right; }; var proxy = new Proxy(sum, twice); proxy(1, 2) // 6 proxy.call(null, 5, 6) // 22 proxy.apply(null, [7, 8]) // 30