”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > JavaScript 中的 &#this&# 关键字、call()、apply() 和 bind() 方法 - 简单解释

JavaScript 中的 &#this&# 关键字、call()、apply() 和 bind() 方法 - 简单解释

发布于2024-10-31
浏览:232

学习 call()、apply() 和 bind() 方法很重要,因为它们允许您在 JavaScript 中控制 this 的上下文。在默认情况下此行为无法按预期工作的情况下,例如从一个对象借用方法到另一个对象或在回调内维护正确的上下文时,这些方法提供了灵活性和控制。通过掌握它们,您可以编写更高效、可重用和上下文感知的函数,这在复杂的应用程序中特别有用。

在我们进入call()、apply()和bind()方法之前,让我们先了解一下“this”关键字及其机制。

‘这个’关键字

让我们通过以下要点了解此关键字何时以及所指的内容:

  • 在对象方法中, this 指的是对象。在对象内定义的方法内,this 将指向拥有该方法的对象。

  • 在常规函数中, this 指的是全局对象。在非严格模式下,如果在全局上下文中调用函数(不是作为对象的方法),则 this 引用全局对象(浏览器中的窗口)。

  • 在严格模式函数中, this 是未定义的。如果函数不是对象的方法并且未绑定到特定上下文(通过调用、应用或绑定),则 this 在严格模式下将是未定义的。

  • 在事件处理程序中, 这是指接收事件的元素。当事件被触发时,它指的是调用该事件的 HTML 元素。

    
    

    在本例中,this 指的是接收 onclick 事件的按钮元素本身。

在箭头函数中, 其行为有所不同。箭头函数没有自己的 this 上下文。相反,这是在创建箭头函数时从词法上继承自周围范围的。这意味着箭头函数内的 this 将引用其封闭函数或上下文的 this 值。

const person = {
  name: "Alice",
  greet: function() {
    setTimeout(() => {
      console.log(`Hi, I'm ${this.name}`);
    }, 1000);
  }
};

person.greet(); // Output: Hi, I'm Alice

在这种情况下,setTimeout内部的箭头函数继承了greet方法的this,它指向person对象。

调用()方法

call() 方法允许您从一个对象“借用”函数或方法,并通过将另一个对象作为第一个参数传递来将其与另一个对象一起使用。第一个参数成为函数内的 this 值,后面跟随其他参数。

call() 方法不会创建新函数;它使用提供的上下文和参数运行现有函数。

const person = {
  fullName: function(city, country) {
    console.log(this.firstName   " "   this.lastName   " is going to "   city   ", "   country   ".");
  }
}

const person1 = {
  firstName: "John",
  lastName: "Doe"
}

person.fullName.call(person1, "Oslo", "Norway");
// Output: John Doe is going to Oslo, Norway.

在此示例中,call() 用于执行具有 person1 数据(firstName 和 lastName)的 person 的 fullName 方法,附加参数为“Oslo”和“Norway”。

apply() 方法

apply() 方法与 call() 方法非常相似。主要区别在于如何将参数传递给函数。使用 apply(),您可以将参数作为数组(或类似数组的对象)传递,而不是单独传递。

与 call() 一样,apply() 方法不会创建新函数。它立即使用提供的上下文(此值)和参数执行函数。

const person = {
  fullName: function(city, country) {
    console.log(this.firstName   " "   this.lastName   " is going to "   city   ", "   country   ".");
  }
}

const person1 = {
  firstName: "John",
  lastName: "Doe"
}

person.fullName.apply(person1, ["Oslo", "Norway"]);
// Output: John Doe is going to Oslo, Norway.

在此示例中,apply() 用于调用 person 对象的 fullName 方法,但使用 person1 的上下文 (this)。参数“Oslo”和“Norway”作为数组传递。

绑定()方法

JavaScript 中的 bind() 方法允许您设置函数或方法的上下文(this 值),就像 call() 和 apply() 一样。然而,与 call() 和 apply() 不同,bind() 方法不会立即调用该函数。相反,它返回一个新函数,并将 this 值设置为您指定的对象。

const person = {
  fullName: function(city, country) {
    console.log(this.firstName   " "   this.lastName   " is going to "   city   ", "   country   ".");
  }
}

const person1 = {
  firstName: "John",
  lastName: "Doe"
}

const func = person.fullName.bind(person1);
func("Oslo", "Norway");
// Output: John Doe is going to Oslo, Norway.

在此示例中,bind() 创建一个新函数 func,并将 this 值设置为 person1。该函数不会立即调用,但您可以稍后调用它,传入参数“Oslo”和“Norway”。

示例:具有多个上下文的集中式记录器

这是一个小而复杂的应用程序示例,其中使用 call()、apply() 或 bind() 可以提高效率,尤其是在处理部分应用用于记录目的的函数时:

假设您有一个集中式日志记录功能,可以记录有关不同用户执行操作的信息。使用bind()可以让你有效地为不同的用户设置this上下文,避免重复的代码。

const logger = {
  logAction: function(action) {
    console.log(`${this.name} (ID: ${this.id}) performed: ${action}`);
  }
};

const user1 = { name: "Alice", id: 101 };
const user2 = { name: "Bob", id: 202 };

