JavaScript高级手记(闭包高级应用)
1、闭包应用值惰性函数和柯理化函数
JS高阶编程函数:惰性函数
+ 懒
+ 能只执行一次的绝不会执第二次
function getCss(ele
, attr
){
if(window
.getComputedStyle
) {
return window
.getComputedStyle(ele
)[attr
];
} else {
return ele
.currentStyle
[attr
];
}
}
let isComputed
= 'getComputedStyle' in window
;
function getCss(ele
, attr
){
if(isComputed
) {
return window
.getComputedStyle(ele
)[attr
];
} else {
return ele
.currentStyle
[attr
];
}
}
function getCss(ele
, attr
){
if(window
.getComputedStyle
) {
getCss = function(ele
, attr
) {
return window
.getComputedStyle(ele
)[attr
];
}
} else {
getCss = function(ele
, attr
) {
return ele
.currentStyle
[attr
];
}
}
return getCss(ele
, attr
);
}
console
.log(getCss(document
.body
, 'width'));
console
.log(getCss(document
.body
, 'height'));
console
.log(getCss(document
.body
, 'padding'));
* JS高阶函数:柯理化函数
+ 预处理思想:
第一次执行大函数,形成一个闭包(原因:返回了一个小函数),把一些信息存储到闭包中(传递的实参或者当前闭包中声明的以下私有变量等信息);等到后面把返回的小函数(匿名函数
)执行的时候,需要用到一些非自己私有的变量,则向上级上下文中查找(也就是把之前存储在闭包中的信息获取到)
+ 应用的也是闭包的机制
function fn(...arg1
){
return function(...arg2
) {
let arr
= arg1
.concat(arg2
);
return arr
.reduce((total
, item
) => {
return total
+ item
;
});
};
}
let res
= fn(1,2)(3);
console
.log(res
);
* reduce:数组中用来迭代遍历每一项的
arr
.reduce(function([res
], [item
]) {
})
let arr
= [10,20,30,40];
var a
= arr
.reduce((res
, item
) =>{
console
.log(res
, item
);
return res
+ item
;
})
console
.log(a
);
function reduce(arr
, callback
, init
) {
arr
= arr
.slice(0);
let index
= 0;
if(typeof init
=== 'undefined') {
init
= arr
[0];
index
=1;
}
for(let i
=index
; i
<arr
.length
; i
++) {
init
= callback(init
, arr
[i
], i
);
}
return init
;
}
let arr
= [10,20,30,40];
let result
= reduce(arr
, function(res
, item
, index
){
console
.log(index
, item
);
return res
+ item
;
});
let result1
= reduce(arr
, function(res
, item
, index
){
console
.log(index
, item
)
return res
+ item
;
}, 100);
let result2
= reduce([90], function(res
, item
, index
){
console
.log(index
, item
)
return res
+ item
;
});
console
.log(result
, result1
, result2
)
2、闭包应用之compose组合函数
在函数式编程当中又以个很重要的概念就是函数组合,实际上就是把处理数据的函数像管道一样连接起来,然后让数据穿过管道得到最终的结果。(有点像高中数学中的复合函数)例如:
const add1 = (x
) => x
+1;
const mul3 = (x
) => x
*3;
const div2 = (x
) => x
/2;
div2(mul3(add1(add1(0))));
而这样的写法可读性太差了,可以构建一个compose函数,它接收多个函数作为参数(这些函数都只接收一个参数),然后compose返回的也是一个函数,从而达到解析复合函数的效果
简而言之:compose函数可以把类似于
f(g(h(x
))) 这种写法简化成
compose(f
,g
,h
)(x
) 请完成 compose 函数的编写
function compose(...funcs
){
return function(x
){
if(funcs
.length
< 1) return x
;
let length
= funcs
.length
- 1,
fun
= funcs
[length
];
console
.log(fun
);
let res
= fun(0);
for(let i
=length
-1; i
>=0;i
--) {
console
.log(funcs
[i
]);
res
= funcs
[i
](res
);
}
console
.log(res
);
return res
;
funcs
= funcs
.reverse();
console
.log(funcs
);
return funcs
.reduce((res
, item
) => {
console
.log(res
, item
)
return item(res
);
}, x
)
}
}
const add1 = (x
) => x
+1;
const mul3 = (x
) => x
*3;
const div2 = (x
) => x
/2;
let re
= compose(div2
,mul3
,add1
,add1
)(0);
console
.log(re
);
3、闭包应用之函数的防抖和节流
* 函数的防抖(防止老年帕金森)
:
对于频繁触发某个操作,只识别一次(执行一次)
@params
:
fn
[function]:最后要触发执行的函数
wait
[number
]:“频繁”设定的界限(时间间隔)
immediate
[boolean
]:触发多次函数时,识别第一次还是最后一次
@
return
可以被调用执行的函数
function debounce(fn
, wait
, immediate
=false){
wait
= wait
|| 300;
let timer
= null;
return function(ev
){
clearTimeout(timer
);
console
.log(timer
);
if(immediate
&& (timer
=== null)) {
fn
.call(this, ev
);
}
timer
= setTimeout(()=>{
timer
= null;
if(!immediate
) {
fn
.call(this, ev
)
}
}, wait
);
}
}
function handle(ev
) {
console
.log(this, ev
);
console
.log('防抖');
}
app
.onclick
= debounce(handle
, 500, false);
function throttle(fn
, wait
=300){
let timer
= null,
previous
= 0;
return function(ev
){
let now
= new Date(),
cha
= wait
- (now
- previous
);
if(cha
<= 0 ){
clearTimeout(timer
);
previous
= now
;
fn
.call(this, ev
);
} else if(!timer
){
timer
= setTimeout(() =>{
timer
= null;
previous
= new Date();
fn
.call(this, ev
)
},cha
)
}
}
}
function handle() {
console
.log('节流');
}
window
.onscroll
= throttle(handle
, 500);