@[toc]javascript
function fun(n, o) { console.log(o); return { fun: function (m) { return fun(m, n); } }; } var c = fun(0).fun(1); c.fun(2); c.fun(3);
△ 答案是?java
△ 圖3.7_圖解redux
function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (...args) => a(b(...args))) }
△ redux中的compose函數函數
咱們普通寫調用函數,可是可讀性太差spa
const add1 = x => x + 1; const mul3 = x => x * 3; const div2 = x => x / 2; div2(mul3(add1(add1(0)))); //=>3
△ 普通調用函數code
那麼,須要寫一個可讀性較高的組合函數:對象
const operate = compose(div2, mul3, add1, add1); operate(0);
△ 調用compose函數blog
compose(div2, mul3, add1, add1)
傳參的順序與div2(mul3(add1(add1(0))))
調用函數的順序關係ip
那麼,咱們上次寫的reduceRight
從裏面往外調用函數實現組合函數的調用內存
然而,redux使用的是reduce
按照輸入參數的順序調用的
咱就從EC/VO/AO 堆棧內存做用域的角度,一步一步分析就好
我們就根據:執行上下文、做用域、做用域鏈、VO、AO這些一步步分析便可
// funcs=[div2,mul3, add1, add1] 函數集合 // return funcs.reduce((a, b) => (...args) => a(b(...args))) return funcs.reduce((a, b) => { let fn = (x) => { return a(b(x)); }; return fn; });
△ 分析reduce的寫法
【0】EC(C001) 假設這是compse() 執行造成的執行上下文
operate 是一個函數
那麼 ,compose return 出去的是一個函數
let result = funcs.reduce((a,b)=>{ return function anonymous(x){ return a(b(x)); }; });
△ result 獲得的是一個函數
result 接收到的結果是一個函數
此時,須要經過reduce每次調用callback造成 函數私有上下文
在每次的函數的私有上下文中,都會建立一個匿名函數
每一個匿名函數所處的做用域是不一樣的
代碼執行到:funcs.reduce(callback)
【1】 第一輪遍歷 EC(CB1)私有執行上下文
AO(CB1) 變量對象
a=div2
b=mul3
anonymous=0xA001
做用域鏈:<EC(CB1), EC(C001)>
形參賦值:a=div2; b=mul3
變量提高:anonymous=0xA001
代碼執行:
return function anonymous(x){ a(b(x)); }; //=====> 【return 0xA001】;
△ 第一輪循環返回的值
【2】第二輪遍歷 EC(CB2) 私有執行上下文
AO(CB2) 變量對象
a=0xA001
b=add1
anonymous=0xA002
做用域鏈:<EC(CB2), EC(C001)>
形參賦值:a=0xA001; b=add1
變量提高:anonymous=0xA002
代碼執行:
return function anonymous(x){ a(b(x)); }; //=> 【return 0xA002】;
△ 第二輪循環返回的值
【3】第三輪遍歷 EC(CB3)私有執行上下文
AO(CB3) 變量對象
a=0xA002
b=add1
anonymous=0xA003
做用域鏈:<EC(CB3), EC(C001)>
形參賦值:a=0xA003; b=add1
變量提高:anonymous=0xA003
代碼執行:
return function anonymous(x){ a(b(x)); }; //=> 【return 0xA003】;
△ 第三輪循環返回的值
三輪遍歷結束後,把0xA003
賦值給operate
operate(0)
執行
【3】EC(0xA003)
AO(0xA003)
x=0
做用域鏈:<EC(0xA003),EC(CB3) >
形參賦值:x=0
代碼執行:
a(b(x));
=> x 是本身的:x=0; a和b都是上級上下文的
=> a=0xA002
=> b=add1
==> 0xA002(add1(0))
=> add1(0) => x+1=1
=> add1(0) 就當它是最後結果了,爲了最後看到的效果是同樣的,就不寫計算了
=> 0xA002() 調用
【2】EC(0xA002)
AO(0xA002)
x = add1(0)
做用域鏈:<EC(0xA002),EC(CB2) >
形參賦值:x=add1(0)
代碼執行:
a(b(x));
=> x 是本身的:x=add1(0);a和b都是上級上下文的
=> a=0xA001
=> b=add1
==> 0xA001(add1(add1(0)))
=> add1(add1(0))就當是計算後的結果了
=> 0xA001() 調用
【1】EC(0xA001)
AO(0xA001)
x = add1(add1(0))
做用域鏈:<EC(0xA001),EC(CB1) >
形參賦值:x = add1(add1(0))
代碼執行:
a(b(x));
=> x 是本身的:x=add1(add1(0)); a和b都是上級上下文的
=> a=div2
=> b=mul3
==> div2(mul3(add1(add1(0))))
即:div2(mul3(add1(add1(0))))
- end -
把你的心 個人心串一串
串一株幸運草 串一個同心圓