学习 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() 方法与 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(不要重复自己)。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3