Function.bind与变量捕获:this绑定方式对比及性能、内存泄漏问题探讨
Alright, let's dig into your question—this is a classic JS pitfall that actually reveals some neat details about how the language handles this and memory!
Performance: bind() vs. self = this
First, let's break down the performance difference between these two approaches:
bind()creates a new function every time you call it: When you use.bind(this)on the setTimeout callback, the JS engine generates a brand new function instance permanently bound to yourFoobarinstance. If you callprintLazy1000+ times in quick succession, that's 1000+ extra function objects being created and stored in memory temporarily.- Variable capture (
self = this) reuses the same callback: With this approach, you're just assigning a reference to the outerthisto a local variable, then using that reference in the existing callback function. No new functions are created—you're reusing the same anonymous function each time, so there's less overhead in terms of memory allocation and function setup.
In practice, modern JS engines optimize both approaches pretty well, but for high-frequency calls (like 1000+ times), the self = this method will be marginally faster and use less memory because it avoids the repeated function creation from bind().
Memory Leak Concerns: Will self cause leaks?
Short answer: No, it won't cause memory leaks in this scenario. Here's why:
JS uses a garbage collection system that cleans up objects when there are no active references to them. When you call printLazy 1000 times, each setTimeout callback references self (which points to your Foobar instance). But once each callback executes (after 1 second), the callback function itself is no longer needed, so the reference to self is removed.
Once all timers have fired and their callbacks are garbage collected, there are no remaining references to your Foobar instance (assuming you don't have other code holding onto myBar), so the instance will be cleaned up normally.
The bind() approach works the same way—each bound function references the instance, but those bound functions are also garbage collected once the timer fires. The only way you'd get a memory leak here is if you kept a reference to the Foobar instance (like storing myBar in a global variable that never gets cleared), which has nothing to do with either bind() or self = this.
Bonus: ES6 Arrow Functions Are a Cleaner Alternative
If you're working in an ES6+ environment, you can skip both approaches and use arrow functions, which automatically inherit the this value from the surrounding scope:
this.printLazy = function(){ this.timer = setTimeout(() => { console.log(this.baz); // Automatically uses the outer `this` from printLazy }, 1000); }
This is just as efficient as the self = this method, and the code is more readable.
内容的提问来源于stack exchange,提问作者XPD

