JavaScript中this指向详解

前言

关于JavaScript中this指向问题一直是一个老大难的问题,每次遇到基本都靠蒙,很少有蒙对的时候,究其原因还是自己对this的理解不够到位,今天就带大家一起来分析一下this指向问题。
在分析之前,我们要先理解调用栈调用位置这两个名词,只有明白了这两个名词才能理解this指向问题。
调用栈是要执行该函数需要先执行的的所有函数,而调用位置就是当前执行函数的前一个执行函数的调用位置。下面来看一个例子

function fn1(){  // 调用栈fn1
  console.log('fn1')  
  fn2()  // fn2调用
}
function fn2(){  // 调用栈fn1->fn2
  console.log('fn2')
  fn3() // fn3调用
}
function fn3(){ // 调用栈fn1->fn2->fn3
  console.log('fn3')
}
fn1() // fn1调用

fn1只需要执行自己就可以了,所以调用位置为全局对象window
fn2调用会经过fn1->fn2,所以调用位置在fn1中。
fn3调用会经过fn1->fn2->fn3,所以调用位置在fn2中。

this绑定规则

理解了调用位置,我们再来讲this绑定规则。
1.默认绑定
函数执行是使用不带任何修饰的方式执行就是默认绑定。

var a = 1
function fn(){
  console.log(this.a)
}
fn() // 1

fn调用时无任何修饰,所以被默认绑定到了全局对象this中,需要注意的是严格模式下无法进行默认绑定,函数输出为undefined
2.隐式绑定
隐式绑定需要判断调用位置是否有上下文对象,即被某个对象包含。

var a = 1;
function fn(){
  console.log(this.a)
}
const obj = {
  a:2,
  fn:fn
}
obj.fn() // 2

调用位置使用obj上下文来引用函数,所以最终结果为2而不是1。

function fn(){
  console.log(this.a)
}
var obj = {
   a: 2,
   fn: fn
}
var fn1 = obj.fn
var a = 1;
fn1() // 1

在上面的例子中虽然fn有上下文对象,但是将obj.fn赋值给fn1后,可以理解为在这里直接声明的fn1函数,没有上下文对象,所以最终结果是1,这就是隐式丢失。
3.显示绑定
显示绑定就是使用关键字apply、call、bind给函数指定绑定的this对象,显示绑定的this指向无法修改,无论怎么调用都指向绑定的内容。

function fn(){
  console.log(this.a)
}
var obj = {
  a:2
}
var fn1 = function(){
  fn.apply(obj) // 使用call、bind结果一样
}
fn1() // 2
fn1.call(window)  // 无法更改

4.new绑定
new绑定会创建一个新的对象;这个对象会执行[Prototype]链接;这个对象会绑定到函数调用的this;如果该函数没有返回值,new操作会自动返回该对象

function fn(){
  console.log(this.a)
}
var fn1 = new fn(2)
console.log(fn1.a) // 2

总结

1.有new绑定则this绑定返回的对象。
2.有bind、call、applythis绑定指定的对象
3.有上下文对象则绑定上下文对象。
4.都没有则默认绑定。

猜你喜欢

转载自blog.csdn.net/Salange1/article/details/127542938