柯理化函數編程:
一個大函數執行,返回一個小函數。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>柯理化函數</title>
<style>
.box {
background: red;
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<div class="box" id="box">柯理化函數</div>
<script>
//柯理化思想重寫bind:ES6版柯理化函數思想,類似實現一個模擬的this
// ~ function (proto) {
// function bind(context = window, ...outerArgs) {
// // this:要處理的函數
// let _this = this; //將要處理的函數保留下來
// return function proxy(...innerArgs) {
// // this:將這個proxy綁定給誰就是誰
// let args = outerArgs.concat(innerArgs); //拼接事件對象和參數
// _this.call(context, ...args)
// }
// };
// proto.bind = bind;
// }(Function.prototype)
// fn.bind(); //這是調用自己定義bind
// 處理兼容,兼容所有瀏覽器:
// ~ function (proto) {
// function bind(context) {
// var context = context || window;
// var _this = this;
// var outerArgs = Array.prototype.slice.call(arguments, 1);
// return function proxy() {
// var innerArgs = [].slice.call(arguments, 0);
// // this:將這個proxy綁定給誰就是誰
// let args = outerArgs.concat(innerArgs); //拼接事件對象和參數
// _this.apply(context, args); //apply 傳的是一個數組
// }
// };
// proto.bind = bind;
// }(Function.prototype)
let obj = {
x: 100
}
function fn(y) {
// console.log(y)
this.x += y;
console.log(this);
}
box.onclick = fn.bind(obj, 200);
//=> 即 box.onclick = function proxy(ev) { //弱項把ev事件對象傳過去,就加一個這個參數
//_this.call(context, ...outerArgs);
//=>即是這樣:
// fn.call(obj, ...[200, ev])
// }
/*
* 柯理化函數的思想:
* 利用閉包的機制,把一些內容事先存儲和處理了,等到後期需要的時候,拿來即用即可。
*/
/*
* bind:預先處理內容:
* @params:
* func: 要執行的函數
* context:要改變的this指向
* ...args:給函數傳遞的參數
* @return:
* 返回一個代理函數
*
*/
// 真實項目中經常使用柯理化思想,大函數存儲一些值,供以後給小函數調用,利用閉包機制。,redux中的源碼很多就是使用的柯理化函數思想
// 這是需要掌握的,執行大函數,返回小函數
function bind(func, context, ...args) {
// => func: fn
// => context: obj
// => ...args: [200,300]
return function proxy() {
func.call(context, ...args);
};
}
// 1秒鐘後執行這個函數
// setTimeout(function(){
// fn.call(obj, 200);
// }, 1000);
// ==>修改爲:
setTimeout(bind(fn, obj, 200), 1000);
// => setTimeout(function proxy(){
// func.call(context,...args)
// => fn.call(obj,200,300)
// },1000)
// 不使用bind,可以使用如下方式:
box.onclick = function () {
//點擊執行匿名函數,在匿名函數執行的時候再把fn執行
fn.call(obj, 200);
}
// 觸發盒子點擊事件的時候,把fn執行,並且讓fn的this指向obj,再給fn傳遞一個值200
// box.onclick = fn; => this指向obj,y => MouseEvent {isTrusted: true, screenX: 766, screenY: 200, clientX: 51, clientY: 68, …}
// call/apply都會把函數立即執行,bind不會立即執行函數,預先存儲一些內容。(bind不兼容IE8及以下)
// box.onclick = fn.call(obj, 200); //會立即執行
// box.onclick = fn.bind(obj, 200);
</script>
</body>
</html>