ES6 入门教程 15 Proxy 15.2 Proxy 实例的方法 15.2.1 get()

news2025/1/9 17:15:30

ES6 入门教程

ECMAScript 6 入门

作者:阮一峰

本文仅用于学习记录,不存在任何商业用途,如侵删

文章目录

      • ES6 入门教程
      • 15 Proxy
        • 15.2 Proxy 实例的方法
          • 15.2.1 get()

15 Proxy

15.2 Proxy 实例的方法

拦截方法的详细介绍。

15.2.1 get()

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

get方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子。

var person = {
  name: "张三"
};

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

proxy.name // "张三"
proxy.age // 抛出一个错误

在这里插入图片描述

上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回undefined

get方法可以继承。

let proto = new Proxy({}, {
  get(target, propertyKey, receiver) {
    console.log('GET ' + propertyKey);
    return target[propertyKey];
  }
});

let obj = Object.create(proto);
obj.foo // "GET foo"

上面代码中,拦截操作定义在Prototype对象上面,所以如果读取obj对象继承的属性时,拦截会生效。

下面的例子使用get拦截,实现数组读取负数的索引。

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

上面代码中,数组的位置参数是-1,就会输出数组的倒数第一个成员。

利用 Proxy,可以将读取属性的操作(get),转变为执行某个函数,从而实现属性的链式操作。

var pipe = function (value) {
  var funcStack = [];
  var oproxy = new Proxy({} , {
    get : function (pipeObject, fnName) {
      if (fnName === 'get') {
        return funcStack.reduce(function (val, fn) {
          return fn(val);
        },value);
      }
      funcStack.push(window[fnName]);
      return oproxy;
    }
  });

  return oproxy;
}

var double = n => n * 2;
var pow    = n => n * n;
var reverseInt = n => n.toString().split("").reverse().join("") | 0;

pipe(3).double.pow.reverseInt.get; // 63

上面代码设置 Proxy 以后,达到了将函数名链式使用的效果。

下面的例子则是利用get拦截,实现一个生成各种 DOM 节点的通用函数dom

const dom = new Proxy({}, {
  get(target, property) {
    return function(attrs = {}, ...children) {
      const el = document.createElement(property);
      for (let prop of Object.keys(attrs)) {
        el.setAttribute(prop, attrs[prop]);
      }
      for (let child of children) {
        if (typeof child === 'string') {
          child = document.createTextNode(child);
        }
        el.appendChild(child);
      }
      return el;
    }
  }
});

const el = dom.div({},
  'Hello, my name is ',
  dom.a({href: '//example.com'}, 'Mark'),
  '. I like:',
  dom.ul({},
    dom.li({}, 'The web'),
    dom.li({}, 'Food'),
    dom.li({}, '…actually that\'s it')
  )
);

document.body.appendChild(el);

下面是一个get方法的第三个参数的例子,它总是指向原始的读操作所在的那个对象,一般情况下就是 Proxy 实例。

const proxy = new Proxy({}, {
  get: function(target, key, receiver) {
    return receiver;
  }
});
proxy.getReceiver === proxy // true

上面代码中,proxy对象的getReceiver属性是由proxy对象提供的,所以receiver指向proxy对象。

const proxy = new Proxy({}, {
  get: function(target, key, receiver) {
    return receiver;
  }
});

const d = Object.create(proxy);
d.a === d // true

上面代码中,d对象本身没有a属性,所以读取d.a的时候,会去d的原型proxy对象找。这时,receiver就指向d,代表原始的读操作所在的那个对象。

如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性,否则通过 Proxy 对象访问该属性会报错。

const target = Object.defineProperties({}, {
  foo: {
    value: 123,
    writable: false,
    configurable: false
  },
});

const handler = {
  get(target, propKey) {
    return 'abc';
  }
};

const proxy = new Proxy(target, handler);

proxy.foo
// TypeError: Invariant check failed

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/21719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应急响应-进程排查

进程排查 进程是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础。无论在Windows还是Linux中&#xff0c;主机在感染恶意程序后&#xff0c;恶意程序都会启动相应进程来完成恶意操作。 Window…

Android 深入理解View.post() 、Window加载View原理

文章目录背景&#xff1a;如何在onCreate()中获取View的宽高&#xff1f;View.post()原理Window加载View流程setContentView()ActivityThread#handleResumeActivity()总结扩展Window、Activity及View三者之间的关系是否可以在子线程中更新UI资料背景&#xff1a;如何在onCreate…

m认知无线电信号检测算法matlab仿真,能量检测,循环平稳检测以及自相关检测

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 频谱感测是认知无线电的一项关键技术。我们将频谱感知作为一个分类问题&#xff0c;提出一种基于深度学习分类的感知方法。我们归一化接收信号功率以克服噪声功率不确定性的影响。我们使…

postgresql源码学习(49)—— MVCC⑤-cmin与cmax 同事务内的可见性判断

一、 难以理解的场景 postgresql源码学习&#xff08;十九&#xff09;—— MVCC④-可见性判断 HeapTupleSatisfiesMVCC函数_Hehuyi_In的博客-CSDN博客 在前篇的可见性判断中有个一直没想明白的问题 —— 本事务插入的数据&#xff0c;什么场景可能会出现去查询获取快照后插入…

路面坑洼检测中的视觉算法

3D道路成像和路面坑洼检测的经典工作综述。论文链接&#xff1a;https://arxiv.org/pdf/2204.13590.pdf 计算机视觉算法在3D道路成像和路面坑洼检测中的应用已有二十多年的历史。这里先介绍了用于2D和3D道路数据采集的传感系统&#xff0c;包括摄像机、激光扫描仪和微软Kinect…

