Maison > Article > interface Web > Un article expliquant l'utilisation du proxy ES6 Proxy dans JS (partage de code)
Dans l'article précédent "Une brève analyse de l'optimisation des projets web front-end dans Vue (avec code)", nous avons découvert l'optimisation des projets web front-end dans Vue. L'article suivant vous présentera l'utilisation du proxy ES6 dans JS. Jetons un coup d'œil.
proxy
La signification originale anglaise est proxy Dans ES6
, il peut être traduit par "agent". Il est principalement utilisé pour changer le comportement par défaut de certaines opérations, ce qui équivaut à faire des modifications au niveau du langage, c'est donc une sorte de "méta-programmation" (méta-programmation
), c'est-à-dire la programmation un langage de programmation. 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
construit une couche d'interception sur la couche externe de l'objet cible. Certaines opérations sur l'objet cible depuis le monde extérieur (les opérations qui peuvent être interceptées seront expliquées plus tard) doivent passer par cette couche. d'interception. La SyntaxeExemple🎜L'effet d'interception concerne uniquement les opérations proxy, pas l'objet cible. 🎜🎜🎜Méthodes des instances proxy🎜🎜Lors de la lecture de propriétés inexistantes, lancez une erreur au lieu de renvoyerlet target = { a: 1, b: 2, c: 3, }; let handler = { ownKeys(target) { return ["a"]; }, }; let proxy = new Proxy(target, handler); Object.keys(proxy); // [ 'a' ]génère un
proxy
via le constructeur. Le paramètretarget
est l'objet cible à intercepter, et lehandler. Le paramètre code> est également un objet utilisé pour personnaliser le comportement d'interception.
undéfini
🎜rrreee🎜Interceptez la lecture des propriétés héritées🎜rrreee🎜 Lecture du tableau négative index (un index négatif signifie récupérer les nombres à l'envers) 🎜rrreee🎜 Implémentez des restrictions de données 🎜rrreee🎜 pour empêcher l'attribut interne "_
" d'être lu et écrit en externe (généralement, nous commençons par un trait de soulignement pour indiquer qu'en réalité Propriétés internes) 🎜rrreee🎜Interception - appels de fonction, appel
, opérations appliquer
🎜rrreee🎜ne prend pas effet dans ...dans...
boucles 🎜rrreee🎜La boucle for...in...
incorrecte prend effet🎜rrreee🎜Interception de la méthode object.keys()
🎜rrreee🎜🎜Source de cet article Adresse RYF : https://es6.ruanyifeng.com/#docs/proxy🎜🎜🎜Apprentissage recommandé : 🎜Tutoriel avancé JS🎜🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!