JS中的函数绑定以及实现函数柯里化

版权声明:如果这篇文章对你有所帮助,请点个赞~~~ https://blog.csdn.net/qq_35087256/article/details/81545988

假设页面有个按钮btn,实现点击打印message信息和事件类型(暂只介绍ES5,js新的提案中提出了“函数绑定”(function bind)运算符::)。

第一步:

var handler = {
    message:'hello world',
    handleClick:function(e){
        console.log(this.message)
        console.log(e.type)
    }
}

btn.addEventListener('click', handler.handleClick ,false);

预期中,结果打印hello world、click,结果却是:undefined、click.

根据闭包 的特性,上面代码中handler.handleClick()的上下文环境没有得到保留,所以在函数内部this的指向不是handler而是btn对象,所以不存在message属性。

第二步:

我们可以使用一个闭包去修复上面this指向问题。

var handler = {
    message:'hello world',
    handleClick:function(e){
        console.log(this.message)
        console.log(e.type)
    }
}

btn.addEventListener('click', function(e){
    handler.handleClick(e);
} ,false)

结果打印hello world、click,没有问题。

第三步:

我们可以构建一个通用的函数bind(),用于将函数绑定到指定上下文环境。

function bind(fn,context){
    return function(){
        fn.apply(context, arguments)
    }
}

btn.addEventListener('click', bind(handler.handleClick,handler) ,false)

结果打印hello world、click,没有问题。

bind()中使用了apply改变了fn的上下文环境。arguments是内部匿名函数的,而非bind的。所以可以拿到对应的event参数。

bind的简单使用:

Function.prototype.bind():bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

btn.addEventListener('click', handler.handleClick.bind(handler) ,false)

结果打印hello world、click,没有问题。

关于bind的Polyfill,MDN介绍的很详细,用于兼容部分浏览器。

第四步:

使用函数柯里化,加入额外参数。

var handler = {
    message:'hello world',
    handleClick:function(params, e){
        console.log(this.message)
        console.log(e.type)
        console.log(params)
    }
}

function bind(fn,context){
    var fnArgs = Array.prototype.slice.call(arguments, 2);
    return function(){
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = fnArgs.concat(innerArgs);
        fn.apply(context, finalArgs)
    }
}

btn.addEventListener('click', bind(handler.handleClick,handler,'first args') ,false)

结果打印hello world , click , first args

ES5的 bind() 方法也实现函数柯里化,只要在 this 的值之后再传入额外参数

var handler = {
    message:'hello world',
    handleClick:function(params1, params2, e){
        console.log(this.message)
        console.log(e.type)
        console.log(params1)
        console.log(params2)
    }
}


btn.addEventListener('click', handler.handleClick.bind(handler, 'first args', 'second args') ,false)

结果打印hello world , click , first args, second args

猜你喜欢

转载自blog.csdn.net/qq_35087256/article/details/81545988