1iterator(迭代器)
迭代器是一種接口俭茧、一種機制。
為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機制,部署了iterator接口的數(shù)據(jù)結(jié)構(gòu)就可是執(zhí)行遍歷操作别洪。(主要是for......of)。
1.1iterator本質(zhì)
Iterator本質(zhì)上柳刮,就是一個指針對象挖垛。
過程是這樣的:
(1)創(chuàng)建一個指針對象,指向當前數(shù)據(jù)結(jié)構(gòu)的起始位置诚亚。
(2)第一次調(diào)用指針對象的next方法晕换,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個成員。
(3)第二次調(diào)用指針對象的next方法站宗,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個成員闸准。
(4)不斷調(diào)用指針對象的next方法,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置梢灭。
1.2普通函數(shù)實現(xiàn)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 接口的數(shù)據(jù)結(jié)構(gòu)如下夷家。
Array
Map
Set
String
函數(shù)的 arguments 對象
NodeList 對象
(1)數(shù)組
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 構(gòu)造函數(shù),用來生成 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中接受三個參數(shù)第一個就是目標對象(這里是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} 不是數(shù)字`)
}
}
})
或者通過反射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()捕獲器五督,攔截函數(shù)藏否;
function fn(){
return '哈哈'
}
var newFn = new Proxy(fn,{
apply(){
return '我已經(jīng)攔截了函數(shù)'
}
})
console.log(newFn());//'我已經(jīng)攔截了函數(shù)'
或者通過反射API方法;
let proxy = new Proxy(obj, {
apply(target, thisArg,...arguments) {
return Reflect.apply(...arguments);
}
})
Reflect.apply(target,context,args) 有三個參數(shù)
target: 需要調(diào)用的函數(shù)
context: this指向
args : 參數(shù)數(shù)組概荷。
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屬性是一個函數(shù)继薛,可以取消Proxy實例。上面代碼中愈捅,當執(zhí)行revoke函數(shù)之后遏考,再訪問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');