Im vorherigen Artikel „Eine kurze Analyse der Optimierung von Web-Front-End-Projekten in Vue (mit Code)“ haben wir etwas über die Optimierung von Web-Front-End-Projekten in Vue erfahren. Der folgende Artikel führt Sie in die Verwendung des ES6-Proxy-Proxys in JS ein.
proxy
Die ursprüngliche englische Bedeutung ist Proxy. In ES6
kann es als „Agent“ übersetzt werden. Es wird hauptsächlich verwendet, um das Standardverhalten bestimmter Vorgänge zu ändern, was einer Änderung auf Sprachebene entspricht. Es handelt sich also um eine Art „Meta-Programmierung“ (meta programming
), also Programmierung eine Programmiersprache. proxy
英文原意是代理的意思,在ES6
中,可以翻译为"代理器"。它主要用于改变某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming
),即对编程语言进行编程。
proxy
在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作(后文会说明,有哪些操作可以拦截),必须通过这层拦截。语法
var proxy = new Proxy(target, handler);
通过构造函数生成proxy
,target
参数是要拦截的目标对象,handler
参数也是一个对象,用来定制拦截行为。
例子
var obj = new Proxy( {}, { get: function (target, key, receiver) { console.log(`getting ${key}!`); return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { console.log(`setting ${key}!`); return Reflect.set(target, key, value, receiver); }, } );
一般将handle
参数说成配置对象,在配置对象中,可以定义需要拦截的操作。如果配置对象为空,那么对proxy
的操作将直通目标对象。
对proxy操作才有拦截效果,而不是目标对象。
Proxy实例的方法
当读取不存在的属性时候,抛出错误而不是返回undefined
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; // 抛出一个错误
拦截读取继承属性
let proto = new Proxy( {}, { get(target, propertyKey, receiver) { console.log("GET " + propertyKey); return target[propertyKey]; }, } ); let obj = Object.create(proto); obj.xxx; // "GET xxx"
数组读取负数索引(负数索引表示倒着取数)
function createArray(...elements) { let handler = { get(target, propKey, receiver) { let index = Number(propKey); if (index < 0) { propKey = String(target.length + index); } return Reflect.get(target, propKey, receiver); }, }; let target = []; target.push(...elements); return new Proxy(target, handler); } let arr = createArray("a", "b", "c"); arr[-1]; // c
实现数据的限制
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; // 报错
防止内部属性“_
”被外部读写(通常我们以下划线开头,表示其实内部属性)
var handler = { get(target, key) { invariant(key, "get"); return target[key]; }, set(target, key, value) { invariant(key, "set"); target[key] = value; return true; }, }; function invariant(key, action) { if (key[0] === "_") { throw new Error(`Invalid attempt to ${action} private "${key}" property`); } } var target = {}; var proxy = new Proxy(target, handler); proxy._prop; // Error: Invalid attempt to get private "_prop" property proxy._prop = "c"; // Error: Invalid attempt to set private "_prop" property
拦截——函数调用、call
、apply
操作
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
不对...in...
循环生效
var handler = { has(target, key) { if (key[0] === "_") { return false; } return key in target; }, }; var target = { _prop: "foo", prop: "foo" }; var proxy = new Proxy(target, handler); "_prop" in proxy; // false
不对for...in...
循环生效
let stu1 = { name: "张三", score: 59 }; let stu2 = { name: "李四", score: 99 }; let handler = { has(target, prop) { if (prop === "score" && target[prop] < 60) { console.log(`${target.name} 不及格`); return false; } return prop in target; }, }; let oproxy1 = new Proxy(stu1, handler); let oproxy2 = new Proxy(stu2, handler); "score" in oproxy1; // 张三 不及格 // false "score" in oproxy2; // true for (let a in oproxy1) { console.log(oproxy1[a]); } // 张三 // 59 for (let b in oproxy2) { console.log(oproxy2[b]); } // 李四 // 99
拦截object.keys()
proxy
baut eine Abfangschicht auf der äußeren Schicht des Zielobjekts auf (welche Operationen von außen abgefangen werden können, wird später erläutert) muss diese Schicht durchlaufen des Abfangens. Syntaxlet target = { a: 1, b: 2, c: 3, }; let handler = { ownKeys(target) { return ["a"]; }, }; let proxy = new Proxy(target, handler); Object.keys(proxy); // [ 'a' ]Nach dem Login kopierengeneriert
Beispiel🎜Der Abfangeffekt gilt nur für Proxy-Operationen, nicht für das Zielobjekt. 🎜🎜🎜Methoden von Proxy-Instanzen🎜🎜Beim Lesen nicht vorhandener Eigenschaften wird ein Fehler ausgegeben, anstattproxy
über den Konstruktor. Der Parametertarget
ist das abzufangende Zielobjekt und derhandlerCode> Parameter ist auch ein Objekt, das zum Anpassen des Abfangverhaltens verwendet wird.
undefiniert
zurückzugeben.🎜rrreee🎜Intercept beim Lesen geerbter Eigenschaften🎜rrreee🎜 Array-Lesung negativ Index (negativer Index bedeutet, Zahlen rückwärts abzurufen) 🎜rrreee🎜 Implementieren Sie Datenbeschränkungen 🎜rrreee🎜, um zu verhindern, dass das interne Attribut „_
“ extern gelesen und geschrieben wird (normalerweise beginnen wir mit einem Unterstrich, um dies tatsächlich anzuzeigen). Interne Eigenschaften) 🎜rrreee🎜Interception – Funktionsaufrufe,call
,apply
-Operationen 🎜rrreee🎜wird nicht wirksam in...in...
Schleifen 🎜rrreee🎜Falschefor...in...
-Schleife wird wirksam🎜rrreee🎜Abfangen derobject.keys()
-Methode🎜rrreee🎜🎜Quelle dieses Artikels RYF-Adresse: https://es6.ruanyifeng.com/#docs/proxy🎜🎜🎜Empfohlenes Lernen: 🎜JS Advanced Tutorial🎜🎜Das obige ist der detaillierte Inhalt vonEin Artikel, der die Verwendung von ES6-Proxy-Proxy in JS (Code-Sharing) erläutert.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!