1iterator(迭代器)
迭代器是一种接口、一种机制。
为各种不同的数据结构提供统一的访问机制,部署了iterator接口的数据结构就可是执行遍历操作。(主要是for......of)。
1.1iterator本质
Iterator本质上,就是一个指针对象。
过程是这样的:
(1)创建一个指针对象,指向当前数据结构的起始位置。
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
1.2普通函数实现iterator
function myTest(obj) {
let i = 0;
return {
next() {
let done = (i >= obj.length);
let value = done ? undefined : obj[i++];
return {
done,
value
}
}
}
}
let str = 'abc';
let test = myTest(str);
test.next();//{done : false, value: "a"}
test.next()//{done : false, value: "b"}
test.next()//{done : false, value: "c"}
test.next()//{done : true, value: undefined}
原生具备 Iterator 接口的数据结构如下。
Array
Map
Set
String
函数的 arguments 对象
NodeList 对象
(1)数组
let arr = [1, 2, 3];
let iter = arr[Symbol.iterator]();
iter.next(); //{done: false, value: 1}
iter.next(); //{done: false, value: 2}
iter.next(); //{done: false, value: 3}
iter.next(); //{done: true, value: undefined}
(2)Map
let map = new Map();
map.set(0, 1).set(1, 2).set(2, 3);
let iter = map[Symbol.iterator]();
iter.next();//{value: [0,1], done: false}
iter.next();//{value: [1,2], done: false}
iter.next();//{value: [2,3], done: false}
iter.next();//{value: undefined, done: true}
(3)Set
let set = new Set([1,2,3,2]);
let iter = set[Symbol.iterator]();
iter.next();//{value: 1, done: false}
iter.next();//{value: 2, done: false}
iter.next();//{value: 3, done: false}
iter.next();//{value: undefined, done: true}
(4)Arguments
function myTest(a,b,c){
let iter = arguments[Symbol.iterator]();
console.log(iter.next());// {value: 1, done: false}
console.log(iter.next());// {value: 2, done: false}
console.log(iter.next());// {value: 3, done: false}
console.log(iter.next());// {value: undefined, done: true}
}
myTest(1,2,3)
(5)NodeList
<ul>
<li></li>
<li></li>
<li></li>
</ul>
let ali = document.getElementsByTagName('li');
let iter = ali[Symbol.iterator]();
iter.next();//{value:li,done:false};
iter.next();//{value:li,done:false};
iter.next();//{value:li,done:false};
iter.next();//{value:undefined,done:true};
2Proxy代理
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”,即对编程语言进行编程。ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
使用方法:
let proxy = new Proxy(target, handle);
如果没有拦截行为;(handle为{})
let obj = {};
let handle = {};
let proxy = new Proxy(obj, handle);
proxy.a = 1;
obj.a; //1
proxy通向原对象。
2.1get()捕获器
let obj = {
a: 1,
b: 2
};
let proxy = new Proxy(obj, {
get(target, prop,receiver) {
if (prop in target) {
return target[prop];
} else {
throw new Error(`没找到 ${prop}`)
}
}
})
或者通过反射API方法;
let proxy = new Proxy(obj, {
get(target, prop, receiver) {
return Reflect.get(...arguments);
}
})
get中接受三个参数第一个就是目标对象(这里是obj),第二个是属性,第三个是代理对象(这里是proxy)。
2.2 set()捕获器
let obj = {
a: 1,
b: 2
};
let proxy = new Proxy(obj, {
set(target, prop, value, receiver) {
if (typeof value == 'number') {
target[prop] = value
} else {
throw new Error(`${value} 不是数字`)
}
}
})
或者通过反射API方法;
let proxy = new Proxy(obj, {
set(target, prop, value,receiver) {
return Reflect.set(...arguments);
}
})
这里多了的value是输入的新的属性。
2.3 deleteProperty()捕获器
let obj = {
a: 1,
b: 2
};
let proxy = new Proxy(obj, {
deleteProperty(target, prop, receiver) {
if (prop in target) {
delete target[prop];
} else {
throw new Error(`没找到 ${prop}`)
}
return delete target[prop];//判断是否删除成功
}
})
或者通过反射API方法;
let proxy = new Proxy(obj, {
deleteProperty(target, prop,,receiver) {
return Reflect.deleteProperty(...arguments);
}
})
delete proxy.a//true
2.4 has()捕获器
let obj = {
a: 1,
b: 2
};
let proxy = new Proxy(obj, {
has(target, prop,receiver) {
return prop in target
}
})
或者通过反射API方法;
let proxy = new Proxy(obj, {
has(target, prop,,receiver) {
return Reflect.has(...arguments);
}
})
'a' in proxy;//true
2.5apply()捕获器,拦截函数;
function fn(){
return '哈哈'
}
var newFn = new Proxy(fn,{
apply(){
return '我已经拦截了函数'
}
})
console.log(newFn());//'我已经拦截了函数'
或者通过反射API方法;
let proxy = new Proxy(obj, {
apply(target, thisArg,...arguments) {
return Reflect.apply(...arguments);
}
})
Reflect.apply(target,context,args) 有三个参数
target: 需要调用的函数
context: this指向
args : 参数数组。
2.6 revocable()取消代理
Proxy.revocable方法返回一个可取消的 Proxy 实例。
let obj = {};
let {
proxy,
revoke
} = Proxy.revocable(obj, {});
proxy.a = 10;
obj.a;//10
revoke();
proxy.a;//TypeError;
obj.a;//10
Proxy.revocable方法返回一个对象,该对象的proxy属性是Proxy实例,revoke属性是一个函数,可以取消Proxy实例。上面代码中,当执行revoke函数之后,再访问Proxy实例,就会抛出一个错误。
2.7 defineProperty()
给目标对象定义属性
const myTarget = {};
const proxy = new Proxy(myTarget, {
defineProperty(target, property, descriptor) {
console.log(target); //{}
console.log(property); //foo
console.log(descriptor); //{value:'bar'}
return Reflect.defineProperty(...arguments)
}
});
Object.defineProperty(proxy, 'foo', {
value: 'bar'
});
2.8 Ownkeys()
返回包含字符串或符号的可枚举对象。
const myTarget = {
0: 'a',
1: 'b'
};
const proxy = new Proxy(myTarget, {
ownKeys(target) {
return Reflect.ownKeys(...arguments)
}
});
console.log(Object.keys(proxy));//['0', '1'];
2.9 getPrototypeOf()
返回描述对象,没有返回null
const myTarget = {};
const proxy = new Proxy(myTarget, {
getPrototypeOf(target) {
console.log('getPrototypeOf()');
return Reflect.getPrototypeOf(...arguments)
}
});
Object.getPrototypeOf(proxy);
2.10 setPrototypeOf()
设置原型
const myTarget = {};
const proxy = new Proxy(myTarget, {
setPrototypeOf(target) {
console.log('getPrototypeOf()');
return Reflect.setPrototypeOf(...arguments)
}
});
Object.setPrototypeOf(proxy);
2.11 getOwnPropertyDescriptor
返回描述对象,没有返回null
const myTarget = {};
const proxy = new Proxy(myTarget, {
getOwnPropertyDescriptor(target, property) {
console.log('getOwnPropertyDescriptor()');
return Reflect.getOwnPropertyDescriptor(...arguments)
}
});
Object.getOwnPropertyDescriptor(proxy, 'foo');