es6 学习笔记(四)

proxy

用于代理。在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截。就比如客户端与服务器之间的代理服务器。
设置了代理后,对原对象的修改直接通过代理就可以。

有点可以类比于标签模板,做了一层处理。

  1. 基本用法

    new Proxy(targetObj,handler)
    handler:{一组方法,如get(){},set(){}}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var person = {
    name: "张三"
    };
    var proxy = new Proxy(person, {
    get: function(target, property) {
    if (property in target) {
    return target[property];
    } else {
    throw new ReferenceError("Property \"" + property + "\" does not exist.");
    }
    }
    });
    proxy.name // "张三"
    proxy.age // 抛出一个错误
  2. 常用的可以拦截的方法

  • get/set :拦截属性获取/设置 如 obj.name。set方法可以用于validate
    - get可以被继承 
    
  • apply: 拦截函数调用/call/apply函数
    - 使用 apply (target, ctx, args) 
    如proxy(1, 2) // 6
    
    proxy.call(null, 5, 6) // 22
  • construct:拦截Proxy实例作为构造函数调用的操作,比如new obj(…args)。该方法必须返回对象
  • has(target, propKey):拦截
    - propKey in proxy的操作(for in 不影响),
    - 以及对象的hasProperty(不区分own)方法,返回一个布尔值。(eg。使用has方法隐藏某些属性,不被in运算符发现)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    //摘自ruanyf博客
    var handler = {
    get: function(target, name) {
    if (name === 'prototype') {
    return Object.prototype;
    }
    return 'Hello, ' + name;
    },
    apply: function(target, thisBinding, args) {
    return args[0];
    },
    construct: function(target, args) {
    return {value: args[1]};
    }
    };
    var fproxy = new Proxy(function(x, y) {
    return x + y;
    }, handler);
    fproxy(1, 2) // 1
    new fproxy(1,2) // {value: 2}
    fproxy.prototype === Object.prototype // true
    fproxy.foo // "Hello, foo"

reflect

同proxy一样,是es6为了完善对象的操作而新提出的对象。主要做的内容包括:

  • 移除Object某些方法:把原有的一些属于object内部的方法如defineProperty挂到Reflect商
  • 改变Object某些操作:把如 a in obj这种变为函数行为Reflect.has(Object,’assign’)
  • Proxy与Reflect一一对应,proxy的每一个方法,都可以调用Reflect的相应的方法,保证原生方法可以调用。(这个方法其实就是完善了的object方法)