If I run this code within the Chrome Developer Tools:
var test = (function () {
var publicFunction,
privateFunction1,
privateFunction2;
privateFunction1 = function privateFunction1() {
return true;
};
privateFunction2 = function privateFunction2() {
return true;
};
publicFunction = function publicFunction() {
privateFunction1();
debugger;
};
return {
publicFunction: publicFunction
};
})();
why is privateFunction1
in scope at the breakpoint, while privateFunction2
is not?
The Revealing Module pattern is a design pattern for Javascript applications that elegantly solves this problem. The central principle of the Revealing Module pattern is that all functionality and variables should be hidden unless deliberately exposed.
In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.
The Module Pattern is one of the important patterns in JavaScript. It is a commonly used Design Pattern which is used to wrap a set of variables and functions together in a single scope. It is used to define objects and specify the variables and the functions that can be accessed from outside the scope of the function.
Revealing Module Pattern is JavaScript's design pattern that is available for users to actually organize JavaScript's codes in modules which actually gives better code structure and helps in making things either private or public to users.
Fascinating question.
privateFunction2
is in scope for publicFunction
, but publicFunction
never actually uses it. I believe what you're seeing in the debugger is because V8 (Chrome's JavaScript engine) optimizes the content of closures for various reasons (including minimizing memory use).
In theory, according to the specification, publicFunction
closes over (has an enduring reference to) all symbols in scope where it's defined. Specifically, an execution context was created for the call to your outermost anonymous function, and that execution context has a lexical environment with an associated binding object to which publicFunction
has an implicit, anonymous reference. That binding object has properties on it with (in theory) the names publicFunction
, privateFunction1
, privateFunction2
, and a few other things (arguments
and such).
But the thing is that publicFunction
doesn't actually reference anything but privateFunction1
, and with the code in place for it, it cannot reference anything else. For it to reference anything else, you'd have to change its code, and of course them V8 would make a different decision. The code in publicFunction
has no eval(string)
or new Function(string)
calls, so V8 is free to do a static analysis on the symbols it references. That means that, absent the debugger, there is no point whatsoever to the binding object keeping those other properties. They're never used.
Since V8 is an aggressively optimizing compiler (yes, compiler), apparently it removes dead properties from the binding object of the execution context.
If I add something to publicFunction
that uses privateFunction2
for anything, I can then refer to it from the console just like I can privateFunction1
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With