this指向
this指向当前函数的调用者,如果当前函数没有调用者,那么this指向全局对象。
普通函数
谁调用这个函数,this就指向谁
需要注意的是严格模式下,普通函数的指向是undefined
js
function foo() {
console.log(this);
}
foo(); // window
setTimeout(function() {
console.log(this);
})
// window 其实本质上是window.setTimeout
js
var obj = {
foo: function() {
console.log(this);
}
};
obj.foo(); // obj
箭头函数
箭头函数没有自己的this,它继承自最近作用域的this。
js
var obj = {
foo: function() {
console.log(this);
},
bar: () => {
console.log(this);
}
};
obj.foo(); // obj
obj.bar(); // window
构造函数
构造函数的this指向实例对象
js
function Foo() {
console.log(this);
}
new Foo(); // Foo {}
改变this指向
- call
- apply
- bind
使用
js
function foo() {
console.log(this);
}
foo.call({ name: 'foo' }); // { name: 'foo' }
foo.apply({ name: 'foo' }); // { name: 'foo' }
foo.bind({ name: 'foo' })(); // { name: 'foo' }
1、call
call的参数,第一个参数是this指向的对象,后面的参数是函数的参数 函数立即执行
js
function foo() {
console.log(this);
}
foo.call({ name: 'foo' }); // { name: 'foo' }
call的参数,第一个参数是this指向的对象,后面的参数是函数的参数
js
function foo(a, b) {
console.log(this, a, b);
}
foo.call({ name: 'foo' }, 1, 2);
// { name: 'foo' } 1 2
2、apply
apply的参数,第一个参数是this指向的对象,第二个参数是函数的参数数组
函数立即执行
js
function foo() {
console.log(this);
}
foo.apply({ name: 'foo' }); // { name: 'foo' }
使用场景:数组最大值
js
const arr = [1, 2, 3, 4, 5];
console.log(Math.max.apply(null, arr)); // 5
3、bind
bind返回一个函数,不会立即执行
js
function foo() {
console.log(this);
}
foo.bind({ name: 'foo' })(); // { name: 'foo' }
4、总结call apply bind
相同点
- 都是用来改变this指向的
- 都可以用来调用函数
不同点
- call和apply会立即执行函数
- bind不会立即执行函数,会返回一个函数
call和apply的区别
- call的参数是逐个传入的
call({}, 1, 2, 3)
- apply的参数是数组
apply({}, [1, 2, 3])
应用场景
- call调用函数并传递参数
- apply经常用来处理数组
- bind经常用来改变this指向并且不立即执行函数,例如:事件处理函数、定时器函数
箭头函数
- 箭头函数没有this,箭头函数的this指向的是定义时的this,而不是执行时的this
js
function foo() {
console.log(this);
return () => {
console.log(this); // 定义时的this 指向的是foo函数的this
};
}
foo.call({ name: 'foo' })(); // { name: 'foo' } { name: 'foo' }
- 箭头函数没有arguments
js
function foo() {
console.log(arguments);
return () => {
console.log(arguments); // 报错
};
}
foo.call({ name: 'foo' })(); // { name: 'foo' } { name: 'foo' }