箭头函数 & reduce & compose

箭头函数

特点:没有this arguments prototype ,没有就向上找

1
2
3
4
5
6
7
// node中没有window 代码在浏览器中执行 
let fn = ()=>{
// console.log(arguments);
// 报错:VM364:2 Uncaught ReferenceError: arguments is not defined
console.log(this); // window
}
// console.log(fn(1,2,3));

面试题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 1.
let obj = {
a: 1,
fn(){
console.log(this.a);
}
}
obj.fn();
// 执行结果: 1

// 2.
let a = 100;
let obj = {
a: 1,
fn(){ // this => obj
setTimeout(function() { // this => window 其实是window.setTimeout
console.log("a:", this.a);
});
}
}
obj.fn();
// 执行结果: undefined
// line12 let声明的变量不会放到全局上 所以windowh上没有a 取不到

// 3. 将setTimeout中变成箭头函数
let a = 100;
let obj = {
a: 1,
fn(){ // this => obj
setTimeout(()=> { // 这里就没有this了,往上找 找到line29 从而解决this问题
console.log("a:", this.a);
});
}
}
obj.fn();
// 执行结果: 1

// 4. 将fn变成箭头函数
let a = 100;
let obj = {
a: 1,
fn: ()=>{ // 这里就没有this了,往上找
setTimeout(()=> { // 这里就没有this了,往上找
console.log("a:", this.a);
});
}
}
obj.fn();
// 执行结果: undefined

不能再扩展原型

1
2
const fn = ()=>{}
console.log(fn.prototype); // undefined

数组

forEach filter map find findIndex some every reduce

some & every
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//some() 方法测试数组中是不是有元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
var array = [1, 2, 3, 4, 5];
var even = function(element) {
console.log(element)
return element % 2 === 0;
};
console.log(array.some(even));
// 1 2 true 有一个通过就停止循环

// every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
var array = [1, 2, 3, 4, 5];
var even = function(element) {
console.log(element)
return element % 2 === 0;
};
console.log(array.some(even));
// 1 false 有一个false就停止
reduce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[1,2,3,4,5].reduce((pre, curr, index, arr)=>{
console.log(pre, curr, index, arr)
})
// 执行结果:
1 2 1 [ 1, 2, 3, 4, 5 ]
undefined 3 2 [ 1, 2, 3, 4, 5 ]
undefined 4 3 [ 1, 2, 3, 4, 5 ]
undefined 5 4 [ 1, 2, 3, 4, 5 ]
// 这里pre为undefined 是因为pre又可写为acc,代表上一次调用回调时返回的累积值,这里line2没有做累计

let total = [1,2,3,4,5].reduce((pre, curr, index, arr)=>{
console.log(pre, curr, index, arr)
return pre + curr;
})
console.log(total);
// 执行结果:
1 2 1 [ 1, 2, 3, 4, 5 ]
3 3 2 [ 1, 2, 3, 4, 5 ]
6 4 3 [ 1, 2, 3, 4, 5 ]
10 5 4 [ 1, 2, 3, 4, 5 ]
15

[1,2,3,4,5].reduce((pre, curr, index, arr)=>{
console.log(pre, curr, index, arr)
},100)
// 执行结果:
100 1 0 [ 1, 2, 3, 4, 5 ]
undefined 2 1 [ 1, 2, 3, 4, 5 ]
undefined 3 2 [ 1, 2, 3, 4, 5 ]
undefined 4 3 [ 1, 2, 3, 4, 5 ]
undefined 5 4 [ 1, 2, 3, 4, 5 ]

示例 收敛

1
2
3
4
 let total = [{price: 1, count: 5}, {price: 2, count: 5}, {price: 3, count: 6}].reduce( (acc, curr, index, arr) => {
return acc + curr.price * curr.count;
}, 0); // 这里这个0就代表初始值 即第一项
console.log(total); // 33

示例 数组扁平化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let arr = [1,[2,[3,[4,[5]]]]];
console.log(arr.toString(), typeof arr.toString()); // 这样的方式不行 数据类型string
// 1,2,3,4,5 string

// flat
console.log( [1,[2,[3,[4,[5]]]]].flat(10)); // 10指嵌套10项都打开
// [1, 2, 3, 4, 5]

// 用reduce写一下
Object.defineProperty(Array.prototype, 'flat', {
value: function(depth = 1) {
return this.reduce(function (flat, toFlatten) {
return flat.concat((Array.isArray(toFlatten) && (depth>1)) ? toFlatten.flat(depth-1) : toFlatten);
}, []);
}
});

console.log(
[1, [2], [3, [[4]]]].flat(2)
);
// [ 1, 2, 3, [ 4 ] ]

https://stackoverflow.com/questions/50993498/flat-is-not-a-function-whats-wrong

示例 函数的组合 compose (redux源码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function sum(a,b){
return a + b;
}
function len(str){
return str.length;
}
function addCurrency(val){
return '$' + val;
}
// 现在想把这3个函数组合起来
let r = addCurrency(len(sum('abc', 'bed')));
console.log(r); // $6

// 自己写下compose
function sum(a,b){
return a + b;
}
function len(str){
return str.length;
}
function addCurrency(val){
return '$' + val;
}
function compose(...args){
return function(...values){
let fn = args.pop(); // 取到最后一个方法 即sum
return args.reduceRight( (prev, curr) => { // reduceRight反向
return curr(prev); // 把上一次计算的结果再传递给下一个函数
// 注意:这里不能return curr(prev(...values));这样写
},fn(...values));
}
}
// 优化成箭头函数
const compose = (...args) => (...values) => {
let fn = args.pop();
return args.reduceRight( (prev, curr) => curr(prev) ,fn(...values));
}

let r = compose(addCurrency, len, sum)('abc', 'bed');
// 这个compose是个高阶函数 compose(addCurrency, len, sum)返回一个函数
// 这里的执行顺序是('abc', 'bed')里面的值先传给sum, sum('abc', 'bed')的值再传给len....

上面的写法是因为知道有reduceRight 可以反向 现在正向来写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function sum(a,b){
return a + b;
}
function len(str){
return str.length;
}
function addCurrency(val){
return '$' + val;
}
function compose(...args){ // len, sum
return args.reduce( (prev, curr) => {
return function(...values){ // 'abc', 'bed'
return prev(curr(...values));
}
})
}
// es6箭头函数优化
const compose = (...args) => args.reduce( (prev, curr) => (...values) => prev(curr(...values)));
// redux中compose的源码 github redux => src => compose.ts => 最下面
// return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
let r = compose(addCurrency,len, sum)('abc', 'bed');
console.log(r);

compose 组合多个函数 这个是redux compose的原理


作业

1
2
3
1.反柯里化
2.flat (reduce)
3.Array.prototype.reduce 实现reduce原理