Javascript this 101 全局 this 常规函数内的 this 箭头函数内的 this 更多阅读:

2025-06-08

JavaScript 101

全球的this

this在常规函数内部

this箭头函数内部

更多阅读材料:

this是最常见的 JS 关键字之一。你随处可见它们,但很难分辨它们this是什么。

我将介绍三种可能使用的场景this:全局、常规函数内部以及箭头函数内部。这应该涵盖了大多数用法。

  1. 全球的this
  2. this在常规函数内部
  3. this箭头函数内部

让我们先看一些例子!

顺便说一下,我将在浏览器(Chrome)控制台中执行此操作,而不是在 Node 模块中。我还假设未使用严格模式。

全球的this

如果我们只是this在浏览器控制台中输入,它将引用窗口/全局对象。

this // Window {...}

var helloVar = 'helloVar'
this.helloVar // helloVar

window.helloWindow = 'helloWindow'
this.helloWindow // 'helloWindow'

const helloConst = 'helloConst'
this.helloConst // undefined

let helloLet = 'helloLet'
this.helloLet // undefined
Enter fullscreen mode Exit fullscreen mode

你会看到,letconst无法通过 调用this。它们不是存储在“对象环境记录”中,而是存储在“声明性环境记录”中。解释这一点超出了本文的范围。如果你感兴趣,可以点击这里查看链接。

this在常规函数内部

让我们从一个例子开始:

const obj = {
    breakfast: 'donut',
    wutBreakfast: function() {console.log(`I had ${this.breakfast} this morning!`)}
}
window.breakfast = 'waffles';

obj.wutBreakfast() // I had donut this morning!
Enter fullscreen mode Exit fullscreen mode

这里我们观察到thisinsidethis.breakfast指的是对象本身。查看调用 时函数调用的位置obj.wutBreakfast()。问问自己:“我的函数调用左边是否有一个对象?” 那个对象就是 yourthis所指的位置。

如果函数调用左侧没有对象怎么办?如果你调用一个函数,而函数调用左侧没有对象,你可以假设它是全局对象。在本例中,就是这个Window对象。
我们来看下一个例子:

function sayBrunch(){
    console.log(`I had ${this.brunch} for brunch!`)
}

sayBrunch() // I had undefined for brunch
Enter fullscreen mode Exit fullscreen mode

我们还没有为 brunch 定义任何内容,所以它返回 undefined。让我们在 window 对象中定义它。

window.brunch = 'oatmeal'
function sayBrunch(){
    console.log(`I had ${this.brunch} for brunch!`)
}

sayBrunch() // I had oatmeal for brunch!
Enter fullscreen mode Exit fullscreen mode

让我们再举几个例子来建立你的直觉:

window.dinner = 'pizza'
const foodObj = {
  dinner: 'spaghetti',
  sayDinner: function(){
        console.log(`I had ${this.dinner} for dinner!`)

  }
}
foodObj.sayDinner() // what does it return?
Enter fullscreen mode Exit fullscreen mode

再来一个,稍微有点变化。我们定义了一个 window appetizer 字符串和一个 mealObj.appetizer 字符串。我们从两个不同的对象调用 sayAppetizers。你觉得它们会返回什么呢?

window.appetizer = 'chocolate';

function sayAppetizer(){
    console.log(`I had ${this.appetizer} for appetizer!`)
}
const mealObj = {
  appetizer: 'ice cream',
  sayAppetizer: sayAppetizer
}
mealObj.sayAppetizer() // what does it return?
sayAppetizer() // what does it return?
Enter fullscreen mode Exit fullscreen mode

请记住,this在常规 JS 中,函数引用的是调用函数时紧邻左侧的对象。如果没有对象,则假定它是一个窗口对象。

考虑到这一点,即使我们有obj1.obj2.obj3.someFunc(),我们也知道thisinsidesomeFunc()将引用,obj3因为它是距离函数被调用位置最近的对象。

this箭头函数内部

这在箭头函数中的行为有所不同。你需要始终牢记三件事:

  1. 只有常规函数和全局函数才可以有this
  2. 箭头函数本身具有this
  3. this箭头函数内部引用 时,它会查找作用域来找到 this 值。其行为类似于词法作用域。

