From a2dfcb6be483a7882c370f8b32340c198e0112b4 Mon Sep 17 00:00:00 2001 From: David Brito <39559632+davbrito@users.noreply.github.com> Date: Mon, 28 Feb 2022 21:58:43 -0400 Subject: 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 Co-authored-by: Anderson Vallejo <48649209+Vallejoanderson@users.noreply.github.com> --- .../reference/global_objects/proxy/index.html | 440 ------------------- .../reference/global_objects/proxy/index.md | 477 +++++++++++++++++++++ 2 files changed, 477 insertions(+), 440 deletions(-) delete mode 100644 files/es/web/javascript/reference/global_objects/proxy/index.html create mode 100644 files/es/web/javascript/reference/global_objects/proxy/index.md (limited to 'files/es/web/javascript') 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 ---- -
-
{{JSRef}}
-
- -

El objeto Proxy 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).

- -

Terminología

- -
-
handler
-
Objeto que gestiona las intercepciones a las propiedades del objeto proxy.
-
traps
-
Son los métodos interceptores que proveen acceso a las propiedades. Es análogo al concepto de traps en los sistemas operativos.
-
target
-
El objeto que virtualiza este objeto. Suele usarse como backend 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 target.
-
- -

Sintaxis

- -
var p = new Proxy(target, handler);
-
- -

Parámetros

- -
-
target
-
Un objeto target (puede ser cualquier órden de objetos, incluyendo un array nativa, funcion o incluso otro proxy) o función que contenga el Proxy
-
handler
-
Un objeto cuyas propiedades son funciones que definen el comportamiento del proxy cuando una operación es realizada en él.
-
- -

Métodos

- -
-
{{jsxref("Proxy.revocable()")}}
-
Crea un objeto Proxy revocable
-
- -

Métodos del objeto handler

- -

The handler object is a placeholder object which contains traps for Proxy.

- -
{{page('/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler', 'Methods') }}
- -

Ejemplos

- -

Ejemplo básico

- -

En este simple ejemplo el número 37 se devuelve como valor predeterminado cuando la propiedad name no se encuentra en el objeto. Se utilizando el manejador get.

- -
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
-
- -

No-op forwarding proxy

- -

In this example, we are using a native JavaScript object to which our proxy will forward all operations that are applied to it.

- -
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
-
- -

Validación

- -

Con un Proxy, puedes validar fácilmente el valor puesto a un objeto. Este ejemplo usa el handler (manejador) 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');
-      }
-    }
-
-    // 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
-
- -

Extending constructor

- -

A function proxy could easily extend a constructor with a new constructor. This example uses the construct and apply handlers.

- -
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
- -

Manipular nodos del DOM

- -

A veces queremos cambiar el atributo clase de dos elementos diferentes. Aquí se muestra cómo usando el handler (manejador) set.

- -
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'
-
- -

Value correction and an extra property

- -

The products proxy object evaluates the passed value and convert it to an array if needed. The object also supports an extra property called latestBrowser both as a getter and a setter.

- -
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'] <- no problem, the value is an array
-
-products.latestBrowser = 'Chrome';
-console.log(products.browsers); // ['Firefox', 'Chrome']
-console.log(products.latestBrowser); // 'Chrome'
-
- -

Finding an array item object by its property

- -

This proxy extends an array with some utility features. As you see, you can flexibly "define" properties without using Object.defineProperties. This example can be adapted to find a table row by its cell. In that case, the target will be table.rows.

- -
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
-
- -

A complete traps list example

- -

Now in order to create a complete sample traps list, for didactic purposes, we will try to proxify a non native object that is particularly suited to this type of operation: the docCookies global object created by the "little framework" published on the document.cookie page.

- -
/*
-  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 && "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);
- -

Specifications

- - - - - - - - - - - - - - - - - - - -
SpecificationStatusComment
{{SpecName('ES2015', '#sec-proxy-objects', 'Proxy')}}{{Spec2('ES2015')}}Initial definition.
{{SpecName('ESDraft', '#sec-proxy-objects', 'Proxy')}}{{Spec2('ESDraft')}}
- -

Browser compatibility

- -

{{CompatibilityTable}}

- -
- - - - - - - - - - - - - - - - - - - - - -
FeatureChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support{{CompatChrome(49.0)}}13 (10586){{ CompatGeckoDesktop("18") }}{{CompatNo}}{{CompatUnknown}}{{CompatUnknown}}
-
- -
- - - - - - - - - - - - - - - - - - - - - -
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{CompatUnknown}}{{CompatChrome(49.0)}}{{ CompatGeckoDesktop("18") }}13 (10586){{CompatUnknown}}{{CompatUnknown}}
-
- -

Gecko specific notes

- - - -

See also

- - - -

Licensing note

- -

Some content (text, examples) in this page has been copied or adapted from the ECMAScript wiki which content is licensed CC 2.0 BY-NC-SA.

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/) -- cgit v1.2.3-54-g00ecf