ES6
过滤器 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
| 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 19 20 21
| 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 37 38
| 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
| 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*
这玩意叫啥?
function*
这种声明方式(function 关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个 Generator 对象。
- 这里新出了个关键词
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());
|
类 Class
1 2 3 4 5 6 7 8 9 10 11
| class Person { constructor(name, age) { this.name = name; this.age = age; } show() { console.log(`我叫${this.name},今年${this.age}岁`); } } var p1 = new Person("张三", 18); p1.show();
|
Promise
- 他是一个对象,代表异步操作最终完成或失败
- 解决回调地狱的问题
- 时序:
then
中的函数被放到了微任务队列,而不是立即执行,等事件队列被清空之后再继续执行。
- 类方法:
Promise.all()
、Promise.race()
,里面承接的是Promise数组
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
| let promise = new Promise((resolve, reject) => { if (1) { resolve("操作成功"); } else { reject("操作异常"); } });
function requestA() { console.log("请求A成功"); return "A请求的结果"; } function requestB(res) { console.log("上一步的结果:" + res); console.log("请求B成功"); return "B请求的结果"; } function requestC(res) { console.log("上一步的结果:" + res); console.log("请求C成功"); } function requestError() { console.log("请求失败"); }
promise.then(requestA).then(requestB).then(requestC).catch(requestError);
|