this 的指向

18 阅读2分钟

this指向

总结this的指向

  1. 直接调用函数,this 指向全局对象(严格模式是 undefined)
  2. 在函数外,this 指向全局对象(严格模式是 undefined)
  3. 通过对象调用或 new 一个函数,this 指向调用的对象或新对象
  4. 使用call/apply/bind 方法调用,this 指向被绑定的对象
  5. 箭头函数中的 this 有外层(函数或全局)作用域来决定的

一个个举例

1. 直接调用函数,this 指向全局对象(严格模式是 undefined)

function sayName() {
  console.log(this); // global
  console.log(this.name); // undefined
}

sayName(); // this => global
'use strict';
function sayName() {
  console.log(this); // undefined
  console.log(this.name); // TypeError: Cannot read property 'name' of undefined
}

sayName(); // this => undefined

2. 在函数外,this 指向全局对象(严格模式是 undefined)

console.log(this === module.exports); // true 

Tips:

当在Node REPL 交互环境中输入 this === global 才为 true,因为在 一个 js 文件中执行时,Node 文件顶层 this 是模块导出对象,只有全局作用域 / 独立函数调用,this 才是 global

image.png

'use strict';
console.log(this === module.exports); // true

总结:

执行环境this 指向this === global
Node .js 文件顶层module.exports❌ false
Node REPL 命令行global(全局对象)✅ true
普通函数独立调用(非严格)global✅ true
普通函数独立调用(严格)undefined❌ false
定时器 / IO 回调(非严格)global✅ true
箭头函数继承外层 this视情况而定

3. 通过对象调用或 new 一个函数,this 指向调用的对象或新对象

function Person() {
  this.name = 'summer';
}

let person = new Person();

console.log(person.name); // summer

4. 使用call/apply/bind 方法调用,this 指向被绑定的对象

function sayName() {
  console.log(this.name);
}

let person = {
  name: 'summer',
};

sayName.call(person); // summer

5. 箭头函数中的 this 有外层(函数或全局)作用域来决定的

let sayName = () => {
  console.log(this);
};

sayName(); // module.exports

箭头函数不新开 this,直接借外面的

const obj = {
  name: '张三',
  say: function() {
    setTimeout(() => {
      // 箭头函数:继承外层 say 函数的 this(就是 obj)
      console.log(this.name); // 张三
    }, 1000);
  }
};
obj.say();

普通函数有自己的 this,作为普通函数调用时,会在其执行上下文中将其 this 指向 window,因为它是独立调用的。

const obj = {
  name: '张三',
  say: function () {
    setTimeout(function () {
      // 普通函数:定时器回调独立调用,this → 全局(window/global)
      console.log(this.name); // undefined
    }, 1000);
  },
};

obj.say();

核心原理

普通函数:this 只由「调用方式」决定,和 定义位置、作用域、闭包、[[Scope]] 全都无关。

箭头函数:this 只由定义时的外层作用域决定,跟怎么调用完全无关