es6 proxy小注及应用

js代理(Proxy)的做用是对基础操做(取值,赋值,调用函数等)进行自定义。e.g. 你有一个对象obj = {},当对其属性赋值时obj.age = 5,你但愿作一些验证好比age不能赋值为string。这时代理就能够帮上忙。javascript

用法

const p = new Proxy(target, handler);复制代码

target:能够是任意对象,包括数组,函数,或者另外一个代理html

handler:属性是预约义函数的对象,它定义了这个代理的行为。这个对象内的函数叫作陷阱(traps),由于你一旦对代理进行操做,相关的陷阱就会被触发。java

来看一个最基本的例子,如上赋值obj.age = 5数组

const obj = {};
const proxy = new Proxy(obj, {
    set(target, key, value, receiver) {
        if (key === 'age') {
            if (!Number.isInteger(value)) {
                return false;
                // 或者 throw new TypeError('only allow int');
            }
            target[key] = value;
            return true;
        }
    }
});

proxy.age = 5; // OK
proxy.age = 'lol'; // 隐式赋值失败,或抛错复制代码

set方法必须返回布尔值,表示赋值成功与否。返回false在严格模式下会抛错TypeErrorbash

set函数的四个参数:app

target:你代理的真正对象,上面就是obj函数

key: 你访问的代理属性,如上ageui

value:给上面属性赋的值,如上5this

receiver:被调用的对象,要么是代理,要么是继承代理的对象。通常状况下,如上,显而易见就是proxy,可是某些状况下代理并非最开始被调用的对象。e.g. 假设你赋值p.age = 5,p不是代理,p本身也没有age属性,可是p的原型链上有个代理,因此当那个代理的set被调用时,receiver实际上是p。spa


ps:赋值和返回true的的那句有些人喜欢写成

return Reflect.set(target, key, value, receiver);复制代码

上面这个基本等价于target[key] = value; 可是它返回设置成功与否,因此省了一步哈。

主要的陷阱函数

上面说了set,基本上全部对对象进行基本操做的方法都有相应的trap。这里只谈一下has(), get(), apply(), construct()

has

const obj = {_secret: 'hidden property', show: 'show'};
const proxy = new Proxy(obj, {
    has(target, key) {
        if (key[0] === '_') {
            return false;
        }
        return key in target;
    }
});

'_secret' in obj // false
'show' in obj // true复制代码

这个trap是给in用的(不是for in),Reflect.has()也会触发,上面例子基本上自我解释了,很容易懂。必须返回boolean。

get

var p = new Proxy(target, {
  get: function(target, property, receiver) {
  }
});复制代码

p.foo或p[bar]都会触发。能够返回任意值。

apply

var p = new Proxy(target, {
  apply: function(target, thisArg, argumentsList) {
  }
});复制代码

p(),p.call(this), p.apply(this)均可触发,能够返回任意值。

construct

var p = new Proxy(target, {
  construct: function(target, argumentsList, newTarget) {
  }
});复制代码

new一个实例的时候触发,必须返回一个对象。

newTarget:被调用的构造器,如上p

应用

实现一个简单的双向绑定

<body> <input type="text" id="model"> <p id="word"></p> </body> <script> const model = document.getElementById("model") const word = document.getElementById("word") var obj= {}; const newObj = new Proxy(obj, { set: function(target, key, value, receiver) { if (key === "text") { model.value = value; word.innerHTML = value; } return Reflect.set(target, key, value, receiver); } }); // change ui will change local object model.addEventListener("keyup",function(e){ newObj.text = e.target.value }) // later on, if you want to programmaticly change local object, it will also reflect on UI newObj.text = 'something i like'; </script>复制代码

取得输入框和显示框元素,给输入框加监听,若是用户输入了,那么对代理的text属性赋值, 这是ui改js,若是后面用户想直接修改newObject,其改动也会反映在UI上,由于代理内部有给元素赋值。

相关文章
相关标签/搜索