Maison  >  Article  >  interface Web  >  Un article expliquant l'utilisation du proxy ES6 Proxy dans JS (partage de code)

Un article expliquant l'utilisation du proxy ES6 Proxy dans JS (partage de code)

奋力向前
奋力向前avant
2021-08-27 10:23:331959parcourir

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.

Un article expliquant l'utilisation du proxy ES6 Proxy dans JS (partage de code)

Le concept de proxy

proxyLa 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);

通过构造函数生成proxytarget参数是要拦截的目标对象,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

拦截——函数调用、callapply操作

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 Syntaxe
let target = {
  a: 1,
  b: 2,
  c: 3,
};

let handler = {
  ownKeys(target) {
    return ["a"];
  },
};

let proxy = new Proxy(target, handler);

Object.keys(proxy);
// [ &#39;a&#39; ]

génère un proxy via le constructeur. Le paramètre target est l'objet cible à intercepter, et le handler. Le paramètre code> est également un objet utilisé pour personnaliser le comportement d'interception.

Exemple

rrreee De manière générale, le paramètre handle est appelé un objet de configuration. Dans l'objet de configuration, vous pouvez définir les opérations qui doivent être interceptées. Si l'objet de configuration est vide, les opérations sur proxy iront directement sur l'objet cible.

🎜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 renvoyer 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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer