愚墨的博客
  • 首页
  • 前端技术
  • 面试
只争朝夕不负韶华
  1. 首页
  2. 前端技术
  3. 正文

js编程之柯理化函数思想

2016年07月11日 4185点热度 0人点赞 2条评论

今天饭桌上的时候,朋友突然问了我一个问题,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指向的问题。待完善。。。

 

标签: 暂无
最后更新:2017年08月30日

愚墨

保持饥渴的专注,追求最佳的品质

点赞
< 上一篇
下一篇 >

文章评论

  • homes for sale in Olympia

    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

    2016年07月28日
    回复
    • manster

      @homes for sale in Olympia thanks,虽然我不知道你在说什么。

      2016年07月28日
      回复
  • 取消回复

    搜搜看看
    历史遗迹
    • 2023年5月
    • 2022年9月
    • 2022年3月
    • 2022年2月
    • 2021年12月
    • 2021年8月
    • 2021年7月
    • 2021年5月
    • 2021年4月
    • 2021年2月
    • 2021年1月
    • 2020年12月
    • 2020年11月
    • 2020年9月
    • 2020年7月
    • 2020年5月
    • 2020年4月
    • 2020年3月
    • 2020年1月
    • 2019年5月
    • 2019年3月
    • 2019年2月
    • 2019年1月
    • 2018年9月
    • 2018年3月
    • 2018年2月
    • 2018年1月
    • 2017年11月
    • 2017年7月
    • 2017年6月
    • 2017年3月
    • 2017年2月
    • 2017年1月
    • 2016年12月
    • 2016年11月
    • 2016年9月
    • 2016年8月
    • 2016年7月
    • 2016年6月
    • 2016年5月
    • 2016年4月
    • 2016年3月
    • 2016年2月
    • 2016年1月
    • 2015年12月
    • 2015年10月
    • 2015年9月
    • 2015年7月
    • 2015年6月
    • 2015年4月

    COPYRIGHT © 2020 愚墨的博客. ALL RIGHTS RESERVED.

    THEME KRATOS MADE BY VTROIS