这两天看sf,偶然看到一些讨论js中原生实现apply和bind方法等帖子,觉得挺好玩儿,自己也照着思路试了一下,发现果然还是要自己写代码跑跑看,本来觉得思路已经有了,自己在实现的时候还是遇到了一些思路卡顿的状况,所以就记录一下啦。先上一个MDN上对Function.prototype.apply 和 Function.prototype.bind的解释:
apply(thisArg[, argsArray]) 方法在指定 this 值和参数(参数以数组或类数组对象的形式存在)的情况下调用某个函数.
bind(thisArg[, arg1[, arg2[, …]]])方法创建一个新的函数, 当被调用时,它的this关键字被设置为提供的值 ,在调用新函数时,提供任何一个给定的参数序列
原生apply用法例子
apply_test.js源代码:
1 | var obj_a = { |
输出结果:
1 | name: obj_a |
分析:
被apply的show方法会立即执行,但是执行的时候,show函数中的this对应的上下文不再是obj_a,而是obj_b;
原生bind用法例子
bind_test.js源代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var obj_a = {
name:'obj_a',
show:function(a,b) {
console.log('name:',this.name);
console.log('param a:',a,'param b:',b);
}
};
obj_a.show(22,33);
var obj_b = {
name:'obj_b'
};
//此处返回函数dd是一个 obj_a.show同样功能的函数,但是函数的this被指定为obj_b
console.log('start bind test here:');
let dd = obj_a.show.bind(obj_b);
dd('22bind','33bind');
输出结果:1
2
3
4
5name: obj_a
param a: 22 param b: 33
start bind test here:
name: obj_b
param a: 22bind param b: 33bind
分析:此处bind返回值是一个函数,该函数具有和obj_a.show()具有同样的功能,
但是新函数中的this对应的上下文被指定为obj_a,即返回函数在创建时便被指定了this。
这里我们也可以看出bind和apply函数的区别,一个是函数立即执行,一个是返回一个新函数。
手工实现apply
思路
func_a.apply(obj_new,params_arr)函数是要在this指向obj_new的上下文中中执行目标函数func_a,同时传入参数数组params_arr,
所以我们只要在obj_new下建立一个新方法temp_func,并赋值为func_a,然后使用传入的参数params_arr执行tem_func即可。
own_apply.js源代码:
1 | //apply函数的模拟实现 |
输出结果:
1 | { '0': { name: 'obj_b' }, '1': [ '2', '3' ] } |
手工实现bind
own_bind实现思路
与own_apply不同的是,own_bind不是立即执行目标函数,而是生成一个指定了this上下文的新函数,所以与手工实现apply类似,只是不在own_bind中立即执行,
而是返回一个匿名函数,把执行放在该匿名函数中
own_bind.js源代码:
1 | //bind函数的模拟实现 |
结果输出
1 | name: obj_b |