让我们看第一个例子:

let myObj = {
  breakfast: 'taco',
  sayBreakfast: () => {
    console.log(`I had ${this.breakfast} for breakfast`)
  }
}
window.breakfast = 'pizza'

myObj.sayBreakfast() // pizza
Enter fullscreen mode Exit fullscreen mode

让我们看看在牢记上述三条规则的情况下,这是否合理:
当我们调用 myObj.sayBreakfast() 时,它会查找 myObj,但由于 myObj没有this(规则 2),它会再查找一个,即 global/window 对象(规则 1)。它发现 global/window 有this.breakfast = 'pizza',所以打印了 pizza。

现在向对象添加一个常规函数:

let myObj = {
  breakfast: 'taco',
  sayBreakfast: () => {
    console.log(`I had ${this.breakfast} for breakfast`)
  },
  sayRegBreakfast: function() {
    console.log(`I had ${this.breakfast} and it was yummy`)
  }
}
window.breakfast = 'pizza'

myObj.sayBreakfast() // pizza
myObj.sayRegBreakfast() // taco
Enter fullscreen mode Exit fullscreen mode

您会看到,使用常规函数会给出“taco”,而使用箭头会给出“pizza”。

让我们从全局对象作用域调用一个箭头函数。我们应该预期它来自this全局作用域。是这样吗?

window.secondBreakfast = 'eggs';

const saySecondBreakfast = () => {
  console.log(`I had ${this.secondBreakfast} for second breakfast!`)
}

saySecondBreakfast() // eggs
Enter fullscreen mode Exit fullscreen mode

我当时看到这个也难以置信,所以让我们进一步证明一下。下面的例子来自getify 存档

function foo() {
    return function() {
        return function() {
            return function() {
                console.log("Id: ", this.id);
            }
        }
    }
}
foo.call( { id: 42} )()()() // undefined
Enter fullscreen mode Exit fullscreen mode

对比

function foo2() {
   return () => {
      return () => {
         return () => {
            console.log("id:", this.id);
         };
      };
   };
}
foo2.call( { id: 42 } )()()() // 42
Enter fullscreen mode Exit fullscreen mode

(顺便说一下,call分配this给我们正在调用的函数 - foo/foo2 本身 - 以及我们传递的参数对象)

请记住,只有箭头函数按词汇方式向上查找;第一个例子在第三个this嵌套函数内部查找,但没有找到任何内容,因此返回未定义。

而 foo2 在第三个嵌套函数中找不到this,于是在词法上查找下一个可用的 reg/全局函数this。它首先找到了 foo2 的this(来自foo2.call({id: 42}))(记住规则 1),因此打印 42。

如果前面第二个例子中有一个常规函数,它就不会找到它,例如:

function foo3() {
   return () => {
      return function() { // this is regular function now
         return () => {
            console.log("id:", this.id);
         };
      };
   };
}
foo3.call({id:101})()()() // undefined
Enter fullscreen mode Exit fullscreen mode

但是如果我们传入的this位置return function() {...}),它就能找到它。因为当箭头函数按词法查找并找到第一个常规函数时,该函数会被赋值this为 101。

function foo3() {
   return () => {
      return function() { 
         return () => {
            console.log("id:", this.id);
         };
      };
   };
}
foo3()().call({id: 101})() // 101
Enter fullscreen mode Exit fullscreen mode

就这样吧,伙计们!这肯定只是冰山一角,但this应该足够你入门了——双关语😁。

如果您有任何问题或发现错误请告诉我 - 感谢您的阅读并祝您编码愉快!!

更多阅读材料:

鏂囩珷鏉ユ簮锛�https://dev.to/iggredible/javascript-this-101-13j5
PREV
Redux 101 我为什么写这篇文章 没有状态管理的 React 的问题 Redux 解决的问题 关于 Redux 的四个重要概念
NEXT
Javascript Reduce 101 它有什么作用?示例:减少为单个数字;减少为数组;减少为对象;何时使用 Reduce?