柯理化函数编程:
一个大函数执行,返回一个小函数。
<!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>