[ apply-bind-call 思考 上 | 青训营笔记]

59 阅读2分钟

前置知识: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的不同之处

    1. 箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,自己本身并没有this值;
    2. 箭头函数的this永远指向其上下文的this,任何方法都改变不了其指向,如call(), bind(), apply()。