Proxy 讲解

以下内容是引用或者借鉴别人的,自己只是做个笔记,方便学习。理解错误的地方,欢迎评论。如有侵权,私聊我删除,未经允许,不准作为商业用途

Proxy 在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,可以对外界的访问进行过滤和改写。Proxy 支持的拦截操作共 13 种:

  • get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
  • set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
  • has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。

get(target, propKey, receiver)

var target = {
  a: 'a'
};

var handler = {
  get(target, propKey, receiver){
    if (propKey in target) {
      return target[propKey];
    } else {
      throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
    }
  }
};

var proxy = new Proxy(target, handler);
proxy.b = 'b';

console.log(proxy.a)  //a
console.log(proxy.b)  //b
console.log(target.c)  //undefined
console.log(proxy.c)  //Uncaught ReferenceError: Prop name "c" does not exist.

set(target, propKey, value, receiver)

var target = {
  a: "a"
};

var handler = {
  set(target, propKey, value, receiver) {
    target[propKey] = value + 1;
    return true;  //没有返回true,就会报错
  }
};

var proxy = new Proxy(target, handler);
proxy.b = "b";

console.log(proxy.a);  //a
console.log(proxy.b);  //b1

has(target, propKey)

var target = {
  a: "a"
};

var handler = {
  has(target, propKey) {
    return propKey in target;
  }
};

var proxy = new Proxy(target, handler);
proxy.b = "b";

console.log("a" in proxy); //true
console.log("b" in proxy); //true
console.log("c" in proxy);  //false

deleteProperty(target, propKey)

var target = {
  a: "a"
};

var handler = {
  deleteProperty(target, propKey) {
    if(propKey == 'b'){
      throw new Error(`Invalid attempt to delete private "${propKey}" property`);
    }
    delete target[propKey]
    return true;
  }
};

var proxy = new Proxy(target, handler);
proxy.b = "b";

delete proxy.a
delete proxy.b  //抛出错误

ownKeys(target)

var target = {
  a: "a"
};

var handler = {
  ownKeys(target) {
    return Reflect.ownKeys(target).filter(key => key[0] !== "_");
  }
};

var proxy = new Proxy(target, handler);
proxy._b = "b";

//_b将会被拦截
for (let key in proxy) {
  console.log(key); // a
}

getOwnPropertyDescriptor(target, propKey)

var target = {
  a: "a"
};

var handler = {
  getOwnPropertyDescriptor(target, propKey) {
    if (propKey[0] === "_") {
      return;
    }
    return Object.getOwnPropertyDescriptor(target, propKey);
  }
};

var proxy = new Proxy(target, handler);
proxy._b = "b";

console.log(Object.getOwnPropertyDescriptor(proxy, "a"));
// {
//   configurable: true;
//   enumerable: true;
//   value: "a";
//   writable: true;
// }
console.log(Object.getOwnPropertyDescriptor(proxy, "_b")); // undefined

apply (target, ctx, args)

var target = function() {};

var handler = {
  apply (target, ctx, args){
    let obj = {};
    for (let key in args) {
      obj[key] = args[key];
    }
    return obj;
  }
};

var proxy = new Proxy(target, handler);
var p = proxy('a', 'b');
var p = proxy.call(null,'a', 'b');
var p = proxy.apply(null,['a', 'b']);
console.log(p);
// {
//   0: "a",
//   1: "b"
// }

construct(target, args)

var target = function() {};

var handler = {
  construct(target, args) {
    let obj = {};
    for (let key in args) {
      obj[key] = args[key];
    }
    return obj;
  }
};

var proxy = new Proxy(target, handler);
var p = new proxy('a', 'b');
console.log(p);
// {
//   0: "a",
//   1: "b"
// }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Proxy 概述 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(met...
    pauljun阅读 3,249评论 0 1
  • proxy:可以理解为一种权限设置,将一些数据拦截,使得访问的时候只能访问到设定的内容var proxy = ne...
    灯不梨喵阅读 554评论 1 1
  • 一、Proxy概述 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(me...
    傑仔阅读 8,343评论 0 8
  • Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta program...
    木中木阅读 544评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,474评论 16 22