bind 方法和 call、apply 方法都是用来改变函数的 this 上下文的。
(1)bind 方法会创建一个新的函数,当被调用时,将设置其 this 关键字为提供的值,在提供的参数加上原函数的参数一起传入原函数执行。
(2)bind 方法不会立即执行函数,而是返回一个新的函数,这个新的函数的 this 值被绑定到了指定的对象,调用时也可以传入参数。同时使用 bind 方法可以实现柯里化,即将函数转化为接收部分参数的函数。
(3)call 方法在调用一个函数时会立即提供所有参数。
总结:bind 创建一个新函数,call 和 apply 立即调用函数。call 和 apply 的区别在于参数的传递方式不同,call 传递参数列表,而 apply 传递参数数组。
手写实现call
Call和apply相同点:
-
两者都用于改变函数上下文,第一个参数就是用来指定函数执行时的上下文。
-
两者实现时都调用函数的内置函数[[Call]]。
-
第一个参数为null或undefined,则用全局对象替换this。
fun.call(this, arg1,arg2,...)
(1) 参数: call函数的第一个参数是在 ‘fun’函数运行时指定的 this 值,它和我们函数内部的this 指向不是一回事
(2) 返回值: call函数的返回值,是调用call函数的函数返回值
Function.prototype.call (thisArg , arg1 , arg2, … )
function myCall(context) {
// 判断this是否是函数
if(typeof this !== 'function') {
throw new Error('this is not a function');
}
// 形参不一定会传
let context = context || window;
// let args = Array.prototype.slice.call(arguments, 1);
// call函数有传参,利用argument取参,但是要去除第一个
let args = [...arguments].slice(1);
// this 是一个函数 context是我们想改变指向的man对象
// 调用person.getName 就使用this
context.fn = this;
// getName的函数 this 指向man
let result = context.fn(args);
// context.fn 并不是真正存在 所以用完后要删掉
delete context.fn;
return result;
}
person.getName.myCall(man);
手写实现apply
Function.prototype.apply (thisArg, argArray)
Function.prototype.myApply = function (context, args) {
// 默认不传就是window,
let context = context || window;
// 判断参数 有显示,没有先是空数组
let args = args || [];
context.fn = this;
// 通过隐式绑定的方式调用函数
let result = context.fn(...args);
// 删除添加的属性
delete context.fn;
return result;
}
手写实现bind
bind方法允许我们绑定函数的上下文并返回一个新的函数. bind 方法会创建一个新的函数,当被调用时,将设置其 this 关键字为提供的值,在提供的参数加上原函数的参数一起传入原函数执行。
Function.bind(thisArg, arg1,arg2,...)
(1). 创建一个新函数。
(2). 将新函数的this值绑定为指定的thisArg值。
(3). 将新函数的参数与绑定函数的参数合并。
(4). 调用绑定函数,将绑定函数的结果返回给新函数。
注意:
与call和apply不一样的地方是,这里还需要设置一下返回的那个函数的原型,采用继承的方式,不能直接 = ,要采用一个中介函数fn来辅助改变_fn的原型。
function myBind(context) {
context = context || window;
if (typeof this !== "function") {
return;
}
var self = this;
// let args = [...arguments].splice(1);
var args = Array.prototype.slice(arguments, 1);
var A = function() {};
var B = function() {
var _this = this instanceof A ? this : context;
return self.apply(_this, args.concat(Array.prototype.slice.call(arguments, 0)));
}
if (this.prototype) {
A.prototype = this.prototype;
}
B.prototype = new A();
return B;
}
以上是学习和总结。