aboutsummaryrefslogtreecommitdiff
path: root/files/es/web
diff options
context:
space:
mode:
authorDavid Brito <39559632+davbrito@users.noreply.github.com>2022-02-28 21:58:43 -0400
committerGitHub <noreply@github.com>2022-02-28 20:58:43 -0500
commita2dfcb6be483a7882c370f8b32340c198e0112b4 (patch)
tree3eb01963cecd1123419e2abdf32ca8ea03359331 /files/es/web
parent5c177fd34f91fa3af58afe2244aac22921d8b63c (diff)
downloadtranslated-content-a2dfcb6be483a7882c370f8b32340c198e0112b4.tar.gz
translated-content-a2dfcb6be483a7882c370f8b32340c198e0112b4.tar.bz2
translated-content-a2dfcb6be483a7882c370f8b32340c198e0112b4.zip
Update content and convert to md of Proxy [es] (#4306)
* Proxy Update content and convert to md (es) * Update files/es/web/javascript/reference/global_objects/proxy/index.md Co-authored-by: Anderson Vallejo <48649209+Vallejoanderson@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Anderson Vallejo <48649209+Vallejoanderson@users.noreply.github.com> Co-authored-by: Sergio.valera <sergiovaladez@duck.com> Co-authored-by: Anderson Vallejo <48649209+Vallejoanderson@users.noreply.github.com>
Diffstat (limited to 'files/es/web')
-rw-r--r--files/es/web/javascript/reference/global_objects/proxy/index.html440
-rw-r--r--files/es/web/javascript/reference/global_objects/proxy/index.md477
2 files changed, 477 insertions, 440 deletions
diff --git a/files/es/web/javascript/reference/global_objects/proxy/index.html b/files/es/web/javascript/reference/global_objects/proxy/index.html
deleted file mode 100644
index 7254cb4525..0000000000
--- a/files/es/web/javascript/reference/global_objects/proxy/index.html
+++ /dev/null
@@ -1,440 +0,0 @@
----
-title: Proxy
-slug: Web/JavaScript/Reference/Global_Objects/Proxy
-translation_of: Web/JavaScript/Reference/Global_Objects/Proxy
-original_slug: Web/JavaScript/Referencia/Objetos_globales/Proxy
----
-<div>
-<div>{{JSRef}}</div>
-</div>
-
-<p>El objeto <strong>Proxy</strong> se usa para definir un comportamiento personalizado para operaciones fundamentales (por ejemplo, para observar propiedades, cuando se asignan, enumeración, invocación de funciones, etc).</p>
-
-<h2 id="Terminología">Terminología</h2>
-
-<dl>
- <dt><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler">handler</a></dt>
- <dd>Objeto que gestiona las intercepciones a las propiedades del objeto proxy.</dd>
- <dt>traps</dt>
- <dd>Son los métodos interceptores que proveen acceso a las propiedades. Es análogo al concepto de <em>traps</em> en los sistemas operativos.</dd>
- <dt>target</dt>
- <dd>El objeto que virtualiza este objeto. Suele usarse como <em>backend</em> de almacenamiento del proxy. Invariantes (semántica que no acepta cambios) respecto a la no extensibilidad del objeto o propiedades no configurables se verifican contra este <em>target</em>.</dd>
-</dl>
-
-<h2 id="Sintaxis">Sintaxis</h2>
-
-<pre class="syntaxbox notranslate">var p = new Proxy(target, handler);
-</pre>
-
-<h3 id="Parámetros">Parámetros</h3>
-
-<dl>
- <dt><code>target</code></dt>
- <dd>Un objeto <em>target </em>(puede ser cualquier órden de objetos, incluyendo un array nativa, funcion o incluso otro proxy) o función que contenga el <code>Proxy</code></dd>
- <dt><code>handler</code></dt>
- <dd>Un objeto cuyas propiedades son funciones que definen el comportamiento del proxy cuando una operación es realizada en él.</dd>
-</dl>
-
-<h2 id="Métodos">Métodos</h2>
-
-<dl>
- <dt>{{jsxref("Proxy.revocable()")}}</dt>
- <dd>Crea un objeto <code>Proxy</code> revocable</dd>
-</dl>
-
-<h2 id="Métodos_del_objeto_handler">Métodos del objeto handler</h2>
-
-<p>The handler object is a placeholder object which contains traps for <code>Proxy</code>.</p>
-
-<div>{{page('/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler', 'Methods') }}</div>
-
-<h2 id="Ejemplos">Ejemplos</h2>
-
-<h3 id="Ejemplo_básico">Ejemplo básico</h3>
-
-<p>En este simple ejemplo el número <code>37</code> se devuelve como valor predeterminado cuando la propiedad <code>name</code> no se encuentra en el objeto. Se utilizando el manejador <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get">get</a></code>.</p>
-
-<pre class="brush: js notranslate">var handler = {
- get: function(target, name){
- return name in target?
- target[name] :
- 37;
- }
-};
-
-var p = new Proxy({}, handler);
-p.a = 1;
-p.b = undefined;
-
-console.log(p.a, p.b); // 1, undefined
-console.log('c' in p, p.c); // false, 37
-</pre>
-
-<h3 id="No-op_forwarding_proxy">No-op forwarding proxy</h3>
-
-<p>In this example, we are using a native JavaScript object to which our proxy will forward all operations that are applied to it.</p>
-
-<pre class="brush: js notranslate">var target = {};
-var p = new Proxy(target, {});
-
-p.a = 37; // operation forwarded to the target
-
-console.log(target.a); // 37. The operation has been properly forwarded
-</pre>
-
-<h3 id="Validación">Validación</h3>
-
-<p>Con un <code>Proxy</code>, puedes validar fácilmente el valor puesto a un objeto. Este ejemplo usa el handler (manejador) <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set"><code>set</code></a>.</p>
-
-<pre class="brush: js notranslate">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 &gt; 200) {
- throw new RangeError('The age seems invalid');
- }
- }
-
- // The default behavior to store the value
- obj[prop] = value;
- }
-};
-
-let person = new Proxy({}, validator);
-
-person.age = 100;
-console.log(person.age); // 100
-person.age = 'young'; // Throws an exception
-person.age = 300; // Throws an exception
-</pre>
-
-<h3 id="Extending_constructor">Extending constructor</h3>
-
-<p>A function proxy could easily extend a constructor with a new constructor. This example uses the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/construct"><code>construct</code></a> and <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply"><code>apply</code></a> handlers.</p>
-
-<pre class="brush: js notranslate">function extend(sup,base) {
- var descriptor = Object.getOwnPropertyDescriptor(
- base.prototype,"constructor"
- );
- base.prototype = Object.create(sup.prototype);
- var handler = {
- construct: function(target, args) {
- var obj = Object.create(base.prototype);
- this.apply(target,obj,args);
- return obj;
- },
- apply: function(target, that, args) {
- sup.apply(that,args);
- base.apply(that,args);
- }
- };
- var proxy = new Proxy(base,handler);
- descriptor.value = proxy;
- Object.defineProperty(base.prototype, "constructor", descriptor);
- return proxy;
-}
-
-var Person = function(name){
- this.name = name;
-};
-
-var Boy = extend(Person, function(name, age) {
- this.age = age;
-});
-
-Boy.prototype.sex = "M";
-
-var Peter = new Boy("Peter", 13);
-console.log(Peter.sex); // "M"
-console.log(Peter.name); // "Peter"
-console.log(Peter.age); // 13</pre>
-
-<h3 id="Manipular_nodos_del_DOM">Manipular nodos del DOM</h3>
-
-<p>A veces queremos cambiar el atributo clase de dos elementos diferentes. Aquí se muestra cómo usando el handler (manejador) <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set"><code>set</code></a>.</p>
-
-<pre class="brush: js notranslate">let view = new Proxy({
- selected: null
-},
-{
- set: function(obj, prop, newval) {
- let oldval = obj[prop];
-
- if (prop === 'selected') {
- if (oldval) {
- oldval.setAttribute('aria-selected', 'false');
- }
- if (newval) {
- newval.setAttribute('aria-selected', 'true');
- }
- }
-
- // The default behavior to store the value
- obj[prop] = newval;
- }
-});
-
-let i1 = view.selected = document.getElementById('item-1');
-console.log(i1.getAttribute('aria-selected')); // 'true'
-
-let i2 = view.selected = document.getElementById('item-2');
-console.log(i1.getAttribute('aria-selected')); // 'false'
-console.log(i2.getAttribute('aria-selected')); // 'true'
-</pre>
-
-<h3 id="Value_correction_and_an_extra_property">Value correction and an extra property</h3>
-
-<p>The <code>products</code> proxy object evaluates the passed value and convert it to an array if needed. The object also supports an extra property called <code>latestBrowser</code> both as a getter and a setter.</p>
-
-<pre class="brush: js notranslate">let products = new Proxy({
- browsers: ['Internet Explorer', 'Netscape']
-},
-{
- get: function(obj, prop) {
- // An extra property
- if (prop === 'latestBrowser') {
- return obj.browsers[obj.browsers.length - 1];
- }
-
- // The default behavior to return the value
- return obj[prop];
- },
- set: function(obj, prop, value) {
- // An extra property
- if (prop === 'latestBrowser') {
- obj.browsers.push(value);
- return;
- }
-
- // Convert the value if it is not an array
- if (typeof value === 'string') {
- value = [value];
- }
-
- // The default behavior to store the value
- obj[prop] = value;
- }
-});
-
-console.log(products.browsers); // ['Internet Explorer', 'Netscape']
-products.browsers = 'Firefox'; // pass a string (by mistake)
-console.log(products.browsers); // ['Firefox'] &lt;- no problem, the value is an array
-
-products.latestBrowser = 'Chrome';
-console.log(products.browsers); // ['Firefox', 'Chrome']
-console.log(products.latestBrowser); // 'Chrome'
-</pre>
-
-<h3 id="Finding_an_array_item_object_by_its_property">Finding an array item object by its property</h3>
-
-<p>This proxy extends an array with some utility features. As you see, you can flexibly "define" properties without using <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties"><code>Object.defineProperties</code></a>. This example can be adapted to find a table row by its cell. In that case, the target will be <a href="/en-US/docs/DOM/table.rows"><code>table.rows</code></a>.</p>
-
-<pre class="brush: js notranslate">let products = new Proxy([
- { name: 'Firefox', type: 'browser' },
- { name: 'SeaMonkey', type: 'browser' },
- { name: 'Thunderbird', type: 'mailer' }
-],
-{
- get: function(obj, prop) {
- // The default behavior to return the value; prop is usually an integer
- if (prop in obj) {
- return obj[prop];
- }
-
- // Get the number of products; an alias of products.length
- if (prop === 'number') {
- return obj.length;
- }
-
- let result, types = {};
-
- for (let product of obj) {
- if (product.name === prop) {
- result = product;
- }
- if (types[product.type]) {
- types[product.type].push(product);
- } else {
- types[product.type] = [product];
- }
- }
-
- // Get a product by name
- if (result) {
- return result;
- }
-
- // Get products by type
- if (prop in types) {
- return types[prop];
- }
-
- // Get product types
- if (prop === 'types') {
- return Object.keys(types);
- }
-
- return undefined;
- }
-});
-
-console.log(products[0]); // { name: 'Firefox', type: 'browser' }
-console.log(products['Firefox']); // { name: 'Firefox', type: 'browser' }
-console.log(products['Chrome']); // undefined
-console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
-console.log(products.types); // ['browser', 'mailer']
-console.log(products.number); // 3
-</pre>
-
-<h3 id="A_complete_traps_list_example">A complete <code>traps</code> list example</h3>
-
-<p>Now in order to create a complete sample <code>traps</code> list, for didactic purposes, we will try to proxify a <em>non native</em> object that is particularly suited to this type of operation: the <code>docCookies</code> global object created by <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework" title="https://developer.mozilla.org/en-US/docs/DOM/document.cookie#A_little_framework.3A_a_complete_cookies_reader.2Fwriter_with_full_unicode_support">the "little framework" published on the <code>document.cookie</code> page</a>.</p>
-
-<pre class="brush: js notranslate">/*
- var docCookies = ... get the "docCookies" object here:
- https://developer.mozilla.org/en-US/docs/DOM/document.cookie#A_little_framework.3A_a_complete_cookies_reader.2Fwriter_with_full_unicode_support
-*/
-
-var docCookies = new Proxy(docCookies, {
- get: function (oTarget, sKey) {
- return oTarget[sKey] || oTarget.getItem(sKey) || undefined;
- },
- set: function (oTarget, sKey, vValue) {
- if (sKey in oTarget) { return false; }
- return oTarget.setItem(sKey, vValue);
- },
- deleteProperty: function (oTarget, sKey) {
- if (sKey in oTarget) { return false; }
- return oTarget.removeItem(sKey);
- },
- enumerate: function (oTarget, sKey) {
- return oTarget.keys();
- },
- ownKeys: function (oTarget, sKey) {
- return oTarget.keys();
- },
- has: function (oTarget, sKey) {
- return sKey in oTarget || oTarget.hasItem(sKey);
- },
- defineProperty: function (oTarget, sKey, oDesc) {
- if (oDesc &amp;&amp; "value" in oDesc) { oTarget.setItem(sKey, oDesc.value); }
- return oTarget;
- },
- getOwnPropertyDescriptor: function (oTarget, sKey) {
- var vValue = oTarget.getItem(sKey);
- return vValue ? {
- value: vValue,
- writable: true,
- enumerable: true,
- configurable: false
- } : undefined;
- },
-});
-
-/* Cookies test */
-
-console.log(docCookies.my_cookie1 = "First value");
-console.log(docCookies.getItem("my_cookie1"));
-
-docCookies.setItem("my_cookie1", "Changed value");
-console.log(docCookies.my_cookie1);</pre>
-
-<h2 id="Specifications">Specifications</h2>
-
-<table class="standard-table">
- <tbody>
- <tr>
- <th scope="col">Specification</th>
- <th scope="col">Status</th>
- <th scope="col">Comment</th>
- </tr>
- <tr>
- <td>{{SpecName('ES2015', '#sec-proxy-objects', 'Proxy')}}</td>
- <td>{{Spec2('ES2015')}}</td>
- <td>Initial definition.</td>
- </tr>
- <tr>
- <td>{{SpecName('ESDraft', '#sec-proxy-objects', 'Proxy')}}</td>
- <td>{{Spec2('ESDraft')}}</td>
- <td></td>
- </tr>
- </tbody>
-</table>
-
-<h2 id="Browser_compatibility">Browser compatibility</h2>
-
-<p>{{CompatibilityTable}}</p>
-
-<div id="compat-desktop">
-<table class="compat-table">
- <tbody>
- <tr>
- <th>Feature</th>
- <th>Chrome</th>
- <th>Edge</th>
- <th>Firefox (Gecko)</th>
- <th>Internet Explorer</th>
- <th>Opera</th>
- <th>Safari</th>
- </tr>
- <tr>
- <td>Basic support</td>
- <td>{{CompatChrome(49.0)}}</td>
- <td>13 (10586)</td>
- <td>{{ CompatGeckoDesktop("18") }}</td>
- <td>{{CompatNo}}</td>
- <td>{{CompatUnknown}}</td>
- <td>{{CompatUnknown}}</td>
- </tr>
- </tbody>
-</table>
-</div>
-
-<div id="compat-mobile">
-<table class="compat-table">
- <tbody>
- <tr>
- <th>Feature</th>
- <th>Android</th>
- <th>Chrome for Android</th>
- <th>Firefox Mobile (Gecko)</th>
- <th>IE Mobile</th>
- <th>Opera Mobile</th>
- <th>Safari Mobile</th>
- </tr>
- <tr>
- <td>Basic support</td>
- <td>{{CompatUnknown}}</td>
- <td>{{CompatChrome(49.0)}}</td>
- <td>{{ CompatGeckoDesktop("18") }}</td>
- <td>13 (10586)</td>
- <td>{{CompatUnknown}}</td>
- <td>{{CompatUnknown}}</td>
- </tr>
- </tbody>
-</table>
-</div>
-
-<h2 id="Gecko_specific_notes">Gecko specific notes</h2>
-
-<ul>
- <li>At present, <code>Object.getPrototypeOf(proxy)</code> unconditionally returns <code>Object.getPrototypeOf(target)</code>, because the ES6 getPrototypeOf trap is not yet implemented ({{bug(795904)}}, {{bug(888969)}}).</li>
- <li><code>Array.isArray(proxy)</code> unconditionally returns <code>Array.isArray(target)</code> ({{bug(1096753)}}, {{bug(1111785)}}).</li>
- <li><code>Object.prototype.toString.call(proxy)</code> unconditionally returns <code>Object.prototype.toString.call(target)</code>, because ES6 Symbol.toStringTag is not yet implemented ({{bug(1114580)}}).</li>
-</ul>
-
-<h2 id="See_also">See also</h2>
-
-<ul>
- <li><a class="external" href="https://www.youtube.com/watch?v=sClk6aB_CPk">"Proxies are awesome" Brendan Eich presentation at JSConf</a> (<a class="external" href="http://www.slideshare.net/BrendanEich/metaprog-5303821">slides</a>)</li>
- <li><a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:proxies">ECMAScript Harmony Proxy proposal page</a> and <a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics">ECMAScript Harmony proxy semantics page</a></li>
- <li><a class="external" href="http://soft.vub.ac.be/~tvcutsem/proxies/">Tutorial on proxies</a></li>
- <li><a href="/en-US/docs/JavaScript/Old_Proxy_API" title="/en-US/docs/JavaScript/Old_Proxy_API">SpiderMonkey specific Old Proxy API</a></li>
- <li>{{jsxref("Object.watch()")}} is a non-standard feature but has been supported in Gecko for a long time.</li>
-</ul>
-
-<h2 id="Licensing_note">Licensing note</h2>
-
-<p>Some content (text, examples) in this page has been copied or adapted from the <a class="external" href="http://wiki.ecmascript.org/doku.php">ECMAScript wiki</a> which content is licensed <a class="external" href="http://creativecommons.org/licenses/by-nc-sa/2.0/">CC 2.0 BY-NC-SA</a>.</p>
diff --git a/files/es/web/javascript/reference/global_objects/proxy/index.md b/files/es/web/javascript/reference/global_objects/proxy/index.md
new file mode 100644
index 0000000000..c4e67be147
--- /dev/null
+++ b/files/es/web/javascript/reference/global_objects/proxy/index.md
@@ -0,0 +1,477 @@
+---
+title: Proxy
+slug: Web/JavaScript/Reference/Global_Objects/Proxy
+browser-compat: javascript.builtins.Proxy
+translation_of: Web/JavaScript/Reference/Global_Objects/Proxy
+---
+{{JSRef}}
+
+El objeto `Proxy` permite crear un intermediario para otro objeto, el cual
+puede interceptar y redefinir operaciones fundamentales para dicho objeto.
+
+## Descripción
+
+Un `Proxy` se crea con dos parámetros:
+
+- `target`: el objeto original que se quiere envolver.
+- `handler`: un objeto que define cuáles operaciones serán interceptadas y cómo
+ redefinir dichas operaciones.
+
+Por ejemplo, este código define un objeto simple que tiene solo dos propiedades,
+y un manipulador más simple aún que no tiene propiedades:
+
+```js
+const target = {
+ message1: 'hello',
+ message2: 'everyone',
+};
+
+const handler1 = {};
+
+const proxy1 = new Proxy(target, handler1);
+```
+
+Ya que el manipulador está vacío, este proxy se comporta justo como el objeto
+original:
+
+```js
+console.log(proxy1.message1); // hello
+console.log(proxy1.message2); // everyone
+```
+
+Para personalizar el intermediario, definimos funciones en el objeto
+manipulador:
+
+```js
+const target = {
+ message1: 'hello',
+ message2: 'everyone',
+};
+
+const handler2 = {
+ get: function (target, prop, receiver) {
+ return 'world';
+ },
+};
+
+const proxy2 = new Proxy(target, handler2);
+```
+
+Aquí hemos provisto una implementación del manipulador
+{{jsxref("Global_Objects/Proxy/Proxy/get", "get()")}}, el cual intercepta los
+intentos de acceder a las propiedades del objeto envuelto.
+
+Las funciones manipuladoras son llamadas a menudo _trampas_, probablemente
+proque atrapan las llamadas al objeto envuelto. La trampa simple de arriba en
+`handler2` redefine todos los accesores de propiedades:
+
+```js
+console.log(proxy2.message1); // world
+console.log(proxy2.message2); // world
+```
+
+Con la ayuda de la clase {{jsxref("Reflect")}} podemos darle a algunos accesores
+el comportamiento original y redefinir otros:
+
+```js
+const target = {
+ message1: 'hello',
+ message2: 'everyone',
+};
+
+const handler3 = {
+ get: function (target, prop, receiver) {
+ if (prop === 'message2') {
+ return 'world';
+ }
+ return Reflect.get(...arguments);
+ },
+};
+
+const proxy3 = new Proxy(target, handler3);
+
+console.log(proxy3.message1); // hello
+console.log(proxy3.message2); // world
+```
+
+## Constructor
+
+- {{jsxref("Global_Objects/Proxy/Proxy", "Proxy()")}}
+ - : Crea un nuevo objeto `Proxy`.
+
+## Métodos estáticos
+
+- {{jsxref("Proxy.revocable()")}}
+ - : Crea un objeto `Proxy` revocable.
+
+## Ejemplos
+
+### Ejemplo básico
+
+En este ejemplo, el número `37` es devuelto como valor pordefecto cuando el
+nombre de propiedad no está en el objeto. Se realiza usando el manipulador
+{{jsxref("Global_Objects/Proxy/Proxy/get", "get()")}}.
+
+```js
+const handler = {
+ get: function (obj, prop) {
+ return prop in obj ? obj[prop] : 37;
+ },
+};
+
+const p = new Proxy({}, handler);
+p.a = 1;
+p.b = undefined;
+
+console.log(p.a, p.b);
+// 1, undefined
+
+console.log('c' in p, p.c);
+// false, 37
+```
+
+### Proxy sin modificaciones
+
+En este ejemplo se usa un objeto nativo de JavaScript para el cual el _proxy_
+reenviará todas las operaciones que se le apliquen.
+
+```js
+const target = {};
+const p = new Proxy(target, {});
+
+p.a = 37;
+// operación reenviada al objeto envuelto
+
+console.log(target.a);
+// 37
+// (¡La operación ha sido reenviada correctamente!)
+```
+
+Nótese que mientras que esto funciona para objetos JavaScript, no lo hace para
+objetos nativos del navegador como Elementos del DOM.
+
+### Validación
+
+Con un `Proxy`, puedes puedes validar fácilmente el valor enviado para un
+objeto. Este ejemplo usa el manipulador
+{{jsxref("Global_Objects/Proxy/Proxy/set", "set()")}}.
+
+```js
+let validator = {
+ set: function (obj, prop, value) {
+ if (prop === 'age') {
+ if (!Number.isInteger(value)) {
+ throw new TypeError('La edad no es un entero');
+ }
+ if (value > 200) {
+ throw new RangeError('La edad parece inválida');
+ }
+ }
+
+ // El comportamiento por defecto es almacenar el valor
+ obj[prop] = value;
+
+ // Indica éxito
+ return true;
+ },
+};
+
+const person = new Proxy({}, validator);
+
+person.age = 100;
+console.log(person.age); // 100
+person.age = 'young'; // Lanza una excepción
+person.age = 300; // Lanza una excepción
+```
+
+### Extendiendo el contructor
+
+Una función intermediaria podría fácilmente extender un constructor con un nuevo
+constructor. Este ejemplo usa los manipuladores
+{{jsxref("Global_Objects/Proxy/Proxy/construct", "construct()")}} y
+{{jsxref("Global_Objects/Proxy/Proxy/apply", "apply()")}}.
+
+```js
+function extend(sup, base) {
+ base.prototype = Object.create(sup.prototype);
+ base.prototype.constructor = new Proxy(base, {
+ construct: function (target, args) {
+ var obj = Object.create(base.prototype);
+ this.apply(target, obj, args);
+ return obj;
+ },
+ apply: function (target, that, args) {
+ sup.apply(that, args);
+ base.apply(that, args);
+ },
+ });
+ return base.prototype.constructor;
+}
+
+var Person = function (name) {
+ this.name = name;
+};
+
+var Boy = extend(Person, function (name, age) {
+ this.age = age;
+});
+
+Boy.prototype.gender = 'M';
+
+var Peter = new Boy('Peter', 13);
+
+console.log(Peter.gender); // "M"
+console.log(Peter.name); // "Peter"
+console.log(Peter.age); // 13
+```
+
+### Manipulando nodos del DOM
+
+A veces querrás alternar algún atributo o clase de dos elementos distintos. En
+este ejemplo se explica cómo lo puedes hacer usando el manipulador
+{{jsxref("Global_Objects/Proxy/Proxy/set", "set()")}}.
+
+```js
+let view = new Proxy({
+ selected: null
+},
+{
+ set: function(obj, prop, newval) {
+ let oldval = obj[prop];
+
+ if (prop === 'selected') {
+ if (oldval) {
+ oldval.setAttribute('aria-selected', 'false');
+ }
+ if (newval) {
+ newval.setAttribute('aria-selected', 'true');
+ }
+ }
+
+ // El comportamiento por defecto es almacenar el valor
+ obj[prop] = newval;
+
+ // Indica éxito
+ return true;
+ }
+});
+
+let i1 = view.selected = document.getElementById('item-1'); //da error aquí, i1 es null
+console.log(i1.getAttribute('aria-selected'));
+// 'true'
+
+let i2 = view.selected = document.getElementById('item-2');
+console.log(i1.getAttribute('aria-selected'));
+// 'false'
+
+console.log(i2.getAttribute('aria-selected'));
+// 'true'
+Note: even if selected: !null, then giving oldval.setAttribute is not a function
+```
+
+### Corrección de valor y una propiedad extra
+
+El objeto intermediario `products` evalúa el valor pasado y lo convierte en un
+array de ser necesario. El objeto también soporta una propiedad extra llamada
+`latestBrowser` tanto como _getter_ y como _setter_.
+
+```js
+let products = new Proxy(
+ {
+ browsers: ['Internet Explorer', 'Netscape'],
+ },
+ {
+ get: function (obj, prop) {
+ // Una propiedad extra
+ if (prop === 'latestBrowser') {
+ return obj.browsers[obj.browsers.length - 1];
+ }
+
+ // El comportamiento por defecto es retornar el valor
+ return obj[prop];
+ },
+ set: function (obj, prop, value) {
+ // Una propiedad extra
+ if (prop === 'latestBrowser') {
+ obj.browsers.push(value);
+ return true;
+ }
+
+ // Convierte el valor si no es un array
+ if (typeof value === 'string') {
+ value = [value];
+ }
+
+ // El comportamiento por defecto es almacenar el valor
+ obj[prop] = value;
+
+ // Indica éxito
+ return true;
+ },
+ }
+);
+
+console.log(products.browsers);
+// ['Internet Explorer', 'Netscape']
+
+products.browsers = 'Firefox';
+// pasa una cadena (por error)
+
+console.log(products.browsers);
+// ['Firefox'] <- no hay problema, el valor es un arreglo
+
+products.latestBrowser = 'Chrome';
+
+console.log(products.browsers);
+// ['Firefox', 'Chrome']
+
+console.log(products.latestBrowser);
+// 'Chrome'
+```
+
+### Buscando un elemento de un arreglo por su propiedad
+
+Este _proxy_ extiende un arreglo con ciertas funcionalidades utilitarias. Como
+se puede ver, puedes "definir" propiedades de manera flexible sin usar
+{{jsxref("Object.defineProperties", "Object.defineProperties()")}}. Este ejemplo
+se puede adaptar para encontrar una fila de una tabla por su celda. En dicho
+caso, el target sería {{domxref("HTMLTableElement.rows", "table.rows")}}.
+
+```js
+let products = new Proxy(
+ [
+ { name: 'Firefox', type: 'browser' },
+ { name: 'SeaMonkey', type: 'browser' },
+ { name: 'Thunderbird', type: 'mailer' },
+ ],
+ {
+ get: function (obj, prop) {
+ // El comportamiento por defecto es retornar al valor; prop generalmente es un número
+ if (prop in obj) {
+ return obj[prop];
+ }
+
+ // Obtiene el número de productos; un alias de products.length
+ if (prop === 'number') {
+ return obj.length;
+ }
+
+ let result,
+ types = {};
+
+ for (let product of obj) {
+ if (product.name === prop) {
+ result = product;
+ }
+ if (types[product.type]) {
+ types[product.type].push(product);
+ } else {
+ types[product.type] = [product];
+ }
+ }
+
+ // Obtiene un producto por su nombre
+ if (result) {
+ return result;
+ }
+
+ // Obtiene productos por tipo
+ if (prop in types) {
+ return types[prop];
+ }
+
+ // Obtiene los tipos de productos
+ if (prop === 'types') {
+ return Object.keys(types);
+ }
+
+ return undefined;
+ },
+ }
+);
+
+console.log(products[0]); // { name: 'Firefox', type: 'browser' }
+console.log(products['Firefox']); // { name: 'Firefox', type: 'browser' }
+console.log(products['Chrome']); // undefined
+console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
+console.log(products.types); // ['browser', 'mailer']
+console.log(products.number); // 3
+```
+
+### Un ejemplo con todas las `trampas`
+
+Para crear un ejemplo con la lista completa de `trampas`, con motivos
+didácticos, intentaremos intervenir un objeto _no-nativo_ que se ajusta
+particularmente a este tipo de operación: el objeto global `docCookies` creado
+por
+[un simple marco de cookies](https://reference.codeproject.com/dom/document/cookie/simple_document.cookie_framework).
+
+```js
+/*
+ var docCookies = ... obtén el objeto "docCookies" aquí:
+ https://reference.codeproject.com/dom/document/cookie/simple_document.cookie_framework
+*/
+
+var docCookies = new Proxy(docCookies, {
+ get: function (oTarget, sKey) {
+ return oTarget[sKey] || oTarget.getItem(sKey) || undefined;
+ },
+ set: function (oTarget, sKey, vValue) {
+ if (sKey in oTarget) {
+ return false;
+ }
+ return oTarget.setItem(sKey, vValue);
+ },
+ deleteProperty: function (oTarget, sKey) {
+ if (!sKey in oTarget) {
+ return false;
+ }
+ return oTarget.removeItem(sKey);
+ },
+ ownKeys: function (oTarget, sKey) {
+ return oTarget.keys();
+ },
+ has: function (oTarget, sKey) {
+ return sKey in oTarget || oTarget.hasItem(sKey);
+ },
+ defineProperty: function (oTarget, sKey, oDesc) {
+ if (oDesc && 'value' in oDesc) {
+ oTarget.setItem(sKey, oDesc.value);
+ }
+ return oTarget;
+ },
+ getOwnPropertyDescriptor: function (oTarget, sKey) {
+ var vValue = oTarget.getItem(sKey);
+ return vValue
+ ? {
+ value: vValue,
+ writable: true,
+ enumerable: true,
+ configurable: false,
+ }
+ : undefined;
+ },
+});
+
+/* Pruebas de cookies */
+
+console.log((docCookies.my_cookie1 = 'Primer valor'));
+console.log(docCookies.getItem('my_cookie1'));
+
+docCookies.setItem('my_cookie1', 'Valor cambiado');
+console.log(docCookies.my_cookie1);
+```
+
+## Especificaciones
+
+{{Specifications}}
+
+## Compatibilidad con navegadores
+
+{{Compat}}
+
+## Véase también
+
+- [Presentación de "Proxies are awesome" Brendan Eich presentation at JSConf](https://www.youtube.com/watch?v=sClk6aB_CPk)
+ ([diapositivas](https://www.slideshare.net/BrendanEich/metaprog-5303821))
+- [Tutorial on proxies](https://web.archive.org/web/20171007221059/https://soft.vub.ac.be/~tvcutsem/proxies/)