Why global "this.function" is not accessible without "this."? - javascript

this.func0 = function() {
console.log('hi')
}
this.func0() // this works
func0() // but not this?
Why func0() is not working?
Aren't this.f() and just f() both supposed to access global object?

The important thing to understand here is, in Node.js, each and every JavaScript file will be treated as a separate module.
So, within the JavaScript file, this will refer to the current module object, not the global object. We have something called global object in Node.js, which is somewhat similar to browsers' window object.
This is what you are doing with your program
this.func0 = function() {
console.log('hi')
}
you are creating a function object and assigning it to the current module's func0 attribute.
this.func0();
you are calling current module's func0.
func0();
JavaScript, searches for func0 in the current scope, then in the global scope but it doesn't find it anywhere. That is why it fails with the ReferenceError
ReferenceError: func0 is not defined
If you really wanted to set that in the global scope, then you should do it like this
global.func0 = function() {
console.log('hi')
}
func0();
// hi

Related

Can you locally declare a global variable for eslint?

With eslint you can declare a global variable with /* global <name-of-var> */. For example
/* global document */
const elem = document.querySelector(selector);
Is it possible to declare a global but only inside a certain scope?
function foo(selector) {
/* global document */
return document.querySelector(selector);
}
function bar(selector) {
return document.querySelector(selector); // error! document undefined
}
Testing the example above fails in that declaring document as a global in foo makes it accesseble in bar.
The advantage making the global's access scoped is that if you delete a function there is nothing else to clean up. It declares it's own access. Where as if you put the globals at the top of the file and delete a function you also have to go clean up the top of the file. It also arguably better documenting where the variable comes from based on the idea that more info locally is better.
Note: while I know the feature is different, python has the concept of giving an individual function access to a global. Doing so does not give all functions access to that global so the idea in general of declaring globals per function is not unusual.
Is there a way declare the existence of global only within a certain scope for eslint?
The documentation doesn't say anything about doing it only locally in a function. I can see the point of what you're describing; you never know, they might be open to a pull request adding that...
Two workarounds for you:
Group together the functions that need the global in their own module.
Use eslint-disable-line or eslint-disable-next-line and an inline assignment, like this:
function foo(selector) {
const doc = document; /* eslint-disable-line no-undef */
return doc.querySelector(selector);
}

Can not bind 'this' to imported function - javascript

I am a beginner and I want to bind 'this' to helper-functions which I have imported from an other file (that I can use the variables, I created in the current lexical environment ).
But I have recognized, that I can bind these imported functions to any object - which I have created in the file, into I have imported them - but not to the current this.
node.js example:
https://github.com/sdeli/issues-with-this
// random-js-file.js
// this is the function I import in app.js
function logOutThis() {
console.log(this);
}
module.exports = logOutThis;
// --------------------------------
// app.js
const importedFn = require('./random-js-file.js');
// this is now the global of random-js-file.js
importedFn();
console.log('--------------------------------');
var monkey = {
chimp : 'chimp'
}
// this is now the object 'monkey'
var myfunction = importedFn.bind(monkey);
myfunction();
console.log('---------------------------------');
//this should be now the current this
var myfunction2 = importedFn.bind(this);
myfunction2();
// console.log displays '{}' and i can not refer to the variable in this lexical environment
So I dont understand why I can not bind 'this' into a function which I have imported but I can bind it to any object.
Thank you for your suggestions
There isn't a way to access the inner context of an imported module unless it explicitly exports the bits you want (or provides functions that expose them). Javascript this doesn't behave like Java this, and modules aren't classes.
There's some other cases, but basically, if the function you're currently is called someFunc and it was called with syntax a.someFunc(), then this will be the same as a. Here's a worked example:
const someObject = {
someFunc() {
//Here, "this" will be the same as someObject, because of the way we called it
someOtherFunction();
}
};
someObject.someFunc();
function someOtherFunc() {
//"this" is still someObject because it's inherited from the calling function which was not called using a method syntax
x.y(); //inside the y() function, "this" will now be x
}
Basically, IMHO, this is a broken mess in Javascript and is one of the key reasons I avoided using it whereever possible. That means I don't use classes, and I get everything I need from closures.

How to make a variable global from inside a function [duplicate]

