iterator和Proxy

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'); 

2.11 getOwnPropertyDescriptor

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市譬巫,隨后出現(xiàn)的幾起案子咖楣,更是在濱河造成了極大的恐慌,老刑警劉巖芦昔,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诱贿,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機珠十,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門料扰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人焙蹭,你說我怎么就攤上這事晒杈。” “怎么了孔厉?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵拯钻,是天一觀的道長。 經(jīng)常有香客問我撰豺,道長说庭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任郑趁,我火速辦了婚禮,結(jié)果婚禮上姿搜,老公的妹妹穿的比我還像新娘寡润。我一直安慰自己,他們只是感情好舅柜,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布梭纹。 她就那樣靜靜地躺著,像睡著了一般致份。 火紅的嫁衣襯著肌膚如雪变抽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天氮块,我揣著相機與錄音绍载,去河邊找鬼。 笑死滔蝉,一個胖子當著我的面吹牛击儡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝠引,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼阳谍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了螃概?” 一聲冷哼從身側(cè)響起矫夯,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吊洼,沒想到半個月后训貌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡融蹂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年旺订,在試婚紗的時候發(fā)現(xiàn)自己被綠了弄企。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡区拳,死狀恐怖拘领,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情樱调,我是刑警寧澤约素,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站笆凌,受9級特大地震影響圣猎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乞而,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一送悔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧爪模,春花似錦欠啤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至共郭,卻和暖如春祠丝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背除嘹。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工写半, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憾赁。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓污朽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親龙考。 傳聞我的和親對象是個殘疾皇子蟆肆,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容