Just write code. Don't worry about performance unless performance is shown to be a problem.
And to the two you have, let me add a third. Create a base object with all of the desired functions as methods, expecting this
to have your state. Then have your stateful objects set the base object as their prototype
. And now your methods simply exist, and get called, and state is passed around without having another visible parameter.
I am not a JavaScript programmer, and so don't have a strong opinion about which of these is best.
However, though versions of this text appear all over on the internet my question is not completely answered by this explanation. Though it may be implied, since global variables always seem to be static it would be nice to have a straight out answer.
If you didn't explicitly create it, you don't need to explicitly destroy it.
Let's just remove some of the words from your standard quote:
Static: Objects declared in global or namespace scope (§6.3.4) ... are created and initialized once (only) and ‘‘live’’ until the program terminates (§15.4.3). Such objects are called static objects.
So, if you declare an object with global or namespace scope, it is static, and its lifetime is roughly the program lifetime.
By analogy, consider normally-scoped local variables:
void foo() {
std::string s;
// code
}
now there is no way to destroy s
without exiting its enclosing scope. If you explicitly destroy it in-place, the destructor will still be called again when the scope exits.
Now, consider global and namespace scope to be the top-level scope of your program. You enter this scope before main
(which is nested inside the global scope) and exit it after leaving main
. This top-level scope lives exactly as long as the program, and you're no more able to destroy the its objects early than you are objects in any other scope.
There is some subtlety about exactly when the constructor gets called (generally before main starts, with a fudge to allow dynamically-loaded libraries without having to talk about platform specifics), when the destructor gets called (relative to exit handlers, say), and the relative ordering of these for different statics (not well-defined, so don't make global initialization or destruction depend on other globals).
Of course, if you want the object to be global for convenience, you can still choose to have explicit setup/cleanup calls instead of using the ctor/dtor for this.
Best Answer
What is trapping you in this kind of thinking is the concept of "the key". It should be "a key".
You think of the key as global so anything that would hold it must be global. Imagine your requirements change and suddenly there are 5 keys running around.
Can't imagine that? Fine, imagine 5 systems, that do nearly the same thing, that must have different keys and all need to be part of your application. How much of your code could be reused?
The key belongs in a context. Within that context there will be only one key. But that doesn't mean there will only ever be one context.
Rather than force everything to find this key by knowing "the one true key" tell them what context they are in by passing them some way to find the key they care about.
That means the key will still only be stored in one place. But now only one place decides where that place is. If you make it global then everything has to know where it is and AGREE on where that is. Ick.