JavaScript:理解“this”关键字

2025-06-10

JavaScript:理解“this”关键字

'this'是 JavaScript 中最重要的概念之一。它是基础的一部分,你越早掌握它,你的编程生涯就会越轻松 :)

通过阅读这篇文章,确保您理解“this”的用法。

首先,简单解释一下 5 岁儿童的情况:
 

在编程中,“this”的用法'this'和普通英语的用法类似。例如,当你说“我找到工作了!太棒了!”时,我们知道“this”指的是你找到工作了。换句话说,“this”为第二句话提供了上下文。

--5岁
 

因此,要理解'this',您需要知道什么是上下文。

 

背景解释

 

上下文与对象相关。它指的是方法或属性所属的对象。您的代码开始在全局上下文中运行,在浏览器中,该上下文称为window(在 Node 中,全局对象称为global)。请看以下示例:

 

var name ='Beyonce'  

console.log(this.name)  // Beyonce 
console.log(window.name)  // Beyonce 
Enter fullscreen mode Exit fullscreen mode

 

示例中的'this'equals 是window因为我在浏览器上运行了它,其中全局对象是窗口。所以,window.name ==="Ash" 。到目前为止,上下文是窗口。好的。

现在,上下文在代码执行过程中会发生变化。每当调用对象的方法时,'this'都会设置为调用该方法的对象。

请参见下面的示例。第 4 行和第 10 行相同,但它们根据 的值记录不同的结果'this'

 

var name = 'Beyonce' 

function sayMyName(){ 
  console.log(`Your name is ${this.name}.`) //  'this' is  window 
}  

var heisenberg = { 
  name: 'Heisenberg', 
  sayMyName: function () { 
    console.log(`Your name is ${this.name}.`) //  'this' is heisenberg 
  }  
}  

sayMyName()   // Your name is Beyonce. 
heisenberg.sayMyName() // Your name is Heisenberg. 
Enter fullscreen mode Exit fullscreen mode

 

上面的代码运行良好,但是我们重复了第 4 行,这并不酷(记住:DRY 不要重复自己)。

有一种方法可以console.log()只写入一次并重复使用。为此,我们使用函数bind

 

绑定的“this”

 
Bind将给定的'this'对象应用于调用它的函数。要绑定到函数的对象将作为参数传递给 bind。

参见示例:
 

function sayMyName(){ 
  console.log(`Your name is ${this.name}.`)  
}  

var beyonce = { 
  name: 'Beyonce', 
} 

var heisenberg = { 
  name: 'Heisenberg', 
} 

let sayBeyonce= sayMyName.bind(beyonce)    
let sayHeisenberg= sayMyName.bind(heisenberg) 

sayBeyonce() // Your name is Beyonce. 
sayHeisenberg() // Your name is Heisenberg. 
Enter fullscreen mode Exit fullscreen mode

 

太棒了!现在,假设我们不想创建新函数来读出每个人的名字。我们只想使用 sayMyName() 。

我们可以使用call函数和通用的 person 对象来实现这一点。

 

'this' 调用

 
与绑定类似,call可用于将自定义值设置为'this'

参见示例:
 

var person = { 
  sayMyName: function(){ console.log(`Your name is ${this.name}.`)}; 
} 

var beyonce = { 
  name: 'Beyonce', 

};   

var heisenberg = { 
  name: 'Heisenberg', 
}; 

person.sayMyName.call(beyonce); // Your name is Beyonce. 
person.sayMyName.call(heisenberg); // Your name is Heisenberg. 
Enter fullscreen mode Exit fullscreen mode

 

箭头函数中的“this”

 
小心使用箭头函数🏹

当使用箭头函数时,它不会为 设定新值'this',而是从父作用域继承。

此示例与前一个示例相同,但使用箭头函数而不是普通函数。

控制台里输出了两次“Ash”。很奇怪吧?
 

var name = 'Ash'; 

