前言
关于javascript中的this究竟指的是什么,已经有很多文章写过,在这里总结一下。
书中的重要观点
- this的指向并不是指向函数本身或函数的词法作用域;
- this的值是在函数调用时才绑定的,创建时并没有绑定this;
- this的指向取决于在何处被调用。
函数的调用模式
在说this的绑定方式之前,我们先谈谈函数的调用。调用一个函数时,会暂停当前函数的执行传递控制权和参数给调用的函数。除了函数声明时定义的形参,函数还会接受两个附加的参数: arguments和this,arguments即函数的入参,this的指向和函数的调用模式有关。
在javascript中,函数的调用模式一般分为四种:方法调用模式、函数调用模式、构造器调用模式、apply调用模式。
- 方法调用模式
当一个函数作为一个对象的一个属性时,我们称之为方法。当一个方法被调用时,函数的this指向调用该方法的对象。 - 函数调用模式
当一个函数不作为一个对象的属性时,就是我们最常见的函数调用模式。在这种情况下如果是非严格模式(non-strict mode)下运行则this指向全局对象,浏览器下为window,node模式下为global。 - 构造器调用模式
当一个函数被当做“构造函数”(严格来讲构造函数和普通函数没有区别),当我们用关键字new来以“构造函数”为蓝图来创建一个对象时,函数中的this就会指向创建的对象实例。 - apply调用模式
apply方法让我们构建一个参数数组传给需要调用的函数,apply接受两个参数,第一个为this绑定的值,第二个即需要传入的参数数组。apply方法可以显式地绑定this的值,类似的还有bind和call,需要注意地是,bind方法是返回一个新的函数。
this判断规则
- 看是否由 new 调用?是则绑定到新创建的对象。
- 再看是否由 call 或者 apply (或者 bind )调用?绑定到指定的对象。
- 看函数是否为上下文对象的方法调用?是则绑定到那个上下文调用方法的对象。(特点是用"."或者"[ ]"来调用)
- 默认函数调用:在严格模式下绑定到 undefined ,否则绑定到全局对象。
ES6 中的箭头函数并不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定this ,具体来说,箭头函数会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。这其实和 ES6 之前代码中的 self = this 机制一样。
tips:
- 回调函数丢失 this 绑定是非常常见的,如settimeout();
- 一些流行的JavaScript 库中事件处理器常会把回调函数的 this 强制绑定到触发事件的 DOM 元素上。