// Create new logger functions for different users
const logForUser1 = logger.logAction.bind(user1);
const logForUser2 = logger.logAction.bind(user2);

// Perform actions without manually passing user context
logForUser1("login");
// Output: Alice (ID: 101) performed: login

logForUser2("purchase");
// Output: Bob (ID: 202) performed: purchase

为什么它有效:

上下文重用:您无需在每次记录操作时手动传递用户上下文。上下文(this)被绑定一次,日志记录变得可重用且干净。

模块化:如果您需要添加更多用户或操作,您可以快速将它们绑定到记录器,而无需更改功能本身,从而保持代码 DRY(不要重复自己)。

版本声明 本文转载于:https://dev.to/abeertech01/this-keyword-call-apply-and-bind-methods-in-javascript-simply-explained-3ag2?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 反射动态实现Go接口用于RPC方法探索
    反射动态实现Go接口用于RPC方法探索
    在GO 使用反射来实现定义RPC式方法的界面。例如,考虑一个接口,例如:键入myService接口{ 登录(用户名,密码字符串)(sessionId int,错误错误) helloworld(sessionid int)(hi String,错误错误) } 替代方案而不是依靠反射...
    编程 发布于2025-04-15
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-04-15
  • 您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    在javascript console 中显示颜色是可以使用chrome的控制台显示彩色文本,例如红色的redors,for for for for错误消息?回答是的,可以使用CSS将颜色添加到Chrome和Firefox中的控制台显示的消息(版本31或更高版本)中。要实现这一目标,请使用以下模...
    编程 发布于2025-04-15
  • 为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    网格超过身体,用100%grid-template-columns 为什么在grid-template-colms中具有100%的显示器,当位置设置为设置的位置时,grid-template-colly修复了?问题: 考虑以下CSS和html: class =“ snippet-code”> g...
    编程 发布于2025-04-15
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-04-15
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法时,您可能会出现错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && &&华氏度D...
    编程 发布于2025-04-15
  • 哪种在JavaScript中声明多个变量的方法更可维护?
    哪种在JavaScript中声明多个变量的方法更可维护?
    在JavaScript中声明多个变量:探索两个方法在JavaScript中,开发人员经常遇到需要声明多个变量的需要。对此的两种常见方法是:在单独的行上声明每个变量: 当涉及性能时,这两种方法本质上都是等效的。但是,可维护性可能会有所不同。 第一个方法被认为更易于维护。每个声明都是其自己的语句,使其...
    编程 发布于2025-04-15
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-04-15
  • 如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    使用http request 上传文件上传到http server,同时也提交其他参数,java.net.net.urlconnection and Multipart/form-data Encoding是普遍的。 Here's a breakdown of the process:Mu...
    编程 发布于2025-04-15
  • 如何实时捕获和流媒体以进行聊天机器人命令执行?
    如何实时捕获和流媒体以进行聊天机器人命令执行?
    在开发能够执行命令的chatbots的领域中,实时从命令执行实时捕获Stdout,一个常见的需求是能够检索和显示标准输出(stdout)在cath cath cant cant cant cant cant cant cant cant interfaces in Chate cant inter...
    编程 发布于2025-04-15
  • 如何检查对象是否具有Python中的特定属性?
    如何检查对象是否具有Python中的特定属性?
    方法来确定对象属性存在寻求一种方法来验证对象中特定属性的存在。考虑以下示例,其中尝试访问不确定属性会引起错误: >>> a = someClass() >>> A.property Trackback(最近的最新电话): 文件“ ”,第1行, attributeError:SomeClass实...
    编程 发布于2025-04-15
  • 在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在C中的显式删除 在C中的动态内存分配时,开发人员通常会想知道是否有必要在heap-procal extrable exit exit上进行手动调用“ delete”操作员,但开发人员通常会想知道是否需要手动调用“ delete”操作员。本文深入研究了这个主题。 在C主函数中,使用了动态分配变量(H...
    编程 发布于2025-04-15
  • 如何在Java字符串中有效替换多个子字符串?
    如何在Java字符串中有效替换多个子字符串?
    在java 中有效地替换多个substring,需要在需要替换一个字符串中的多个substring的情况下,很容易求助于重复应用字符串的刺激力量。但是,对于大字符串或使用许多字符串时,这可能是降低的。 利用正则表达式Example UsageConsider a scenario where y...
    编程 发布于2025-04-15
  • 使用jQuery如何有效修改":after"伪元素的CSS属性?
    使用jQuery如何有效修改":after"伪元素的CSS属性?
    在jquery中了解伪元素的限制:访问“ selector 尝试修改“:”选择器的CSS属性时,您可能会遇到困难。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    编程 发布于2025-04-15
  • 如何使用Python理解有效地创建字典?
    如何使用Python理解有效地创建字典?
    在python中,词典综合提供了一种生成新词典的简洁方法。尽管它们与列表综合相似,但存在一些显着差异。与问题所暗示的不同,您无法为钥匙创建字典理解。您必须明确指定键和值。 For example:d = {n: n**2 for n in range(5)}This creates a dicti...
    编程 发布于2025-04-15

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3