微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ES6的Proxy对象

Proxy在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改

ES6原生提供了Proxy构造函数,用来生成Proxy实例。下面代码中proxy代理target。

var proxy = new Proxy(target, handler);

Proxy对象的所有用法,都是上面的这种形式。不同的只是handle参数的写法。其中new Proxy用来生成Proxy实例,target是表示所要拦截的对象,handle是用来定制拦截行为的对象。

var proxy = new Proxy({}, {
  get: function(target, property) {
    return 35;
  }
});

proxy.time   // 35
proxy.name   // 35
proxy.title   // 35

上面是一个拦截读取属性的行为的例子。要使Proxy起作用,必须针对Proxy实例进行操作,而不是针对目标对象(target)进行操作。如果handler没有设置任何拦截,那就等同于直接通向原对象,如下:

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a    // "b"

Proxy对象也可以作为其它对象的原型对象。下面代码中,proxy对象是obj的原型对象,obj本身并没有time属性,所以根据原型链,会在proxy对象上读取属性,从而被拦截

var proxy = new Proxy({}, {
  get: function(target, property) {
    return 35;
  }
});

let obj = Object.create(proxy);
obj.time    // 35

Proxy的实例方法支持拦截的操作),一共有13种:

get(target, propKey, receiver)
set(target, propKey, value, receiver)
has(target, propKey)
deleteProperty(target, propKey)
ownKeys(target)
getownPropertyDescriptor(target, propKey)
defineProperty(target, propKey, propDesc)
preventExtensions(target)
getPrototypeOf(target)
isExtensible(target)
setPrototypeOf(target, proto)
apply(target, object, args)
construct(target, args)

get()

get方法用于拦截某个属性的读取操作,可以接收三个参数,依次为目标对象,属性名和Proxy实例本身,其中最后一个参数可选。

下面代码表示如果有这个属性则返回属性值,如没有就会输出111,如果没有这个拦截,没有属性会返回undefined。

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

var proxy = new Proxy(person, {
  get: function(target, property) {
    if (property in target) {
      return target[property];
    } else {
      console.log(111)
    }
  }
});

proxy.name   // "张三"
proxy.age   // 111

set()

set方法用来拦截某个属性的赋值操作,可以接受4个参数,依次为目标对象,属性名,属性值和Proxy实例本身,其中最后一个参数可选。

假设Person对象有个age属性,该属性一个不大于200的整数,那么可以使用Proxy来保证age的属性值符合要求。

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');   // 报错1
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');   //报错2
      }
    }

    // 对于满足条件的 age 属性以及其他属性,直接保存
    obj[prop] = value;
  }
};

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

person.age = 100;

person.age // 100
person.age = 'young'   // 报错1 
person.age = 300   // 报错2
const handler = {
  set: function(obj, prop, value, receiver) {
    obj[prop] = receiver;
  }
};
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
proxy.foo === proxy   // true

apply()

apply方法拦截函数调用、call和apply操作。apply方法可以接收三个参数,依次是目标对象,目标对象的上下文对象(this)和目标对象的参数数组。

var target = function () { return 'I am the target'; };
var handler = {
  apply: function () {
    return 'I am the proxy';
  }
};

var p = new Proxy(target, handler);
p()   // "I am the proxy"

has()

has方法用来拦截Hasproperty操作,即判断对象是否有某个属性时,这个方法会生效。典型的操作就是in操作。has方法可以接收两个参数,分别是目标对象,需查询属性名。

下面代码中,如原对象的属性名的第一个字符是下划线,则返回false。

var handler = {
  has (target, key) {
    if (key[0] === '_') {
      return false;
    }
    return key in target;
  }
};
var target = { _prop: 'foo', prop: 'foo' };
var proxy = new Proxy(target, handler);
'_prop' in proxy   // false

对象不可配置或禁止扩展时,has拦截会报错。

var obj = { a: 10 };
Object.preventExtensions(obj);

var p = new Proxy(obj, {
  has: function(target, prop) {
    return false;
  }
});

'a' in p   // TypeError is thrown

has方法拦截的是hasProperty操作,而不是hasOwnProperty操作,即不判断一个属性是自身的属性还是继承属性

has方法只对in运算符生效,而不对for...in循环生效,如下。

construct()

construct方法用于拦截new命令,下面是拦截对象的写法。construct方法可以接收三个参数,依次是目标对象,构造函数的参数对象和创造实例对象时,new命令作用的构造函数(可选)

var p = new Proxy(function () {}, {
  construct: function(target, args) {
    console.log('called: ' + args.join(', '));
    return { value: args[0] * 10 };
  }
});

(new p(1)).value
// "called: 1"
// 10

construct方法返回的必须是一个对象,否则会报错。

var p = new Proxy(function() {}, {
  construct: function(target, argumentsList) {
    return 1;
  }
});

new p()   // 报错

deleteproperty()

deleteProperty方法拦截的是delete操作,如果这个方法抛出错误或返回false,则当前属性就无法被delete命令删除

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原文:https://www.cnblogs.com/kdcg/p/9145385.html

原文地址:https://www.cnblogs.com/xjy20170907/p/11558920.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