You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于《You Don't Know JS》中Lexical this示例的技术疑问

Demystifying the this Binding Behavior in Your Modified Call

Hey there! I totally get why this is confusing—this binding in JavaScript can feel like a moving target, especially when mixing method invocations and lexical this from arrow functions. Let's break down exactly what's happening with your examples from You Don't Know JS: Scope and Closures.

First, let's recap the original working example (the one that outputs 2 then 3) to set our baseline:

// Original example (uses arrow function to preserve lexical `this`)
const obj = {
  count: 2,
  increment: function() {
    console.log(this.count); // Logs 2 right away
    setTimeout(() => {
      this.count++;
      console.log(this.count); // Logs 3 after the delay
    }, 100);
  }
};

obj.increment(); // Called as a method directly on `obj`

Why the Original Example Works

  • When you call obj.increment(), JavaScript uses the implicit binding rule: since the function is invoked as a method on obj, the this inside increment points directly to obj. That's why the first log shows obj.count (which is 2).
  • Arrow functions don't have their own this binding—they inherit the this from the surrounding lexical scope. Here, the arrow function inside setTimeout inherits the this from increment, which is obj. So when this.count++ runs, it updates obj.count to 3, hence the second log.

Now, let's talk about your modified call scenario where both logs output 2. The most common way this happens is when you break the implicit binding by invoking the increment function outside of obj's context—like assigning it to a variable and calling it standalone:

// Modified call that breaks implicit binding
const inc = obj.increment;
inc(); // Called as a standalone function, not tied to `obj`

Why This Modified Call Outputs 2 Twice

Here's the breakdown:

  1. When you assign obj.increment to inc, you're just grabbing the function itself—you lose the connection to obj.
  2. When you call inc() as a standalone function, JavaScript uses the default binding rule. In non-strict mode, this means this points to the global object (e.g., window in browsers, globalThis in Node.js). If your global object happens to have a count property set to 2 (maybe from prior code, or an accidental global variable), here's what happens:
    • The first console.log(this.count) logs the global count value: 2.
    • The arrow function still inherits the this from the increment function's scope—which now is the global object. If the global count isn't being modified (or the modification doesn't affect the log timing), both outputs will stay 2.
  3. Even if you're using a different modified invocation (like calling increment with a custom context that has count:2), the core issue stays the same: changing how you invoke increment changes what this points to inside it, and the arrow function will inherit that altered this instead of obj's.

The key takeaway here is that arrow functions don't fix all this problems—they only preserve the lexical this from their outer scope. If that outer scope's this is already pointing to the wrong object (because of how you invoked the function), the arrow function will just inherit that wrong this.

内容的提问来源于stack exchange,提问作者vgaltes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:48:06