Execute top-level JavaScript function inside an arrow function [duplicate] - javascript

We have a global object in javascript that we can refer to using window for accessing any global variable. But how to refer to the module scope object where all the variables in that module are stored?
Actually, I need to refer to an imported object in the module using string. If it was a global variable, I could've simply done this,
let object_I_want = window[string];
But for module, I can't find the reference for such object. I also tried using this,
var scope = this;
somefunction(){
let object_I_want = scope[string];
}
But, this is undefined inside module context according to the specification. Is there a way to reference the module scope/module object like window.

I think another way to word your question might be: "How can I access scoped variables using strings?", and the answer is "It's not possible in JavaScript".
If you truly need this kind of dynamic flexibility with your values, you must assign them all to a top-level object (and you must export that object from your module if you want to access it and its values outside the module). Or use eval, if supported in your environment.

There is no such object for modules. The module scope is like a function scope - an environment record that you cannot access from javascript, you can only use it to declare variables.
There is an object that holds all the exported names of a module (which you can get by doing a namespace import * as … from …), but this doesn't seem to be what you want.

Related

Is a Local Reference to the Global Scope Itself Fundamentally a Bad Idea?

Forgive my ignorance or paranoia if this is a stupid question, but I can't seem to find anything on this specific situation in particular (which leads me to think maybe most people either know to avoid it or have better ways to handle this).
Here's the premise: I don't know whether or not my code will necessarily always be ran in a browser, and as such, I don't know if I'll have access to window (specifically by that name) or if that scope will be named something else in whatever environment my code may find itself in.
So my idea was to find that scope once, assign it to a local variable then let everything within my function just reference that local variable if I ever need to access the global scope instead of reaching for window (again, it could be called something else—I won't know).
My concern is, is this going to cause some memory leak issue (or maybe it's a bad idea for other reasons)? Is there something I should be mindful of or am I good to go?
function myConstructor() {
// Is this fundamentally a bad idea?
var globalScope = findGlobalScope() // Cyclic reference here?
function findGlobalScope() {
// Let's say I had some logic here that
// determinded that I'm running this code
// in a browser, so now I know `window`
// is where my global variables are.
// Keep in mind it may not always be `window`,
// but let's say this time it is.
return window
}
this.doWork = function() {
// In here I reference the `globalScope` variable
// instead of the `window` variable explicitly.
//
// I'm doing it this way because I don't want
// my code to break if I run it outside of a browser
// where I might not have access to an object explicitly
// named "window"
console.log(globalScope) // instead of console.log(window)
}
}
var myObj = new myConstructor()
// Now `myObj` is located at `window.myObj`
// and `myObj` has a reference to `window`
// which... again, has a reference to window.myObj
// Is this something I should be concerned about?
I appreciate the help.
It's not a scope, it's an object. (But it's understandable you'd think of it as a scope; it's used by one of the global scopes to hold variables.¹)
That's absolutely fine, it's not going to cause leaks or anything. That's one object that you know won't be going away (unless your code does, too).
Note that JavaScript now has globalThis, which is exactly what you're looking for. :-) It's a relatively recent addition.
That said, as Taplar mentioned, ideally your code shouldn't care about the global object, and should avoid creating global variables entirely if possible. The global namespace is crowded — and extremely crowded on browsers.
Ways to avoid using global scope:
Use modules. Modern environments support ES2015's modules. Older environments can be supported via bundlers like Webpack or Rollup.js.
If you can't use a module, use a wrapper function. If necessary because your code must be split across files at runtime, have that function expose a single obscurely-named global that has properties on it for your other things.
Example of #2 (using ES5 syntax):
var myStuff = myStuff || {};
(function() {
myStuff.doSomething = function() {
// ...
};
})();
¹ This is an interesting, but confusing, part of JavaScript: There are at least two global scopes in JavaScript, and outer one and an inner one (which is new in ES2015+).
The outer one has "variables" that are properties of the global object, either inherited ones or own properties: If you use a variable name, and it doesn't exist in the current scope or one between the current scope and the global scope, but does exist as a property on the global object, the property on the global object is used — an old-style global variable. When you declare a function at global scope, or declare a variable with var, it adds a property to the global object. The global object also (in most environments) inherits things from its prototype and its prototype's prototype. For instance, globals created on browsers for elements with an id are properties of the WindowProperties object, which is in the prototype chain of the global object. It also sometimes has other "own" properties, such as name (the name of the window on browsers).
The inner global scope doesn't use the global object. It's where things declared with let, const, and class go. They don't become properties of the global object.

When you define a function in NodeJS, which object is that function a member of? [duplicate]

This question already has answers here:
In what scope are module variables stored in node.js?
(4 answers)
Closed 3 years ago.
In the browsers execution environment when you define a function, that function is a member of the window object. For example:
function myFunc() {
console.log( 'hello' );
}
console.log( window.myFunc ); // valid
In NodeJS, we don't have a window object, be we do have a global and a module object. However, when you define a function the same way in the NodeJS execution environment, this function is not part of global object or the module object.
function myFunc() {
console.log( 'hello' );
}
console.log( global.myFunc ); // undefined
console.log( module.myFunc ); // undefined
So which object is myFunc a member of?
Functions in Javascript are not automatically a member of any particular object. If you want them to be, then you have to assign them that way.
It does so happen that in a browser, a function defined in the global scope will be attached to the window object, but that is a nuance of the browser implementation, not of Javascript itself.
And, in fact the language is moving away form this since newer things like class definitions in the top level scope are not attached to the window object.
In node.js, your default top level scope is the module scope and functions defined there are not automatically attached to any object. If you want a function to be global, then you have to assign it to the global object.
Though, please keep in mind that node.js has a modular architecture precisely so that you do NOT make functions you define global. Instead, you export them from a module and have any other module that wants to use them import or require() your module to get access to the function. In this way, all dependencies are explicitly declared in the code rather than implicitly defined in the code through globals.
So, in node.js if you want a function to be attached to an object, you have to explicitly put it on the object as a named property. Javascript does not provide a means in the language to iterate all objects/functions defined within a scope.

How to access variable in the anonymous closure parent scope from a nested function if both contain variables of the same name? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to gain access to the closure of a function?
Say I have the following implementation of the revealing module pattern:
var myModule = (function() {
var myVar,
_self = this;
function setMyVar( myVar ) {
_self.myVar = myVar;
}
return {
setMyVar: setMyVar
}
})()
myModule.setMyVar('happy');​
What I want to do is set the module level myVar to be 'happy'. This doesn't work because 'this' is equal to window in the anonymous parent function. One easy work around would be to avoid child-parent name collisions, but putting that aside, is there a way I could have access to a reference to the anonymous function scope from inside a nested child function?
"One easy work around would be to avoid child-parent name collisions"
Please don't consider that to be a workaround, but rather a best practice. Variable shadowing doesn't often add benefit, but can add confusion to code and bugs when you forget which variable you're working with.
The only variable scope (or variable object, or binding object... whatever) that is available as an object that can be directly manipulated in code is the "global" scope. No nested scopes allow this sort of direct access, so no, there's no other option other than to avoid shadowed variables.
This should generally not be an issue. A function variable or parameter can only access (and therefore shadow) variables in its original scope, so passing a function into a different scope will not cause any sort of conflict with the variables in that scope.
If needed, code validators like http://jshint.com are able to catch shadowed variables for you.
No. If it is masked, it is masked and you can't get access to it.

Accessing variables from another CoffeeScript file?

What is best practice to get a variable outside of its anonymous function without polluting the global namespace?
A number of possibilities:
Create a properly name-scoped public accessor function to obtain the value upon demand.
Pass the value to the functions where it will be needed
Pass a private accessor function to the other module
Put the variable in a properly name-scoped global
Pass a "data object" to the other module that has the value in it (along with other values)
Which makes the most sense depends upon how much data you need to share, how widely it needs to be shared, whether the sharing is both ways, etc...
The typical design pattern for exposing global data with the minimum impact on polluting the global namespace is to do something like this:
var JF = JF || {}; // create single global object (if it doesn't already exist)
JF.getMyData = function() {return(xxx);}; // define accessor function
JF.myPublicData = ...;
Then, anywhere in your app, you can call JF.getMyData(); or access JF.myPublicData.
The idea here is that all public methods (or even data objects) can be hung off the JF object so there's only one new item in the global space. Everything else is inside that one object.
There have been several CoffeeScript questions along these lines:
How do I define global variables in CoffeeScript?
Expose a javascript api with coffeescript
Getting rid of CoffeeScript's closure wrapper
as well as several others that are environment-specific. If you posted a more detailed question with a concrete example, I could provide a more specific answer.

How to preserve global variables in javascript when using Closure compiler with advanced optimization?

I have my own Javascript library, which I want to minify by using Google closure compiler with Advanced optimization. By looking at the docs I see how to declare functions which are used outside of the library.
However I couldn't find a way how to preserve global variables declared in my library. Closure compiler just removes them, because it thinks they are never used. Anybody can help ?
Edit: example code:
var variable_1 = true;
This is defined globally right at the beginning of my library, but it's never used in the library itself. It is used outside the library when it is included in some page. But that Closure compiler doesn't know and thats the reason it removes these declarations.
The closure compiler cannot remove global variables declared as window["variable_1"] = true
I recommend you write to window directly for global variables and I also recommend you use string literals for your variable names so that closure doesn't minify it.
Although you can refer to a "true" global variable through replacing all usage of that global variable with window["varname"], it is usually not a good idea to "pollute" the global namespace. The Closure Compiler is designed to discourage you from doing this.
CAVEAT: window["varname"] and var varname are not the same, as "window" may not always be the global object in non-browser environments. As a matter of fact, the Closure Compiler assumes that the global object and "window" are different. For example, window["varname"] will compile to window.varname instead of var varname. They are NOT the same, although in a browser they work similarly.
It is best to make a global namespace object, then only export that one object. All your "global" variables should become properties under this global namespace variable. Benefits:
All those global variables are renamed to shorter versions
Inlining of constants can happen
The Closure Compiler automatically "flattens" the namespace anyway, so your code won't be any slower
Superior obfuscation
Your code also works in non-browser environments. Remember, "window" may not always exists (e.g. in server-side code) and the "global object" may not always be "window"
If you have global variables that the user must read/set to use your library, it is also discouraged. It is better to expose an API on the global namespace object, then expose the public API's as usual through the window object: window["myLib"]["setConfig"] = myLib.setConfig.
In your case, if you have global variables used in other parts of your non-Closure-Compiled code, you have to consider:
Is it better to put the declaration of those variables outside of the file being compiled by Closure
Why are you not putting the declaration of those variables together with the code using them
Should you actually be Closure-compiling all the code instead of only a portion (it is possible? Do you use another library?)
I've just come across this, and I have my own solution.
Create you're entire library within a self-executing function, putting all the object properties as strings (at least once for each property) like so:
(function () {
var myLibrary = {
'myMethod' : function () {
...
}
}
myLibrary.myMethod['propertyOfTheMethod'] = '';
}());
The usual way to make this accessible from the outside would be to put var myLibrary = before the function and return myLibrary at the end of it so that it gets assigned to a global variable. But the function is executed in the global scope (because it's self-executing), so we can create a property of this using a string literal. So in full:
(function () {
var myLibrary = {
'myMethod' : function () {
...
}
}
myLibrary.myMethod['propertyOfTheMethod'] = '';
this['myLibrary'] = myLibrary;
}());
But, this won't work under "use strict";. The best way to get the global variable in strict mode is with var global = Function('return this')(); then assign your variable to that.

Categories