汉兰达汽车发动机怠速抖动故障诊断方案设计

目录 一、课题简介 1 1.1课题基本内容 1 1.2课题解决的主要问题 1 1.3课题设计思路 1 二、毕业设计成果 2 2.1汉兰达汽车发动机怠速抖动故障现象描述 2 2.2 汉兰达汽车发动机怠速抖动故障原因分析 2 2.3汉兰达汽车发动机怠速抖动故障诊断与排除 6 2.4维修结论与建议 12 三、毕业…

java sleep yield join区别

1、sleep&#xff1a;让出CPU调度&#xff0c;Thread类的方法&#xff0c;必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU&#xff08;阿里面试题 Sleep释放CPU&#xff0c;wait 也会释放cpu&#xff0c;因为cpu资源太宝贵了&#xff0c;只有在线程running的时候&…

高效正则匹配工具

很多人都用过正则&#xff0c;但文章或许会给你一种全新的认识(思考) 以下内容适合高效率正则匹配&#xff08;比较适合正则匹配场景较多的情况&#xff09; 效率提升精华&#xff1a;本地缓存减少编译次数&#xff08;对effective java的思考&#xff0c;以及对数据库连接中…

Java中的装包(装箱)和拆包(装包)

装箱和拆箱 在Java的学习中&#xff0c;我们有的时候会设计装箱和拆箱的概念&#xff08;也就是常说的装包和拆包&#xff09;&#xff0c;这篇博客将详细讲解一下装箱和拆箱的概念及其用途。 装箱&#xff08;装包&#xff09;&#xff1a;将基本数据类型转换成包装类类型 拆…

websocket给指定客户端推送消息

业务场景 最近有一个业务场景是要做实时语音转义&#xff0c;考虑到实时性&#xff0c;所以决定采用websocket实现。 业务场景是A客户端(手机)进行语音转义的结果实时同步到B客户端(pc)&#xff0c;这就需要用到websocket将A转义的结果发送给服务端&#xff0c;服务端接收到A…

软件工程经济学复习题答案

1、利润 收入-成本费用 2、资产 流动资产非流动资产 3、显性成本可以用货币计量&#xff0c;是可以在会计的帐目上反映出来的 4、领取什么保险应缴纳个人所得税 商业保险 某企业一项固定资产的原价为8000 000元&#xff0c;预计使用年限为6年&#xff0c;预计净残值为5 0…

[LeetCode周赛复盘] 第 320 场周赛20221120

[LeetCode周赛复盘] 第 320 场周赛20221120 一、本周周赛总结二、 [Easy] 6241. 数组中不等三元组的数目1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6242. 二叉搜索树最近节点查询1. 题目描述2. 思路分析3. 代码实现四、[Hard] 6243. 到达首都的最少油耗1. 题目描述2. 思路…

10_libpcap以及libnet

知识点1【飞秋欺骗】 1、windwos安装飞秋 双击运行 2、ubuntu安装飞秋 sudo apt-get install iptux ubuntu运行飞秋&#xff1a;iptux& 3、飞秋的格式&#xff1a; 版本:包编号:用户名:主机名:命令字:附加消息 飞秋的端口是2425固定的 1表示上线 32表示普通消息 1_i…

(经典dp) hdu 递推求解专题练习

文章目录前言题单hdu2044 一只小蜜蜂...hdu2045 不容易系列之(3)—— LELE的RPG难题hdu2046 骨牌铺方格hdu2047 阿牛的EOF牛肉串hdu2048 神、上帝以及老天爷hdu2049 不容易系列之(4)——考新郎hdu2050 折线分割平面END前言 题单&#xff1a;递推求解专题练习&#xff08;For Be…

华为机试 - 找出经过特定点的路径长度

目录 题目描述 输入描述 输出描述 用例 题目解析 算法源码 题目描述 无 输入描述 输入一个字符串&#xff0c;都是以大写字母组成&#xff0c;每个相邻的距离是 1&#xff0c; 第二行输入一个字符串&#xff0c;表示必过的点。 说明每个点可过多次。 输出描述 经过这…

精益(Lean)与ERP实施

周四、五看完了24小时不停的Lean Global Connection&#xff0c;总觉得要说些什么。 印象最深的有三个地方&#xff1a; 一是John Shook的话&#xff0c;他说Lean是一种Mindset。 这种Mindset是&#xff1a; 一种积极的态度&#xff0c;Problems solving, 把问题和挑战当成是…

Web 性能优化:TLS

个人博客 Web 性能优化&#xff1a;TCP&#x1f3af; Web 性能优化&#xff1a;TLSWeb 性能优化&#xff1a;HTTP “do it, do it work, do it better … and secure ☠️” 随着追逐利益而来的恶意参与者越来越多&#xff0c;当前的 Web 应用&#xff0c;已经从野蛮生长转而…

【通关MySQL】Java的JDBC编程

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【通关MySQL】 ✈️✈️本篇内容:Java的JDBC编程。 &#x1f680;&#x1f680;代码存放仓库gitee&#xff1a;MySQL码云存放&#xff01; ⛵⛵作者简介&#xff…

[附源码]java毕业设计-室内田径馆预约管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

轻量应用服务器和云服务器CVM有什么区别?

腾讯云新推出的轻量应用服务器Lighthouse和原来的CVM云服务器有什么区别&#xff1f;轻量应用服务器Lighthouse是一种易于使用和管理、适合承载轻量级业务负载的云服务器&#xff0c;主要用于Web网站应用&#xff0c;轻量服务器使用及后期运维更加简单方便&#xff1b;云服务器…