文章目录
- ES6
- 过滤器 Proxy
- target
- handler
- get:改变“读取”操作
- 读对象,找不到抛出错误
- 数组填负的下标,倒着找元素
- 创建 key 类型的标签
- 不允许读取私有属性
- set :改变“修改”操作
- apply
- ownKeys :封掉关键字的使用
- Proxy.revocable();
- 遍历器接口
- 遍历原理
- function*
- 类 Class
- Promise
ES6
过滤器 Proxy
修改某些操作的默认行为,比方说a标签的跳转
又叫元编程
- 作用:拦截操作,类似过滤器、代理器
//建立过滤器
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 的方法
- 没有 get ,输出如下
var obj = {
name :"霍金"
};
//建立 关于目标 obj 的 Proxy 过滤器
var proxy = new Proxy(obj,{
//首先这里什么都没干
});
//通过代理来访问obj中的name属性
console.log(proxy.name);
//霍金
//什么都没干的时候过滤器就是 target 本身
- 有 get 方法,输出如下
var obj = {
name :"霍金"
};
//建立 Proxy 过滤器
var proxy = new Proxy(obj,{
//当你在这里写了get的时候,就已经开始修改读取的方法了
//所有的读取都走get语句,现在语句里啥都没有,所以 proxy.name 是 undefined
get() {
}
});
//通过代理来访问obj中的name属性
console.log(proxy.name);
//undefined
//建立过滤器
var proxy = new Proxy({name:"name的val"},{
//get 封掉了读方法
get(target,key){
console.log("我拦截了读取操作");
if (key == "prototype") {
throw new Error("dont touch me");
}
return target[key];
},
});
//你的所有点方法啊,[]什么的都是get方法
console.log(proxy.name);
//我拦截了读取操作
//name的val
console.log(proxy.prototype);
//Uncaught Error: dont touch me
读对象,找不到抛出错误
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);
//xiaopang
console.log(proxy.age);
//Uncaught Error: Cant find age in [object Object]
数组填负的下标,倒着找元素
问题描述:
有个数组 array = [0,1,2,3,4,5,6,7]
我 console.log(array[-1]),就输出 7
//rest参数,首先把传来的1,2,3,4,5,6,7压缩成数组,保存在rest中
function searchF(...rest) {
//写处理方法
let handle = {
//修改 get 读取方法
get(tar,key){
//把要找的负数的下标变成数
//因为 key 是字符串,需要转换成数字
let index = Number(key);
if(key < 0){
//如果下标小于零,那么就跟着我游戏规则完
key = tar.length + index;
}
//返回找到的元素,给 get 方法
return tar[key];
}
};
//这个 searchF 返回个过滤器
return new Proxy(rest,handle)
}
//这时候的 array 已经是过滤器了
var array = searchF(0,1,2,3,4,5,6,7);
//读取,走get方法
console.log(array[-1]);
//7
创建 key 类型的标签
问题描述:
通过过滤器在页面中添加节点,key 为 啥类型的标签,并且可以为标签添加属性和内容
const creatDom = new Proxy({},{
get(target,key) {
//这里的attrs承接创建标签的属性,other是标签的其他数据
return function (attrs = {},...other) {
//创建游离标签元素,key值是你想要创建啥标签
// 比方说 creatDom.a,key 就是 a
let ele = document.createElement(key);
//循环设置标签属性
for (let x of Object.keys(attrs)) {
ele.setAttribute(x,attrs[x]);
}
//这里用forin是不对的,forin 是取key的,这里的话就是下标了
for (let oth of other) {
if(typeof oth === "string"){
//创建文本节点
oth = document.createTextNode(oth);
}
ele.appendChild(oth);
}
return ele;
}
}
});
//a1承接过滤器返回的ele游离节点
var a1 = creatDom.a({href:"123.html"},"文本1","我是个文本2");
//把节点插入到body中
document.body.appendChild(a1);
//others 中可以接着往下写下一级的东西,比方说如下
var a2 = creatDom.div({},creatDom.ul({},creatDom.li({},"这是第一个")));
document.body.appendChild(a2);
不允许读取私有属性
要求描述:
不允许读写对象属性中以 _ 下划线打头的属性
比方说
const obj = {_pro:1}; 中的 _pro 就不被允许读写
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);
//Proxy {name: "Wangbaoqiang", _nickname: "高冷男神"}
//读取普通属性,No problem
console.log(proxy.name);
//Wangbaoqiang
//尝试读取私有属性_nickname
console.log(proxy._nickname);
//Uncaught Error: get is not use _
//尝试改写私有属性_nickname,死心吧~
proxy._nickname = "我就要改!!改不动md";
//Uncaught Error: set is not use _
set :改变“修改”操作
- set 和 get 很相似,set 多了一个参数
value
- 修改操作就是赋值呗~,看看下面的例子叭
const people = {
name:"xiaopang"
};
var proxy = new Proxy(people,{
//receiver 这参数蛮闲鱼的,有兴趣自己试试吧
set(target, key, value, receiver) {
if (key == "age") {
if (value < 18) {
console.log(`${key}太小了,送你一箱练习册`);
return;
}
}
//set就不用返回值了,你直接设置就可以了
target[key] = value;
}
});
//这里你开始了改写操作,所以走代理器中的set方法
proxy.age = 17;
//age太小了,送你一箱练习册
proxy.habit = ["sing","sang"];
console.log(people);
{name: "xiaopang", habit: Array(2)}
apply
我需要研究一下
ownKeys :封掉关键字的使用
我需要研究一下
Proxy.revocable();
遍历器接口
遍历原理
就是下标下移
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());
//{val: 1, able: true}
console.log(arr.next());
//{val: 2, able: true}
console.log(arr.next());
//{val: 3, able: true}
console.log(arr.next());
//{val: 4, able: true}
console.log(arr.next());
//{val: undefined, able: false}
function*
这玩意叫啥?function*
这种声明方式(function关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个 Generator 对象。
- 这里新出了个关键词
yield
,类似一个暂停符,到底有啥用请看下面的例子, - 这个星号放在哪里都行!
function* test() {
yield "我是第一句";
//yield相当于暂停符号,一步一步的执行,要用 next 手动执行这个玩意儿
yield "我是第二句";
return "yes";
}
var t = test();
console.log(t);
//test {<suspended>}
console.log(t.next());
//{value: "我是第一句", done: false}
console.log(t.next());
//{value: "我是第二句", done: false}
//跟指针一样一直下移
console.log(t.next());
//{value: "yes", done: true}
console.log(t.next());
//{value: undefined, done: true}
类 Class
- ES6 中迎来了真正的
Class
- ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。MDN官方解释。
- 定义类用如下的方法:
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数组
let promise = new Promise((resolve, reject) => {
if (1) {
resolve('操作成功');
} else {
reject('操作异常');
}
});
function requestA() {
console.log('请求A成功');
return 'A请求的结果';
}
function requestB(res) {
// 通过res来获得上一个返回来的结果
console.log('上一步的结果:' + res);
console.log('请求B成功');
return 'B请求的结果';
}
function requestC(res) {
console.log('上一步的结果:' + res);
console.log('请求C成功');
}
function requestError() {
console.log('请求失败');
}
//then处理操作成功,catch处理操作异常
promise.then(requestA)
.then(requestB)
.then(requestC)
.catch(requestError);
// 请求A成功
// 上一步的结果:A请求的结果
// 请求B成功
// 上一步的结果:B请求的结果
// 请求C成功