Retrieve members global to the module programmatically - javascript

On the Browser, it would look something like
//retreive all enumerable of `this`
function globalMems() {
var g = this;
var ret = {};
for (var prop in g) {
ret[prop] = g[prop];
}
return ret;
}
On Node.js, this is not the same as used on the browser to refer to the global object (window). How can I retrieve all members global to a certain module in Node.js? I don't think there is any direct access to a variable that refers to it. global is far beyond the specific module, this is not it when used to refer to it as in the browser, different behavior of keyword "this" between node.js and browsers, and modul is not it.

this will work for your function in Node.js.
globalMems.call(GLOBAL);
GLOBAL in Node.js at some extent substitutes window in browser.
However, my advise would be to read more about this in javascript in general. MDN article is a good start. And not use global scope in Node.js for your developerment needs

Related

The confusion about Global object in JavaScript

I am beginner at JavaScript and I am trying to understand the Global window object in JavaScript. So, is it ok if I just imagine that any code that I write in the console like var text = "Hello"; console.log(text) is put inside window object like this Window{var text = "Hello"; console.log(this.text)} with this referencing window object. Is it ok if I consider it like that or it is not correct? Thank you
Is not pretty safe to make assumptions about the global object or the default this context, as it can vary from one javascript runtime to another, and some features like the strict mode also change this behavior.
Keep in mind that javascript not only runs in the browser -and global in node.js for instance does not work as in the browser-, and that there are a lot of different browser implementations out there.
Also, while var does write to global by default in some environments, const and let doesn't.
In node, functions called freely with no previous reference won't call them from global, but will fail instead. This heavily affects also front-end code since much of javascript for the browser nowadays is pre-compiled in a node environment via webpack etc.
So, succintly: is usually difficult to assume things about global, window and default this bindings and get them right. It is probably safer to assume that you don't have a default global object available and always refer window explicitly, as:
config.js
window.config = {foo: 'bar'}
window.someGlobalFunction = function() {...}
user.js
// do:
const elen = new User(window.config);
window.someGlobalFunction();
// don't
const elen = new User(config);
someGlobalFunction();
"is it ok to use the global object?"
Of course it is. If you know about the pitfalls and use the global object by purpose and not by accident.
(function() {
name = 12; // Note: This *is* a global variable
console.log(typeof name); // string. WTF
})();
The pitfalls are:
1) All undeclared (!) variables, and global variables declared with var automatically get part of the global object. That is bad, as that happens without any good reason, so you should avoid that (use strict mode, and let and const).
2) All scripts you run do have the same global object, so properties can collide. Thats what happens in the example above, name collides with the global window.name getter / setter pair that casts the number to a string. So if you set properties in the global object, make sure that the name is only used by you, and not by others (the browser, libraries, other codepieces you wrote ...)
If you know about these pitfalls and avoid them, you can and should use the global object by purpose, if, and only if, you plan to share a certain function / variable between different scripts on the page, so if it should really be globally accessible.
let private = 1;
window.shared = 2;
Yes, any function or variable can be accessed from the window object example:
var foo = "foobar";
foo === window.foo; // Returns: true
function greeting() {
console.log("Hi!");
}
window.greeting(); // It is the same as the normal invoking: greeting();

Expose an object's member functions as global functions

For example I have:
var n = {
abc: function() { print("abc"); },
def: function() { print("def"); },
};
Is there a way to export abc and def as global functions, so that I can call abc() directly rather than n.abc()?
My context for this is using Rhino/Nashorn script engine, and I'd like to inject a "global" object that provides global functions.
The answers for Rhino and Nashorn would be different.
For Rhino, when you create the global object using Context.initStandardObjects, you can then add your properties on the Java side by calling ScriptableObject.defineProperty (see Rhino API) and then the properties will be added to that global scope. If you need a property of type function as your example shows, create it using the FunctionObject API.
For Nashorn, you can use the interfaces mostly based on the standard javax.script APIs, with a couple of Nashorn-specific extensions. When evaluating your script, first use ScriptEngine.createBindings() to create a Bindings object, then use Bindings.put to use eval(String/Reader,Bindings)
If you need a function property, then on the Java side call ScriptUtils.wrap to create a ScriptObjectMirror (make sure to cast it to that; return type of the method is Object), then call get([function name]) to get an executable function property, then put that in the global scope.
All of that said, it seems to me that this is more easily handled on the script side using:
var abc = function() { return n.abc.apply(n,arguments); };
That's portable across Rhino/Nashorn and is one line, which is a lot less work than what you're going to do if you want to avoid writing that one line.
If you execute that in the global scope, you don't need a qualifier; it'll be added to the top-level object as a property. If you want to be more explicit you can do something like this:
(function() {
var global = this; // inner functions called without target default to global as 'this'
this.abc = function() { return n.abc.apply(n,arguments); };
})();
... which will work unless you start doing stuff that's a lot fancier (like messing around with 'this' values when loading scripts).
Why don't you just use JavaScript's bind, call and apply methods to call the object's member functions when you need to invoke them? Making them global indicates code smell.

Storing a variable in the JavaScript 'window' object is a proper way to use that object?

