应用场景
- 作为普通函数
- 使用
call
,apply
,bind
- 作为对象方法被调用
- 在
class
方法中被调用 - 箭头函数
使用要领
this
在各场景下取什么值,是在函数执行的时候确定的,不是在函数定义的时候确定的!!
下面介绍this
在各个场景中的使用:
1. 普通函数
function fn1() {
console.log(this);
};
fn1(); // window
this指向window
,这里调用fn1
函数的作用域是全局作用域。
2. 使用call,apply,bind
call
、apply
、bind
的作用都是为了改变函数的this指向。
-
call
第一个例子是关于this指向的:
window.color = 'red';
document.color = 'yellow';
var s1 = { color: 'blue' };
function changeColor() {
console.log(this.color);
}
// 以下注释中的“=>”是指向的意思~
changeColor.call(); // red (不传就是默认 changeColor为全局函数,this => 全局)
changeColor.call(window); // red (this => 全局)
changeColor.call(document); // yellow (this => document)
changeColor.call(this); // red (this => 全局作用域)
changeColor.call(s1); // blue (this => s1这个对象)
第二个例子是关于传参的:
var obj = {
name: '夏洛'
}
function func(age, grade) {
console.log(`${age}岁的${this.name}上${grade}年级`);
}
func.call(obj, '20', '五'); // '20岁的夏洛上五年级'
func.call(obj, '20'); // '20岁的夏洛上undefined年级'
func.call('20', '五'); // '五岁的undefined上undefined年级'
// 第一个参数永远是你要指向的对象
参数多传了人家函数也不接收,少传或者不传人家找不到这个值,就会报undefined
。
总结:
对于一个函数:
var func = function(arg1, arg2) {}
我们就酱调用:
func.call(this, arg1, arg2)
其中,this
是你想要指定的上下文对象(就是你想要指定this的区域),arg1
,arg2
是你传递的参数。
-
apply
apply和call一样,第一个例子就省略啦
下面看apply的传值:
var obj = {
name: '夏洛'
}
function func(age, grade) {
console.log(`${age}岁的${this.name}上${grade}年级`);
}
func.apply(obj, ['20', '五']); // '20岁的夏洛上五年级'
func.call(obj, ['20']); // '20岁的夏洛上undefined年级'
func.call(['20', '五']); // 'undefined岁的undefined上undefined年级'
func.call(obj); // 'VM2914:5 undefined岁的夏洛上undefined年级'
有人说,我参数不写成数组行不行?
那指定不行,而且会报这个错:
Uncaught TypeError: CreateListFromArrayLike called on non-object
总结:
apply
和call
一样,只不过二者在传参的时候形式不一样
apply
是数组形式,call
是参数列表(直接传就完事)
所以,对于一个函数:
var func = function(arg1, arg2) {};
我们就酱调用:
func.apply(this, [arg1, arg2]);
-
bind
其实,bind和call是很相似的,也可以改变函数体内this
的指向,只不过call直接就调用了,而bind返回的是一个函数,需要我们再调用一下就好啦
下面的是bind的例子:
function fn1() {
console.log(this);
};
const fn2 = fn1.bind({ x: 200 })
fn2(); // { x: 200 }
总结:
对于一个函数:
var func = function(arg1, arg2) {};
我们就酱调用:
func.bind(this, arg1, arg2)(); // 注意这里我们要调用一次
3. 对象方法调用
看一个不那么普通的🌰:
const xialuo = {
name: '夏洛'
love() {
console.log(`${this.name}喜欢秋雅`); // this 指当前对象xialuo
},
wait() {
setTimeout(function() {
console.log(`${this.name}等马冬梅一起回家`); // this 指window
})
}
}
xialuo.love()
的中的this指的就是xialuo,这没有问题
xialuo.wait()
的中的this就不是指的xialuo这个对象了,因为setTimeout
这个函数调用的时候和this
的第一个情况(当做普通函数执行)是一样的,也就是说,这个函数执行是setTimeout
本身触发的执行,它不是xialuo.love
这种方式触发的。
4. 箭头函数调用
🌰:(还是夏洛)
const xialuo = {
name: '夏洛'
love() {
console.log(`${this.name}喜欢秋雅`); // this 指当前对象xialuo
},
wait() {
setTimeout(() => {
console.log(`${this.name}等马冬梅一起回家`); // this 指当前对象
})
}
}
ps:箭头函数的this
永远取它上级作用域的this
!!!它自己本身不会决定this
的值。
5. class
class People {
constructor(name) {
this.name = name;
this.age = 20;
}
sayHi() {
console.log(this);
}
}
const xialuo = new People('夏洛');
xialuo.sayHi(); // xialuo 对象