bind、call、apply的区别
js中有三个改变函数this指向的方法分别是bind、call、apply。
- call方法
接收多个参数,第一个参数是要函数内部this的指向,第二参数往后都是函数接收的参数,当第一个参数为undefined或者null的时候函数的this默认指向window。改变this指向的后会立即调用该函数。(只是临时改变一次this指向)const obj = { a: 1, b: 2 } function setValue(n1,n2) { this.c = n1; this.d = n2; console.log(this) } setValue(3.4) //Window{...} setValue.call(obj,3,4) //{a: 1, b: 2, c: 3, d: 4} setValue(3.4) //Window{...}
- apply方法
接收两个参数,第一个参数是要函数内部this的指向,第二个参数是函数接收的参数,是一个数组,与call方法一样当第一个参数为undefined或者null的时候函数的this默认指向window。改变this指向后悔立即执行该函数。(也只是临时改变一次this指向)
const obj = {
a: 1,
b: 2
}
function setValue(n1,n2) {
this.c = n1;
this.d = n2;
console.log(this)
}
setValue(3,4)//Window{...}
setValue.apply(obj,[3,4]) //{a: 1, b: 2, c: 3, d: 4}
setValue(3.4)//Window{...}
- bind方法
传参与call方法类似,第一个参数传入的是函数的this指向,第二参数往后都是函数接收的参数,与call不同call是一次性传入所有参数,bind除了第一个参数外,后面要传入函数的可以分两次或多次传入,它不会立即调用函数,会返回一个永远改变this指向的新函数。
const obj = {
a: 1,
b: 2
}
function setValue1(n1,n2) {
this.c = n1;
this.d = n2;
console.log(this)
}
let setValue2 = setValue1.bind(obj,3)
setValue2(4) //{a: 1, b: 2, c: 3, d: 4}
//可以看出函数参数可以分两次传递,最后函数运行时会把所有的参数串联起来传入执行
可以简单来实现bind方法
Function.prototype.mybind= function () {
//记录当前this(此时this为调用mybind的函数)
let _this = this
// 1. 将第一个参数保存下来
let obj = Array.prototype.shift.call(arguments);
//保存除第一参数以外,后面的传入参数
var args = Array.prototype.slice.call(arguments, 0);
return function () {
//获取后面调用新函数传入参数
var curArg = Array.from(arguments);
//将第一次传入的参数与第二次传入的参数拼接起来
var total = args.concat(curArg)
//改变this指向并调用函数
return _this.apply(obj, total);
}
}
总结:
- 它们三个都可以改变函数的this对象指向。
- 它们三个的第一个参数都是this要指向的对象,如果没有传入这个参数或传入参数为undefined或null,则默认指向全局window。
- 它们三个都可以为函数传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入所有参数,而bind可以分为两次或多次传入。bind 是返回绑定this之后的函数,便于后续调用;apply 、call 则是改变this指向后立即调用