var person = { 
  sayMyName: () => console.log(`Your name is ${this.name}.`) 
}; 

var beyonce = { 
  name: 'Beyonce', 
};  

var heisenberg = { 
  name: 'Heisenberg', 
}; 

person.sayMyName.call(beyonce); // Your name is Ash. 
person.sayMyName.call(heisenberg); // Your name is Ash. 
Enter fullscreen mode Exit fullscreen mode

 

即使你使用 call/bind 也不起作用。它仍然会打印“Ash”。为什么?

 

常规函数与箭头函数的“this”

 

常规函数将其自己的'this'对象设置给调用者。

但是箭头函数却不会。它们继承'this'自之前的上下文,也就是它所在的作用域。在本例中,就是从 window 继承。这被称为“词法作用域”。

所以,当我们使用箭头函数时,'this'它与函数的调用者没有任何关系。它仍然等于window并且保持这种状态,结果输出“Ash”。

如果我们用常规函数包装箭头函数会怎么样?

调用常规函数并将其设置'this'为调用者。

箭头函数在常规函数内部被调用。箭头函数中的 this 值继承了外部(常规)函数的 this 值。所以它成功了!

var name = 'Ash'; 

var person = { 
  sayMyName: function () { 
    const arrowFunction = () => console.log(`Your name is ${this.name}.`); 
    arrowFunction(); 
  }, 
};  

var beyonce = { 
  name: 'Beyonce', 
}; 

var heisenberg = { 
  name: 'Heisenberg', 
};  

person.sayMyName.call(beyonce); // Your name is Beyonce. 
person.sayMyName.call(heisenberg); // Your name is Heisenberg. 
Enter fullscreen mode Exit fullscreen mode

 
酷!所以使用箭头函数不好?完全不是。有很多用例需要你从周围的上下文中继承“this”。在这种情况下,箭头函数非常有用。

 

箭头函数中 this 的有用场景

 
我们来看一个例子。这里,我们想使用一个名称数组,每 2 秒记录一个不同的名称。运行此代码时,会收到错误:[Uncaught TypeError: Cannot read property 'forEach' of undefined]。
 

var people = { 
  names: ['Ash', 'Beyonce', 'Heisenberg'], 

  sayNames: function () { 

    // log each name after 1 second 
    setTimeout(function () { 
      console.log(this); 
      this.names.forEach(function (name) { 
        console.log('your name is' + name); 
      }); 
    }, 2000); 
  }, 
}; 

people.sayNames(); 
Enter fullscreen mode Exit fullscreen mode

 

为什么?

调用 sayNames 时,它会将“this”设置为 people 对象。但是调用 setTimeout 时,它会将“this”设置为 window 对象。window 没有names属性。该如何解决这个问题?

你猜对了!我们使用了一个箭头函数,它会从外部上下文继承 this。换句话说,它会'this'从 sayNames 上下文继承。
 

var people = { 
  names: ['Ash', 'Beyonce', 'Heisenberg'], 

  sayNames: function () { 
    console.log(this); 

    // log each name after 1 second 
    setTimeout( ()=> { 
      console.log(this); 
      this.names.forEach(function (name) { 
        console.log('your name is ' + name); 
      }); 
    }, 2000); 
  }, 
}; 

people.sayNames(); 
Enter fullscreen mode Exit fullscreen mode

 

关于我,让我们联系吧!👋👩‍💻

 
感谢阅读!我是一个充满热情的学习者,喜欢分享我的知识。我在这里 免费直播编程👉,并在我的推特上分享编程技巧。如果你感兴趣,欢迎来我这里聊天室跟我打个招呼😁
 

 

鏂囩珷鏉ユ簮锛�https://dev.to/simonpaix/javascript-understand-this-keyword-55j
PREV
关于学习 Vim
NEXT
Showdev:我们正在构建一款在线会议应用程序 - Collabify 🎉🎦🖼🎭