[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Proxy [Back]  [Original]

- JavaScript | MDN

This page was translated from English by the community. Learn more and join the MDN Web Docs community.

View in English Always switch to English

Baseline Widely available

This feature is well established and works across many devices and browser versions. Its been available across browsers since 2016 ..

Proxy , .

In this article

JavaScript . JavaScript, , C++. JavaScript. .

: SpiderMonkey , API . , SpiderMonkey . . .

API ( ), Firefox 18. API (Firefox 17 ) API.

( "intercession API")

.

(proxy)

, .

(handler)

-, . , , .

(traps)

, . .

(target)

, . . .

- ; "" . :

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

:

  • target ( , , ).
  • handler -, () .

. , , -.

JavaScript-
Object.getOwnPropertyDescriptor(proxy, name) getOwnPropertyDescriptor function(target, name) -> PropertyDescriptor | undefined - undefined, , name .
Object.getOwnPropertyNames(proxy) Object.getOwnPropertySymbols(proxy) Object.keys(proxy) ownKeys function(target) -> [string | symbol] ( ) .
Object.defineProperty(proxy,name,pd) defineProperty function(target, name, propertyDescriptor) -> any , propertyDescriptor. .
delete proxy.name deleteProperty function(target, name) -> boolean . true name.
Object.preventExtensions(proxy) preventExtensions function(target) -> boolean . true .
name in proxy has function(target, name) -> boolean
proxy.name (in the context of "getting the value") receiver.name (if receiver inherits from a proxy and does not override name) get function(target, name, receiver) -> any receiver , .
proxy.name = val (in the context of "setting the value") receiver.name = val (if receiver inherits from a proxy and does not override name) set function(target, name, val, receiver) -> boolean receiver , .
proxy(...args) proxy.apply(thisValue, args) proxy.call(thisValue, ...args) apply function(target, thisValue, args) -> any target .
new proxy(...args) construct function(target, args) -> object target .

, , :

  • (==, ===) . p1 === p2 , p1 p2 .
  • Object.getPrototypeOf(proxy) Object.getPrototypeOf(target), ES2015 getPrototypeOf .
  • typeof proxy typeof target. , proxy target .
  • Array.isArray(proxy) Array.isArray(target).
  • Object.prototype.toString.call(proxy) Object.prototype.toString.call(target), ES2015 Symbol.toStringTag .

, 37, :

js
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

JavaScript , :

js
var target = {};
var p = new Proxy(target, {});

p.a = 37; //   

console.log(target.a); // 37.    

Proxy :

js
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");
      }
    }

    //   
    obj[prop] = value;

    //  
    return true;
  },
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = "young"; //  
person.age = 300; //  

:

js
function extend(sup, base) {
  var descriptor = Object.getOwnPropertyDescriptor(
    base.prototype,
    "constructor",
  );

  const prototype = { ...base.prototype };

  base.prototype = Object.create(sup.prototype);
  base.prototype = Object.assign(base.prototype, 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

DOM

:

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");
        }
      }

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

products . latestBrowser .

js
let products = new Proxy(
  {
    browsers: ["Internet Explorer", "Netscape"],
  },
  {
    get: function (obj, prop) {
      //  
      if (prop === "latestBrowser") {
        return obj.browsers[obj.browsers.length - 1];
      }

      //   
      return obj[prop];
    },
    set: function (obj, prop, value) {
      //  
      if (prop === "latestBrowser") {
        obj.browsers.push(value);
        return;
      }

      //  ,    
      if (typeof value === "string") {
        value = [value];
      }

      //   
      obj[prop] = value;
    },
  },
);

console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = "Firefox"; //    ( )
console.log(products.browsers); // ['Firefox'] <-  ,  - 

products.latestBrowser = "Chrome";
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'

. , "" Object.defineProperties. . table.rows.

js
let products = new Proxy(
  [
    { name: "Firefox", type: "browser" },
    { name: "SeaMonkey", type: "browser" },
    { name: "Thunderbird", type: "mailer" },
  ],
  {
    get: function (obj, prop) {
      //   ; prop   
      if (prop in obj) {
        return obj[prop];
      }

      //   ;  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];
        }
      }

      //    
      if (result) {
        return result;
      }

      //    
      if (prop in types) {
        return types[prop];
      }

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

, , , - docCookies, "little framework" document.cookie.

js
/*
  var docCookies = ...   "docCookies"  :
  https://developer.mozilla.org/ru/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();
  },
  iterate: function (oTarget, sKey) {
    return oTarget.keys();
  },
  ownKeys: function (oTarget, sKey) {
    return oTarget.keys();
  },
  has: function (oTarget, sKey) {
    return sKey in oTarget || oTarget.hasItem(sKey);
  },
  hasOwn: function (oTarget, sKey) {
    return oTarget.hasItem(sKey);
  },
  defineProperty: function (oTarget, sKey, oDesc) {
    if (oDesc && "value" in oDesc) {
      oTarget.setItem(sKey, oDesc.value);
    }
    return oTarget;
  },
  getPropertyNames: function (oTarget) {
    return Object.getPropertyNames(oTarget).concat(oTarget.keys());
  },
  getOwnPropertyNames: function (oTarget) {
    return Object.getOwnPropertyNames(oTarget).concat(oTarget.keys());
  },
  getPropertyDescriptor: function (oTarget, sKey) {
    var vValue = oTarget[sKey] || oTarget.getItem(sKey);
    return vValue
      ? {
          value: vValue,
          writable: true,
          enumerable: true,
          configurable: false,
        }
      : undefined;
  },
  getOwnPropertyDescriptor: function (oTarget, sKey) {
    var vValue = oTarget.getItem(sKey);
    return vValue
      ? {
          value: vValue,
          writable: true,
          enumerable: true,
          configurable: false,
        }
      : undefined;
  },
  fix: function (oTarget) {
    return "not implemented yet!";
  },
});

/*  cookies */

alert((docCookies.my_cookie1 = "First value"));
alert(docCookies.getItem("my_cookie1"));

docCookies.setItem("my_cookie1", "Changed value");
alert(docCookies.my_cookie1);

(, ) ECMAScript, CC 2.0 BY-NC-SA


Web Proxy Viewer  |  New URL  |  Original Page