上文中提到了JavaScript中的this指向问题,文本文是用三种方法来改变this的指向的。
改变this指向有三种办法
1.箭头函数
2.call或者apply
3.bind
下面就介绍这三种具体是怎么改变的
1.箭头函数
var a = 100;
let obj = {
a: 1,
fn() {
//this->obj
console.log(this.a);
setTimeout(() => {
//this->obj
console.log(this);//obj
console.log(this.a);//1
}, 1000);
}
}
// obj.fn() // 1 obj 1
let test = obj.fn;
// test->内部的this是window
// 延时器的箭头函数的环境变成 了 window
test();
2.call或者apply
(1)call是函数的方法
call(a, b, c)
方法接收三个参数,第一个是this指向,第二个,三个是传递给函数的实参,可以是数字,字符串,数组等类型的数据类型都可以。
function fn(a, b) {
console.log(this, a, b);
}
// fn(100, 200);//window 100 200
let obj = { name: 'zhangsan' }
fn.call(obj, 100, 200)//{name: 'zhangsan'} 100 200
(2)apply(a, [b])
和call基本上一致,唯一区别在于传参方式,apply把需要传递给fn()
的参数放到一个数组(或者类数组)中传递进去,虽然写的是一个数组,但是也相当于给fn()
一个个的传递。
function fn(a, b) {
console.log(this, a, b);
}
// fn(100, 200);//window 100 200
let obj = { name: 'zhangsan' }
fn.apply(obj, [100, 200])//{name: 'zhangsan'} 100 200
3.bind
bind(a, b, c)
:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8
bind与call的唯一区别就是call直接改变函数的指向,而bind是生成了一个新函数()
,该函数改变了指向。
function fn(a, b) {
console.log(this, a, b);
}
let obj1 = { name: 'zhangsan' }
let resFn = fn.bind(obj);
console.log(resFn);
console.log(resFn == fn);//false
// 不会调用fn函数,不会影响原函数fn里面的this,
// fn(100,200) window 100 200
// {name: 'zhangsan'} 100 200
// 第一个参数的值 会改变 新函数resFn调用的时候的this
resFn(100, 200)
总结:
2---1 call
1-是函数的方法
2-fn.call(obj,arg1,arg2,...)
调用fn这个函数,并且 会改变fn执行的时候的this 为 obj,剩余的参数 会作为 实参 传入 fn 内部,arg1,arg2,
2---2 apply
1-是函数的方法
2-fn.apply(obj,[arg1,arg2,...])
调用fn这个函数,
第一个参数 改变this ,,会改变fn执行的时候的this 为 obj,
第二个参数 会作为 实参 传入 fn 内部,arg1,arg2,
3----bind 给一个函数绑定this
1-是函数的方法
2- let resFn = fn.bind(obj)
不会调用fn函数,不会影响原函数fn里面的this,返回一个新函数resFn,
第一个参数的值 会改变 新函数resFn调用的时候的this
resFn 和 fn 内的代码是一样