使用bind,apply,call改变函数中this的指向
首先先举个例子
var a = 20
function test(){
console.log(this.a); // 20
}
test()
向上面这样直接执行函数,函数内部的this默认是指向全局的,在浏览器中这个this就指向window,所以this.a = 20
通过call,apply,bind方法可以改变函数内部this的指向
- call , apply
var obj1 = {
name: "obj1"
}
var obj2 = {
name: "obj2"
}
var name = "全局的name"
function printName(a, b) {
console.log(this.name, a, b);
}
printName.call(obj1, 1, 2) // obj1 1 2
printName.call(obj2, 3, 4) // obj2 3 4
printName.apply(obj1, [5, 6]) // obj1 5 6
printName.apply(obj2, [7, 8]) // obj2 7 8
call和apply的区别就在于传递参数的形式不同,第一个参数都是你想为函数指定的this,call的参数就直接以逗号隔开的方法直接写参数,而apply是以数组的形式进行传参
// call
function.call(thisArg, arg1, arg2, ......)
// apply
function.apply(thisArg, [arg1, arg2, ......])
两者的返回值都是调用call或者apply方法的函数的返回值结果,没有返回值那就是undefined
function test(){
return "哈哈哈"
}
function test1(){
return true
}
console.log(test.apply()); // 哈哈哈
console.log(test1.call()); // true
不过在指定this的时候,也可以指定是null或者undefined,不过只有在严格模式下才是真正将this指定为null或者undefined,非严格模式下,自动替换成全局对象
function test() {
console.log(this);
}
test.call(null) // window
var a = "haha"
function test() {
console.log(this.a); // haha
}
test.call(null)
- bind 方法
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用 (mdn)
它的参数同call方法
function.bind(thisArg, arg1, arg2, ......)
不同的就是返回值了,bind调用后返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
说白了,就是返回了一个新的函数,这个函数中才被绑定了你指定的this和参数,call和apply调用就执行了,bind需要手动调用返回的函数才行
var name = "全局的"
var obj = {
name: "obj的"
}
function test(n, m) {
console.log(this.name, n, m);
}
var newFn = test.bind(obj, 1, 4)
console.log(newFn);
// ƒ test(n, m) {
// console.log(this.name, n, m);
// }
newFn() // obj的 1 4
注意:bind只能绑定一次,不能再给bind返回的函数再执行bind,结果始终是以第一次绑定为准
var name = "全局的"
var obj = {
name: "obj的"
}
var obj2 = {
name: "obj2的"
}
function test(n, m) {
console.log(this.name, n, m);
}
var newFn = test.bind(obj, 1, 4)
newFn() // obj的 1 4
var newFn1 = newFn.bind(obj2, 2, 3)
newFn1() // obj的 1 4
this在箭头函数中的指向
箭头函数比较特殊,其内部并没有this绑定,它能访问到的this其实是
该函数所在的作用域指向的对象,所以大家要对作用域有所了解。箭头函数也不可以做构造函数
- 全局下
var test = () => {
console.log(this); // window
}
test()
function test() {
var innerTest = () => {
console.log(this); // window
}
innerTest()
}
test()
- 对象
var name = "全局下的name"
var obj = {
name: "obj的name",
logName: function(){
console.log(this.name); // obj的name
},
printName: () => {
console.log(this.name); // 全局下的name
}
}
obj.printName()
看到这个结果,部分同学们是不是有点小意外,箭头函数printName的this还是指向window,不是谁绑定他就指向谁。现在改一下:
var name = "全局下的name"
var obj = {
name: "obj的name",
outFn: function () {
console.log(this); // {name: 'obj的name', outFn: ƒ}
var printName = () => {
console.log(this.name); // obj的name
}
printName()
}
}
obj.outFn()
此时箭头函数printName在普通函数outFn里面,outFn的作用域的this就是指向调用它的对象
- 静态this指向
var a = 1
var obj = {
a: 2
}
var test = () => {
console.log(a);
}
test() // 1
test.call(obj) // 1
test.apply(obj) // 1
test.bind(obj)() // 1
箭头函数里面的this就是指向其当前作用域指向的this,不接受通过call等方法进行this修改。
我觉得也可以这样理解,箭头函数它在找this的时候,从里向外找,找到非箭头函数的作用域
若理解有误,希望大家批评指正