今天饭桌上的时候,朋友突然问了我一个问题,JS中柯理化函数思想是个什么思想,我当是第一反应就是这个东西我知道,但是忘了,,,,好尴尬。所以回来瞅了一眼,写点总结给那位仁兄看,同时给自己一个提示,好记性不如烂笔头啊!
柯理化函数思想是一种编程思想,体现出JS的预处理机制,预处理什么呢?就是把多参数的函数变成一个接受单一参数的函数。
其实更多的是预处理this指向的问题,处理this指向问题,JS提供了两个方法call() 和 apply() 方法,两个区别在于后者传参是以数组形式传递进去的,前者是单个传入;共同点就是都是在改变this指向的同时将方法运行。但是我们在有些时候并不想让方法立即执行,这个时候使用H5中新增的方法bind() ,bind方法体现出了柯理化函数思想,通俗点就是他可以将函数中的this指向改变但同时不立即运行方法,等需要运行的时候再运行。使用bind,返回改变上下文this后的函数
var p = 'Manster' function person(name,age){ console.log(this,name,age) } var fn = person,bind(p,'manster','23); fn()
这样看似就可以了,但是有一点就是bind方法在低版本的IE下不兼容,so,没办法,要想实现功能就只能自己模拟的写一个方法了
function bind(callback,context){ var outerArg = Array.prototype.slice.call(arguments,2); return function (){ callback.apply(context,outerArg) } }
这样就又完成了一步,利用了函数私有作用域被占用不销毁的原理.
但是我们再看一东西,在我们为某个元素绑定事件的时候,浏览器会默认的传递一个参数:事件对象。并且事件绑定的方法中的this是指向当前元素的,这个是没有疑问的。
document.body.onclick = function(){ console.log(this)//这里的this是body }
但是现在我们想要将事件绑定的方法中的this改为别的元素,看一下内置的bind的解决方式
var obj = "it's me" document.body.onclick = fn.bind(obj,100,200) function fn(n1,n2,e){ console.log(n1,n2,this,e) }
内置方法很容易就实现了。 但是我们写的bind方法没有做事件对象的处理,所以需要进一步完善。
先分析一下我们上面写的自定义的bind方法。如果我们使用自定义的bind的话
var obj = "it's me" document.body.onclick = bind(fn,obj,100,200) function fn(n1,n2,e){ console.log(n1,n2,this,e) } function bind(callback,context){ var outerArg = Array.prototype.slice.call(arguments,2); return function (){//事件触发的时候实际上执行的是这个匿名方法 callback.apply(context,outerArg) } }
当我们执行的时候,执行bind方法,将bind方法的返回值绑定到事件上。 所以说我们在处理事件对象的时候要将事件对象参数传到这个return 回来的匿名函数,所以进一步完善
function bind(callback,context){ var outerArg = Array.prototype.slice.call(arguments,2); return function (){ var innerAry = Array.prototype.slice.call(arguments,0)//数组中存着事件对象 innerAry.length===0?innerAry[innerAry.length]=window.event:null;//处理ie下不会传事件对象的问题 callback.apply(context,outerArg.concat(innerAry))//将事件对象拼接到参数数组中 } }
这样就可以处理this指向和事件对象的问题了,为了使用方便,我将这个方法写到方法的原型上:最终版
因为原型上的内置方法是不能重写的,所以拓展一个myBind
Function.prototype.bind = function(context) { var outerArg = Array.prototype.slice.call(arguments, 1); var _this = this; //如果兼容bind方法就使用原生bind方法,改变this同时将参数传进去 if ('bind' in Function.prototype) { //使用了apply传递参数,原则上apply不能改变bind的this指向,所以第一参数还传this return this.bind.apply(this, arguments) } return function() { var innerArg = Array.prototype.slice.call(arguments, 0); innerArg.length === 0 ? innerArg[innerArg.length] = window.event : null; //处理ie下不会传事件对象的问题 var arg = outerArg.concat(innerArg); _this.apply(context, arg) } }
这就使用了柯理化函数的预处理思想解决了bind改变this指向的问题。待完善。。。
文章评论
Your style is very unique compared to other people I've read stuff from.
Thanks for posting when you've got the opportunity, Guess I will just book mark
this page. https://www.youtube.com/watch?v=U8mMmXObJbo
@homes for sale in Olympia thanks,虽然我不知道你在说什么。