博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6新特性:Proxy代理器
阅读量:6956 次
发布时间:2019-06-27

本文共 5509 字,大约阅读时间需要 18 分钟。

  ES6新特性:Proxy; 要使用的话, 直接在浏览器中执行即可, nodebabel目前还没有Proxypolyfill;,要使用的话,直接在浏览器中运行就好了, 浏览器的兼容性为:chrome>49或者firefox>18;

  Proxy的基本使用:

  Proxy如其名, 它的作用是在对象和和对象的属性值之间设置一个代理,获取该对象的值或者设置该对象的值, 以及实例化等等多种操作, 都会被拦截住, 经过这一层我们可以统一处理,我们可以认为它就是“代理器” ;

  Proxy是一个构造函数, 使用new Proxy创建代理器, 第一个参数为一个对象, 第二个参数也为一个对象, 返回被包裹后的代理器, 我们使用基本的getset写一个demo:

  如果实例化的时候不给第二个参数设置get和set, 相当于没有这个代理器:

var obj = new Proxy({},{});obj.vvvv = 1;console.log( obj.vvvv );

  如果给一个对象设置两个代理器或者更多的话, 所有的代理器都会生效:

  通过代理器, 能够对用户设置的值进行验证,  只有验证通过了才设置到对象上;

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;    }};let person = new Proxy({}, validator);person.age = 100;console.log(person.age); // 100person.age = 'young'; // 抛异常person.age = 300; // 值太大了,也抛异常

  代理器Proxy有点像Object的geter和seter,  可以认为是geter和seter的扩展:

  Proxy的第二个参数 

  Proxy的第二个参数为一个对象, 对象的参数为以下的列表, Proxy提供了更多的接口 , 通过不同的参数, 我们可以截获代码的运行并重新处理, 顾名思义, 代理嘛:

  handler.getPrototypeOf()

  handler.setPrototypeOf()
  handler.isExtensible()
  handler.preventExtensions()
  handler.getOwnPropertyDescriptor()
  handler.defineProperty()
  handler.has()
  handler.get()
  handler.set()
  handler.deleteProperty()
  handler.ownKeys()
  handler.apply()
  handler.construct()

  handler.getPrototypeOf(),

  getPrototypeOf方法必须返回一个对象, 否则会报错:

var obj = {};var proto = {};var handler = {    getPrototypeOf(target) {        console.log(target === obj);   // true        console.log(this === handler); // true        return proto;    }};var p = new Proxy(obj, handler);console.log(Object.getPrototypeOf(p) === proto);    // true

  5种触发getPrototypeOf的方法, 包揽了所有了所有获取原型的方法:

var obj = {};var p = new Proxy(obj, {    getPrototypeOf(target) {        return Array.prototype;    }});console.log(    Object.getPrototypeOf(p) === Array.prototype,  // true    Reflect.getPrototypeOf(p) === Array.prototype, // true    p.__proto__ === Array.prototype,               // true    Array.prototype.isPrototypeOf(p),              // true    p instanceof Array                             // true);

 

  handler.setPrototypeOf()

  当对象被设置原型的时候会执行我们设定的代码:

let handler = {    setPrototypeOf : function(target, value) {        console.log("setPrototypeOf");        target.__proto__ = value;        target.hehe = "1111";        return target;    }};let proxy = new Proxy( {}, handler );proxy.__proto__ = Object.prototypeconsole.log(proxy);输出:setPrototypeOf又输出: {hehe: "1111"}

 

  handler.constructor();

  当对象被new的时候会执行handler.constructor方法, 和上面不同的是第一个参数应该为一个函数:

 

 

  Proxy的方法:

    Proxy.revocable()返回一个可以取消的Proxy代理, 当实例化完毕后,在 执行 Proxy实例对象.revoke();   那么这个proxy实例相当于被内存回收, 不存在一样;

var revocable = Proxy.revocable({}, {    get: function(target, name) {        return "[[" + name + "]]";    }});var proxy = revocable.proxy;console.log(proxy.foo); // "[[foo]]"revocable.revoke();console.log(proxy.foo); // 抛出异常proxy.foo = 1           // 抛出异常delete proxy.foo;       // 抛出异常typeof proxy            // "object", 但是它还是一个对象....

 

  实际应用:

  通过constructapply两个变量, 可以实现一个:继承构造函数的工具函数extend:

function extend(sup,base) {    ///获取base方法的constructor    var descriptor = Object.getOwnPropertyDescriptor(        base.prototype,"constructor"    );    //重写base方法的constructor,指向继承超类的对象    base.prototype = Object.create(sup.prototype);    //利用构造器的代理器, 当用户new这个函数的返回对象时候, 会生成一个继承超类和base类的对象    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;    //修复constructor方法    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

   给一个对象绑定一个set,当对象的selected元素发生改变, 那么就改变dom节点的属性:

    
item-1
item-2

 

  浏览器的DEMO:

let products = new Proxy({        browsers: ['Internet Explorer', 'Netscape']    },    {        get: function(obj, prop) {            // 如果实际的属性为latestBrowser            if (prop === 'latestBrowser') {                return obj.browsers[obj.browsers.length - 1];            }            // 其他的属性            return obj[prop];        },        set: function(obj, prop, value) {            // 如果实际的属性为latestBrowser            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'

 

  参考:

    mdn:

    阮一峰:

作者:

出处:
QQ:287101329
微信:18101055830 

转载地址:http://oimil.baihongyu.com/

你可能感兴趣的文章
使用Visual Studio Code进行Swift开发
查看>>
精益业务分析宣言解读
查看>>
VS2017 15.8第二个预览版本提升了对CPU Profiling和F#的支持
查看>>
时序数据库DolphinDB和TimescaleDB 性能对比测试报告
查看>>
运满满的技术架构演进之路
查看>>
基准测试(Benchmarks)不必消亡
查看>>
CrowdStrike为什么从Scala迁移到Go
查看>>
Javaslang 3.0之路
查看>>
Atlassian开放团队健康监测和Team Playbook蓝图
查看>>
FB正在大规模重构React Native,预计今年发布
查看>>
《The Corporate Startup》作者访谈
查看>>
Visual Studio 15.8 Preview 3支持多点编辑功能
查看>>
PHP接入支付宝接口实现打赏功能并记录打赏信息及订单
查看>>
明文存密码成惯例?Facebook 6 亿用户密码可被 2 万员工直接看
查看>>
腾讯最新财报:云业务全年营收增长百分百至91亿元
查看>>
通过Visual Studio为Linux编写C++代码
查看>>
百度智能小程序正式开源,开发方案详解
查看>>
Linus Torvalds: Linux 之旅既有趣又幸运,我不敢奢望精通内核的全部
查看>>
Microsoft将Linux带至桌面操作系统
查看>>
GitLab可完全管理Google Kubernetes Engine
查看>>