I need a few global variables that I need in all .js files.
For example, consider the following 4 files:
global.js
js1.js
js2.js
js3.js
Is there a way that I can declare 3 global variables in global.js and access them in any of the other 3 .js files considering I load all the above 4 files into a HTML document?
Can someone please tell me if this is possible or is there a work around to achieve this?
Just define your variables in global.js outside a function scope:
// global.js
var global1 = "I'm a global!";
var global2 = "So am I!";
// other js-file
function testGlobal () {
alert(global1);
}
To make sure that this works you have to include/link to global.js before you try to access any variables defined in that file:
<html>
<head>
<!-- Include global.js first -->
<script src="/YOUR_PATH/global.js" type="text/javascript"></script>
<!-- Now we can reference variables, objects, functions etc.
defined in global.js -->
<script src="/YOUR_PATH/otherJsFile.js" type="text/javascript"></script>
</head>
[...]
</html>
You could, of course, link in the script tags just before the closing <body>-tag if you do not want the load of js-files to interrupt the initial page load.
The recommended approach is:
window.greeting = "Hello World!"
You can then access it within any function:
function foo() {
alert(greeting); // Hello World!
alert(window["greeting"]); // Hello World!
alert(window.greeting); // Hello World! (recommended)
}
This approach is preferred for two reasons.
The intent is explicit. The use of the var keyword can easily lead to declaring global vars that were intended to be local or vice versa. This sort of variable scoping is a point of confusion for a lot of Javascript developers. So as a general rule, I make sure all variable declarations are preceded with the keyword var or the prefix window.
You standardize this syntax for reading the variables this way as well which means that a locally scoped var doesn't clobber the global var or vice versa. For example what happens here is ambiguous:
greeting = "Aloha";
function foo() {
greeting = "Hello"; // overrides global!
}
function bar(greeting) {
alert(greeting);
}
foo();
bar("Howdy"); // does it alert "Hello" or "Howdy" ?
However, this is much cleaner and less error prone (you don't really need to remember all the variable scoping rules):
function foo() {
window.greeting = "Hello";
}
function bar(greeting) {
alert(greeting);
}
foo();
bar("Howdy"); // alerts "Howdy"
Have you tried it?
If you do:
var HI = 'Hello World';
In global.js. And then do:
alert(HI);
In js1.js it will alert it fine. You just have to include global.js prior to the rest in the HTML document.
The only catch is that you have to declare it in the window's scope (not inside any functions).
You could just nix the var part and create them that way, but it's not good practice.
As mentioned above, there are issues with using the top-most scope in your script file. Here is another issue: The script file might be run from a context that is not the global context in some run-time environment.
It has been proposed to assign the global to window directly. But that is also run-time dependent and does not work in Node etc. It goes to show that portable global variable management needs some careful consideration and extra effort. Maybe they will fix it in future ECMS versions!
For now, I would recommend something like this to support proper global management for all run-time environments:
/**
* Exports the given object into the global context.
*/
var exportGlobal = function(name, object) {
if (typeof(global) !== "undefined") {
// Node.js
global[name] = object;
}
else if (typeof(window) !== "undefined") {
// JS with GUI (usually browser)
window[name] = object;
}
else {
throw new Error("Unkown run-time environment. Currently only browsers and Node.js are supported.");
}
};
// export exportGlobal itself
exportGlobal("exportGlobal", exportGlobal);
// create a new global namespace
exportGlobal("someothernamespace", {});
It's a bit more typing, but it makes your global variable management future-proof.
Disclaimer: Part of this idea came to me when looking at previous versions of stacktrace.js.
I reckon, one can also use Webpack or other tools to get more reliable and less hackish detection of the run-time environment.
Yes you can access them. You should declare them in 'public space' (outside any functions) as:
var globalvar1 = 'value';
You can access them later on, also in other files.

Accessing a variable within a JavaScript object constructed via a function

My application is accessing a third party external JavaScript file that I cannot alter.
Within the file is an object defined similarly to as follows:
object_1 = (function(){
var object_1_var = 'object_1_var_value';
return {
obj_1_func: function() {
console.log(object_1_var);
}
}
})(window);
I need to be able access the object_1_var within the object, but I'm struggling to access it.
object_1.v // returns undefined
object_1.obj_1_func() // returns the value via console, but I need to assign it to a var.
I have tried extending the object using as follows: (Using jQuerys $.extend())
object_2 = (function(){
return {
obj_2_func: function() {
return object_1_var;
}
}
})(window);
$.extend(object_1, object_2);
var my_var = object_1.obj_2_func(); // returns 'Uncaught ReferenceError: object_1_var is not defined'
What can I do to be able to access object_1_var?
You will not be able to access the variable. It happens to be a private member. Private members of an object can be accessed only by its member functions.
Read this.
object_1_var is a lexically scoped local variable.
That means that it can't be accessed by extending object_1 outside of its original definition.
The only way it can be accessed is by adding functions within the original lexical scope in which it was declared:
object_1 = (function(){
var object_1_var = 'object_1_var_value';
return {
obj_1_func: function() {
console.log(object_1_var);
}
var_1: function(x) {
if (typeof x !== 'undefined') {
object_1_var = x;
} else {
return object_1_var;
}
}
}
})(window);
but since you can't modify object_1, you're out of luck, I'm afraid!
Make it public, like this:
object_1 = (function(){
var object_1_var = 'object_1_var_value';
return {
obj_1_func: function() {
console.log(object_1_var);
},
object_1_var: object_1_var
}
})(window);
EDIT
If unable to edit the javascript (such as in a third party library - sorry for omission) then you will not be able to have access to object_1_var as it's scope is local to the closure object_1.
What you are trying to accomplish is impossible in JS.
With the construction of object_1 the variable goes out of scope of that method. The reason why the logging function can access the variable is what we call 'a closure'.
Sadly, object_1_var isn't accessible in this example. The variable is defined as local to within that particular function - the only reason that the other functions can see it is because they are also defined within that function. This "closure scoping" is an interesting feature in JavaScript that you don't see very often elsewhere, but is the only real way of defining "private" variables in JavaScript Objects.
Hope that helps!
In a worst case scenario, in the past I've worked around this sort of issue by effectively overwriting the definition of an object that was previously defined elsewhere - mainly in Greasemonkey scripts - but I wouldn't condone this for production uses!
The trick here is to just copy the entire piece of script into your own. It's ugly as hell, but it might just work! (YMMV)

JavaScript scopes and object-orientation

What's wrong with this—how come the variable foo isn't defined from within onModified() of a Document object?
function Document() {
var foo = "dfsadf";
this.onModified = function() {
alert(foo);
};
}
// Does not alert; "foo" doesn't resolve
new Document().onModified();
I'd like to have public methods on Document that reference variables that are somehow private to Document.
Your Document function is clashing with the Document constructor from the DOM.
document instanceof Document; // true
As with any host-object its behavior completely depends on the host environment, and they often can give you unexpected results.
As far I've tested, on Firefox you are not able to replace its value, therefore I would recommend you to either, rename your function, or, declare it on other scope.

Categories