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