JavaScript中的this关键字

176 阅读1分钟

前言

this是一个老生常谈的话题了,自己初学JS时常常迷惑,故在这里做一个小结。

  • 函数中的this是什么?

this是函数调用时的执行上下文。

  • 函数直接调用,此时函数指向全局(Global 或 Window)
function logThis() {
  console.log(this);
}

logThis(); // Global
  • 作为对象上的方法,指向调用函数的对象
const video = {
  name: "Google",
  play() {
    console.log(this.name);
  },
};

video.play(); // Google
  • 在函数的回调中使用
const video = {
  name: "Google",
  platform: "juejin",
  playAd() {
    setTimeout(function () {
      console.log(this.platform);
    }, 100);
  },
};

video.playAd(); // undefined

这里我们期望会打印出"juejin",但是回调中函数的调用点(call site)变成了全局,所以打印undefined。

  • 解决方案1:使用bind强行绑定执行上下文
const video = {
  name: "Google",
  platform: "juejin",
  playAd() {
    setTimeout(function () {
      console.log(this.platform);
    }.bind(this), 100);
  },
};

video.playAd(); // juejin
  • 解决方案2: 使用箭头函数
const video = {
  name: "Google",
  platform: "juejin",
  playAd() {
    setTimeout(() => {
      console.log(this.platform);
    }, 100);
  },
};

video.playAd(); // juejin

箭头函数本身不定义this关键字,只是向上寻找某一个定义了this的作用域。本例中是playAd函数,然后由video调用,所以此时this指向了video对象。

  • 关于对象中的箭头函数
const video = {
  name: "Google",
  platform: "juejin",
  playArrow: () => {
    console.log(this.name);
  },
};

video.playArrow(); // undefined

这里的原因是对象并不会形成一个作用域,所以箭头函数的this指向了全局。

  • class中的函数调用 (实际开发中会遇到,React & Angular)
var name = "Global";
class Video {
  constructor() {
    this.name = "Facebook";
  }
  play() {
    setTimeout(this.logName, 100);
  }
  logName() {
    console.log(this.name);
  }
}

const myVideo = new Video();
myVideo.play(); // Global

此时logName在回调中调用,this的指向了全局。

  • 解决方案同样有bind和箭头函数两种,但这里更推荐箭头函数
var name = "Global";
class Video {
  constructor() {
    this.name = "Facebook";
  }
  play() {
    setTimeout(this.logName, 100);
  }
  logName = () => {
    console.log(this.name);
  };
}

const myVideo = new Video();
myVideo.play(); // Facebook