js中this的指向容易让人迷惑,这是因为跟编译型的语言不通,this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。注意:this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this就是这个记录的一个属性,会在函数执行的过程中用到。
调用栈
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this就是这个记录的一个属性,会在函数执行的过程中用到。
从调用栈来看,函数被调用的位置就是当前执行函数的前一个调用函数;
- 由于一些设计模式的问题,函数的调用栈可能并不是那么好分析;
绑定规则
我们经常会看到的一种说法:this永远指向调用它的位置。
- 默认绑定?好像没有意义,默认this指向全局
- 隐式绑定:
- this指向调用它的对象,是一种很常见的形式
- 但这种形式会不经意间出现丢失this绑定的情况,比如这段代码:
var a = 100
const foo = function(){
console.log(this.a)
}
const foo = {
a:1,
b:foo
}
foo.b() // 1
const bar = foo.b
bar() // 100 因为此时相当于直接调用foo(),foo中的this指向了全局
- 显式绑定
- call、apply、bind等方法
- new 绑定
这里有一点注意,js种并不存在构造函数,而只有对函数的"构造调用"
使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
1.创建(或者说构造)一个全新的对象。
2.这个新对象会被执行[[Prototype]]连接。
3.这个新对象会绑定到函数调用的this。
4.如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
1.函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。[插图]2.函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是指定的对象。[插图]3.函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。[插图]4.如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象。
箭头函数的this
箭头函数的this指向的是箭头函数声明的位置,而不是绑定的位置
箭头函数则不同,它们不绑定自己的 this。箭头函数的 this 值由外围(封闭)作用域的 this 确定,这通常被称为 "词法作用域" 或 "静态作用域"。在箭头函数创建时,this 的值就被永久固定下来了,与函数如何被调用或是否使用 call、apply 无关。