.bind() does create a new function, though it has far less “slots” than a regular one. It doesn’t modify the original function. The spec doesn’t specify anything beyond that, afair, and if binds aren’t cached in some way (easy to check with === or roll up your own cachedBind()), GC barely can make any benefit out of collecting slightly smaller objects (but the interpreted part of a runtime may still process bound functions a little faster than closures doing the same thing).
As of source code or p-code or by whatever structure {<code>} body is represented inside, it is always* static for all closures, so there is no overhead apart from a closure itself between:
function foo() {<code>} // func
for (;;) foo()
and
let i = 0
for (;;) {
let j = 0
function foo() {i++; j++; <code>} // closure
foo()
}
Because {…<code>} is a singleton in both snippets.
* of course jit may blur this distinction a lot, but that’s unrelated