(Maybe) I just solved a my problem (How to update front-end content after that a form is successfully submitted from a dialog window?) by "storing" / "saving" a variable in the JavaScript window object. However, since I am newbie in JavaScript matters, I have some doubts if storing / saving a variable in the JavaScript window object is a "common" / "proper" way to use that object. Is it?
For example, using the following code
$('.trigger').click(function() {
window.trigger_link = this;
});
is advisable?
In JavaScript, any global variable is actually a property of the window object. Using one is equivalent to (and interchangeable with) using the other.
Using global variables is certainly "common," so the question is whether or not it's "proper." Generally, global variables are discouraged, because they can be accessed from ANY function and you risk having multiple functions trying to read from and write to the same variables. (This is true with any programming language in any environment, not just JavaScript.)
Solve this problem by creating a namespace unique to your application. The easiest approach is to create a global object with a unique name, with your variables as properties of that object:
window.MyLib = {}; // global Object container; don't use var
MyLib.value = 1;
MyLib.increment = function() { MyLib.value++; }
MyLib.show = function() { alert(MyLib.value); }
MyLib.value=6;
MyLib.increment();
MyLib.show(); // alerts 7
Another approach is to use .data() to attach variables to a relevant DOM element. This is not practical in all cases, but it's a good way to get variables that can be accessed globally without leaving them in the global namespace.
What is actually not mentioned here, and is probably the biggest deal breaker on why not to use window as global scope carrier is that it can be frozen (not writable) in some cases (and I'm talking from production based experience).
A good pattern is actually just create a global variable that will be used for all the common stuff in your application
var Application = {};
Application.state = { name: 'Application' }
.
.
What I found as the best pattern for me in javascript is to have a global state using Redux.
Another pattern to make a unique namespace in your application.
(function myApp()
{
var value = 5;
function addToValue(x)
{
value += x;
}
})()
If you want functions/values to be accessible afterwards you can store them in an object like this:
function myApp()
{
this.value = 5;
this.addToValue = function(x)
{
this.value += x;
}
}
var myInstance = new myApp();

node.js: Confusing usage of 'this' in the global scope

I've been toying with node.js lately and I ran into a weird behavior about the usage of this in the global scope of a module.
this is bound to module.exports in the global scope:
console.log(this === exports); // -> true
But this is bound to global in a method scope:
(function() { console.log(this === global); })(); // -> true
This also lead to this confusing behavior:
this.Foo = "Weird";
console.log(Foo); // -> throws undefined
(function() { this.Bar = "Weird"; })();
console.log(Bar); // -> "Weird"
I guess that the solution is to never use this in the global scope and explicitly use extends or global instead, but is there a logic behind all this or is it a bug or limitation in node.js?
The "logic" behind that is, that the value of this always depends on how a function is invoked.
In your case, you have a self-executing anonymous function, there, this always references the global object (non strict mode) or undefined (ES5 strict).
If you want to access the "outer" this value, you could either store a reference before executing that function, like
var outerScope = this;
(function() { outerScope.Bar = "Weird"; })();
console.log(Foo); // -> throws undefined
or re- .bind() the functions scope yourself, like
(function() { this.Bar = "Weird"; }).bind(this)();
In working on a simple CommonJS modules implementation, I had to think about what to do with this in the global scope of the module; it's not addressed by the spec.
I also set it up as the exports object at first, because I thought that would be useful, but later found some code I needed to "modulize" that was using this to get a handle to the global object, so I changed this back to the global object to provide as close of an environment to "normal" as possible for module code.
We can only guess at why node is set up the way it is (or ask the author), but my guess is it was done simply because it seemed like a useful idea, similar to the way you can give the module object an exports property in node and have it reflected in the module's actual exports (this behavior also isn't part of the spec, but doesn't go against it either).
As for the part of your question about this referencing global in functions, as the other answers explain, that's just the way this works; it's not a node-specific behavior, it's a weird javascript behavior.
I don't know if this is the exact intention of Node.js team, but I would be surprised if it was not. Consider this example ran in the dev console of a browser (e.g. chrome):
var x = function(){console.log(this)}
a = {}
a.x = x
a.xx = function(){x()}
a.x()
>> Object
a.xx()
>> DOMWindow
x()
>> DOMWindow
As you can see executing a method without specifying its context sets the context to be the global one. In this case the DOMWindow object.
When you are inside a module your context is the module, but executing a method in it without specifying a context with .call or .apply or obj. will use the global context, global, instead of the local one, module.exports.

what's the difference between Browsers and Node?

what's the difference between Browsers and Node? for instance:
setName.js on Node:
var setName;
setName = function (name) {
return this.name = name;
};
setName("LuLu");
//LuLu
console.log(name);
//undefined
console.log(this.name);
setName.html in browser:
<script>
var setName;
setName = function (name) {
return this.name = name;
};
setName("LuLu");
//LuLu
console.log(name);
//LuLu
console.log(this.name);
</script>
the the second log is different,why?
Node is a JavaScript engine, not a browser. The specific reason that you see undefined in Node, and Lulu in a browser? Differences in the global namespace:
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node this is different. The top-level scope is not the global scope; var something inside a Node module will be local to that module.
In the browser, this is a reference to the window object — the browser's global namespace — for all functions which are invoked unattached to an object (e.g. not like foo.bar()). In Node, this is simply not a reference to the global namespace.
N.B. console.log(this.name) in a Node interpreter will print Lulu, not undefined. That's because, in the REPL only,
> this === global
true
Further reading # How To Node: What is "this?"
Okay, one more edit as prompted by #Šime Vidas' comment regarding this in ES5 strict mode:
In the global context (outside of any function), this refers to the global object, whether in strict mode or not.
When the this keyword occurs inside a function, its value depends on how the function is called.
When a function is called as a method of an object, its this is set to the object the method is called on.
More interesting reading courtesy of Juriy Zaytsev (aka #kangax) in one of his blog posts.
Your browser code has the window host object. Node does not have that host object. When you set this.name, you are actually setting it to the window object aka making a global variable.
window.name === this.name // true

Categories