js实现 bind call apply
很多面试题上都提到 使用 js 实现 bind call apply, 于是稍微尝试了一下,在此记录一下
bind
对于 Function.prototype.bind 这个方法,就是改变函数的上下文环境,并返回一个新函数,原函数不受影响。先看我实现的代码:
var obj = {
name: 'dcw'
};
function fn (a, b) {
console.log(a, b)
console.log(this.name);
}
Function.prototype.myBind = function (obj) {
var arg = [...arguments];
arg.shift();
var res = this.call(obj, ...arg);
return function () {
return res;
}
}
fn.myBind(obj, 1, 2)()
说明
用了添加内置方法的办法,在这里只是为了方便大家 review ,实际上我不喜欢这种写法,主要是因为难以维护,我更喜欢引入相关模块的方法。在代码里,可以看到,手工实现 bind 的方法就是利用闭包保存使用 call 方法返回的结果,然后在返回的函数中引用即可。当然你也可以使用 apply 方法计算 res,一样。
call 和 apply
call 和 apply 与 bind 的不同在于,它俩会立即执行函数,而 call 和 apply不同的地方在于,call 里面的函数参数是散列的,而 apply 传入的是参数的数组。先看下我实现的代码:
var obj = {
name: 'dcw'
};
function fn (a, b) {
console.log(a, b)
console.log(this.name);
}
Function.prototype.myCall = function (obj) {
var arg = [...arguments];
arg.shift();
var tempObj = Object.create(obj);
tempObj.fn = this;
tempObj.fn(...arg);
}
Function.prototype.myApply = function (obj) {
var arg = arguments[1];
var tempObj = Object.create(obj);
tempObj.fn = this;
tempObj.fn(...arg);
}
fn.myCall(obj, 1, 2)
fn.myApply(obj, [1, 2])
说明
实现call 和 apply 的办法就是初始化一个对象,该对象可以访问给定对象的所以属性,然后将方法挂载到新建的对象,然后调用新对象中的方法,在此我用了原型链的办法,当然你也可以使用深拷贝的方法复制该对象,然后调用。在这里需要注意的是,注意 arguments 中第一个参数不是我们想要的。