关于《You Don't Know JS》中Lexical this示例的技术疑问
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 onobj, thethisinsideincrementpoints directly toobj. That's why the first log showsobj.count(which is 2). - Arrow functions don't have their own
thisbinding—they inherit thethisfrom the surrounding lexical scope. Here, the arrow function insidesetTimeoutinherits thethisfromincrement, which isobj. So whenthis.count++runs, it updatesobj.countto 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:
- When you assign
obj.incrementtoinc, you're just grabbing the function itself—you lose the connection toobj. - When you call
inc()as a standalone function, JavaScript uses the default binding rule. In non-strict mode, this meansthispoints to the global object (e.g.,windowin browsers,globalThisin Node.js). If your global object happens to have acountproperty set to2(maybe from prior code, or an accidental global variable), here's what happens:- The first
console.log(this.count)logs the globalcountvalue:2. - The arrow function still inherits the
thisfrom theincrementfunction's scope—which now is the global object. If the globalcountisn't being modified (or the modification doesn't affect the log timing), both outputs will stay2.
- The first
- Even if you're using a different modified invocation (like calling
incrementwith a custom context that hascount:2), the core issue stays the same: changing how you invokeincrementchanges whatthispoints to inside it, and the arrow function will inherit that alteredthisinstead ofobj'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

