过滤器 Proxy
修改某些操作的默认行为,比方说a标签的跳转
又叫元编程
1 2
| var proxy = new Proxy(target,handler);
|
它有两个属性,分别是 target
目标, handler
处理方法
target
就是过滤器的目标
目标是什么类型的,那么过滤器就是什么类型的
handler
他是过滤器的处理方法,就是要告诉过滤器,你咋过滤的?
它本身是个对象
以下是 handler 中的几个方法
get:改变“读取”操作
你的所有获取属性的方法都叫 读取 方法
- 比方说
arr[0]
,这是用 中括号 来读取 arr 中下标为零的元素
console.log()
点方法 获取 console
对象中的 log
方法
- get 有 三个参数,分别是
target
目标,比方说 obj.name
,目标就是 obj
key
就是你点之后的东西,比方说 obj.name
,key
就是 name
第三个不咋用
而过滤器中的 get 会改变你读取 target 的方法
1 2 3 4 5 6 7 8 9 10 11 12
| var obj = { name :"霍金" }; var proxy = new Proxy(obj,{ }); console.log(proxy.name);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var obj = { name :"霍金" }; var proxy = new Proxy(obj,{ get() {
} });
console.log(proxy.name);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var proxy = new Proxy({name:"name的val"},{ get(target,key){ console.log("我拦截了读取操作"); if (key == "prototype") { throw new Error("dont touch me"); } return target[key]; }, }); console.log(proxy.name); console.log(proxy.prototype);
|
读对象,找不到抛出错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function Person() { this.name = "xiaopang" } var person1 = new Person(); var handler = { get(target,key){ if(key in target){ return target[key]; }else{ throw new Error(`Cant find ${key} in ${target}`); } } }; var proxy = new Proxy(person1,handler); console.log(proxy.name);
console.log(proxy.age);
|
数组填负的下标,倒着找元素
问题描述:
有个数组 array = [0,1,2,3,4,5,6,7]
我 console.log(array[-1]),就输出 7
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
| function searchF(...rest) { let handle = { get(tar,key){ let index = Number(key); if(key < 0){ key = tar.length + index; } return tar[key]; } }; return new Proxy(rest,handle) } var array = searchF(0,1,2,3,4,5,6,7);
console.log(array[-1]);
|
创建 key 类型的标签
问题描述:
通过过滤器在页面中添加节点,key 为 啥类型的标签,并且可以为标签添加属性和内容
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 27 28 29 30 31 32 33 34 35 36
| const creatDom = new Proxy({},{ get(target,key) { return function (attrs = {},...other) {
let ele = document.createElement(key);
for (let x of Object.keys(attrs)) { ele.setAttribute(x,attrs[x]); }
for (let oth of other) { if(typeof oth === "string"){ oth = document.createTextNode(oth); } ele.appendChild(oth); } return ele; } } }); var a1 = creatDom.a({href:"123.html"},"文本1","我是个文本2"); document.body.appendChild(a1); var a2 = creatDom.div({},creatDom.ul({},creatDom.li({},"这是第一个"))); document.body.appendChild(a2);
|

不允许读取私有属性
要求描述:
不允许读写对象属性中以 _ 下划线打头的属性
比方说
const obj = {_pro:1}; 中的 _pro 就不被允许读写
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 27 28 29 30 31 32 33 34 35 36 37 38
| const people = { name:"Wangbaoqiang", _nickname:"高冷男神" }; function check(key,method) { if(key[0] == "_"){ throw new Error(`${method} is not use _`); } } const handler = { get(tar,key){ check(key,"get"); return tar[key]; }, set(tar, key, val) { check(key,"set"); tar[key] = val; } }; const proxy = new Proxy(people,handler);
console.log(proxy); console.log(proxy.name);
console.log(proxy._nickname);
proxy._nickname = "我就要改!!改不动md";
|
set :改变“修改”操作
- set 和 get 很相似,set 多了一个参数
value
- 修改操作就是赋值呗~,看看下面的例子叭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const people = { name:"xiaopang" };
var proxy = new Proxy(people,{ set(target, key, value, receiver) { if (key == "age") { if (value < 18) { console.log(`${key}太小了,送你一箱练习册`); return; } } target[key] = value; } }); proxy.age = 17;
proxy.habit = ["sing","sang"]; console.log(people);
|
apply
我需要研究一下
ownKeys :封掉关键字的使用
我需要研究一下
Proxy.revocable();
遍历器接口
遍历原理
就是下标下移
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 27
| function traversing(array) { let index = 0; return { next:function () { return index < array.length ? {val:array[index++],able:true}: {val:undefined,able:false}; } } } var arr = traversing([1,2,3,4]); console.log(arr.next());
console.log(arr.next());
console.log(arr.next());
console.log(arr.next());
console.log(arr.next());
|
function*
这玩意叫啥?
- 这里新出了个关键词
yield
,类似一个暂停符,到底有啥用请看下面的例子,
- 这个星号放在哪里都行!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function* test() { yield "我是第一句";
yield "我是第二句"; return "yes"; } var t = test();
console.log(t);
console.log(t.next());
console.log(t.next());
console.log(t.next());
console.log(t.next());
|