前置知识:this
(👁️ 注意这里说的内容是基于JavaScript这门语言来的,可能会与其它语言中同词不同意,本部分内容来自《你所不知道的JavaScript》一书, getify/You-Dont-Know-JS: A book series on JavaScript. @YDKJS on twitter. (github.com))
常见的两个误区
- 函数中的
this并不是指向函数(function)自身
this也并不是指向方法(method)所属的对象
正式聊聊this是什么
- 先聊一下什么是作用域(scope)
function scopeDemo() {
let bar = 1;
let foo = 2;
}
对于scopeDemo这个函数来说,它的作用域是被{}这对花括号包裹的内容,比如变量bar就在scopeDemo该函数的作用域当中。不难看出作用域是静态的,基于函数是如何定义的。
- 再来看下(执行)上下文([execute]context),
this便是指向这个动态的执行上下文 - 当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。
- 全局上下文 => 无论是否在严格模式下,在全局执行环境中(在任何函数体外部)
this都指向全局对象; 在严格模式下,如果进入执行环境时没有设置this的值,this会保持为undefined - 函数上下文 => 在函数内部,在函数内部,
this的值取决于函数被调用的方式 - 类的上下文 这边没有介绍,虽与函数上下文有一定区别,但大体上相似,细节请查询MDN文档
函数的上下文是动态的,取决于函数是如何被调用的,比如说以下的这个函数中的this.topic的值,就取决于该函数执行时的上下文。
function classroom(teacher) {
return function study() {
console.log(
`${ teacher } says to study ${ this.topic }`
);
};
}
var assignment = classroom("Kyle");
- 下面的内容会涉及一些
call、闭包等一些还没介绍,你可能不太熟的内容,但无伤大雅,相信你可以看的懂的。
// 和上面那段代码是连贯的,注意一下
var homework = {
topic: "JS",
assignment: assignment
};
var otherHomework = {
topic: "Math"
};
homework.assignment();
// Kyle says to study JS
// otherHomework.assignment();
// 如果执行以上那行 会出现类似以下的错误
// otherHomework.assignment();
^
// TypeError: otherHomework.assignment is not a function
// 以下使用call将assignment的执行上下文指定为otherHomework,函数便可以正常执行了
assignment.call(otherHomework);
// Kyle says to study Math
-
注意箭头函数中的this的不同之处
- 箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,自己本身并没有this值;
- 箭头函数的this永远指向其上下文的this,任何方法都改变不了其指向,如call(), bind(), apply()。