javascript 的bind/apply/call函数

javascript有三个使用频率非常高的内建函数:bind/apply/call。许多高级点的技巧都是基于这几个函数来实现的。这三个函数都用于改变函数的执行环境.从而达到代码复用的目的。
先来所说bind函数, bind,函数通常有两个用途:

1. 创建新函数,指定函数的this指针。

name = ‘global‘;
var obj1 = {name: ‘foo‘};
var showName = function() {
    console.log(this.name);
}
showName(); //global

var showObj = showName.bind(obj1);
showObj(); // foo

2. bind函数体现出偏函数的思维,可以有效减少匿名函数的使用,譬如,有一个接收用户不同请求并分发处理的模块:

//query: 请求参数
//config:不同请求的配置信息
function dispatcher(query, config) {
       var action = query.action;
       switch(action){
            case ‘action1‘:{
            //....
                break;
            }
        }
}

dispatcher函数执行的操作都是类似的,只是不同的用户请求需要不同的config配置信息。可以有如下做法:

function createDispatcher(config) {
    return function(query) {
        dispatcher(query, config);
    };
}

当然如果需要多个参数也可以这样搞:

function createDispatcher(config, ext) {
    //借用Array原型对象的slice函数把函数参数拷贝一份
    var args = Array.prototype.slice.call(arguments);
    return function (query) {
        var newArgs = args.push(query);
        dispatcher.apply(null, newArgs);
    }; 
}

如果通过bind来实现,可以这样搞:

function dispatcher(config, query) {
    //
}

//创建分发函数
var dispatch1 = dispatcher.bind(null, config1);
var dispatch2 = dispatcher.bind(null, config2);
var dispatch3 = dispatcher.bind(null, config3);

在这里我们不需要改变bind返回的偏函数的this指针,所以bind函数第一个参数传null。只需要指定一个固定的参数。所以一句话就搞定了。

再说说apply函数,apply和call函数可以方便的实现函数借用。javascript这种基于原型继承的语言,基础类型的原型为我们提供了许多方便的内建函数,譬如,我要把上面的分发函数写成一个通用的模块,即:把分发行为也抽象出来,由使用者来指定函数行为。createDispatcher只是收集用户参数并调用指定的动作函数:

function createDispatcher(doit, context) {
    var args = Array.prototype.slice.call(arguments, 2);
    return function() {
        doit.apply(context, args.concat(Array.prototype.slice.call(arguments));
    }
}

var obj1 = {name: ‘obj1‘};
var obj2 = {name: ‘obj2‘};
var showParams1 = function() {
    console.log(this.name + ‘got it: ‘ + arguments.join(‘+‘));
};

var showParams2 = function() {
    console.log(this.name + ‘got it: ‘ + arguments.join(‘-‘));
};
//obj1 got it: 1+2+3
createDispatcher(showParams1, obj1)(1, 2, 3);
//obj2 got it: 4-5-6
createDispatcher(showParams2, obj2)(4, 5, 6);

apply与call的唯一区别是apply通过数组的形式传参,而call需要把参数列在函数后面,可以认为apply是javascript语言基于call构造的一个语法糖罢了~

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。