Re-defining global variable with conflicting local variable - javascript

So I was trying to get a handle on JavaScript's scope and looking up lots of info about it. I saw a lot of questions about people accidentally making local variables that conflicted with global ones.
But I was wondering if there was a way to change global variables despite a conflicting local variable.
Like:
var globalVariable = 6;
var func1 = function() {
this.func2 = function() {
var globalVariable = 99;
= 7;
}
};
print(globalVariable);
Is there a way to change the global variable value despite that conflicting local variable name?
When I tried this.globalVariable = 7 to print 7 as the output, it did not work. Can anyone make clear why the this.access did not work or if there is even a way to change the global variable if there does happen to be a local of conflicting name?
Obviously it would not make sense to write code this way, but I thought I understood that the this. keyword always specified the global variable/object?

"I thought I understood that the this. keyword always specified the global variable/object?"
No. The value of this depends on how a function is called and whether the function is in strict mode.
In the browser global variables are properties of the window object, so use:
window.globalVariable = 7;
Sometimes this is equal to window, but often it is not. (I don't mean that to sound like this just gets set randomly; there is a specific set of rules that apply.)
Note that if you find yourself needing to distinguish between global variables and local variables like this you might well be using too many global variables.

You could use window['globalVariable'] = 7;
It's not a good solution though. There really are none.
The "this" variable refers to the scope the current function has, usually, unless it was bound to something else or called/applied (.call/.apply). I'd suggest Googling function scope because it can get quite confusing.
I'm on Skype if you have any more questions (thetenfold).

Related

Is it bad to use window property to create variables?

(Sorry for my poor English)
I finally realized why it's better to use let or const instead of var because var can't work with window properties!
However, is it a good idea still to use window properties as variable names just because you can bypass the problem by using other two keywords of creating variables?
For example:
var name = 'James';
console.log(name);
The above won't work because I'm using var keyword however if I used let or const, this wouldn't cause any error!
So once again, just because I can should I ?
Using variable names that exist as properties on the window object was never the real problem. Using them for global variables was (and still is). But if you are in a local scope, e.g. inside a function, you can name your local variables however you like.
If you cannot avoid global variables, you should strife to use as few as possible, and yes you should try to avoid collisions with other globals, be they properties of window or not. Using let or const just ensures that if they are window properties, your custom variable will shadow them, but you will still break other code that relies on these to be accessible as global variables with the builtin value. However, most of the time you cannot avoid global variables you also cannot avoid var, as let and const cannot be redeclared.
var
Function-scoped variable. It is visible in the current function. If it's outside all functions, then it's visible globally, assuming it's not in module scope.
let
Block-scoped variable. It's visible in the {} block where it was defined.
const
Block-scoped constant. Like let, it's block-scoped, but this one is constant.
object property
window is an object, so let's think about objects in general.
window.foo = "bar"; console.log(window.foo);
"Better"
One is not "better" than the other by definition. You will need to think about your needs and the conventions your team has agreed upon and apply them. Setting window attributes should not be a custom in general, because you are making it global, but sometimes you need to set window properties. Again: always think about what you need to achieve.

Avoid declaring variables on scroll?

var variableOne;
var variableTwo;
var variableThree;
function veryInterestingFunction() {
var variableFour;
if(a){
variableFour = 'Good';
}
else {
variableFour = 'Decent';
}
console.log(variableFour);
}
$(window).on('scroll', function(){
veryInterestingFunction();
});
Here I have some variables in the global scope, a function declaring a variable and assigning a value to it, and calling this function on scroll.
This way on every scroll you are going to declare the "variableFour" which is not a good practice, right?
However I don't want to crowd the global scope with unnecessary variables and also can't use an IIFE. Is there a "best practice" way to declare the variable outside the function and still only possible to use it inside the scope of that function ?
http://jsfiddle.net/2jyddwwx/1/
to declare the variable outside the function and still only possible to use it inside the scope of that function ?
I guess, that's impossible
When I don't want to crowd the global scope, I will declare one global object, for example App = {}, and instead of global variables, I use it's properties.
App.variableOne;
App.variableTwo;
App.variableThree;
Or you can use classes in ES6
I don't think there's anything wrong with your code sample, I seriously doubt variable declaration is ever going to slow down your code. I'd definitely only start to worry about this kind of thing when you're absolutely certain it's causing issues (it won't), otherwise it might be wasted effort.
If you really want to optimize this, one thing you might be able to do is debouncing the veryInterestingFunction calls - that is if you don't necessarily need to respond to every single scroll event (depends on your logic).
As per your question, IIFE/function closure is essentially the only way to limit scope in JavaScript that I know of, so if you can't use that, I don't see any other option.
There is no problem in declaring an empty variable into your scope. If it is not global, it belongs to the scope.
And there is no need to fear for performance. If you declare variables within your scope, the Javascript garbage collector will empty that for you. Take a read at this article

How can I set a Global Variable from within a function

How can I set a Global Variable from within a function?
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
var option = $(this).val();
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Declare it outside the scope of your jQuery onready
var option = '';
$(document).ready(function() {
$("[name=select_option_selected]").change(function() {
option = $(this).val();
alert(option); // Example: Foo
});
alert(option); //This will never be "Foo" since option isn't set until that select list changes
});
if you want to initialize this to the current selected value try this:
var option = "";
var $select_option_selected = null;
$(function() {
$select_option_selected = $("[name='select_option_selected']")
$select_option_selected.change(function() {
option = $(this).val();
});
option = $select_option_selected.val();
});
The Bad Way
As the other answers point out, it's not a good idea to create global variables. And as they point out, you can create a global variable by:
Declaring variable outside of all functions
Initializing your variable without the var keyword
Or, declaring it as a property of the window object: window.options = 'blah';
Using jQuery's Data() Method
But there is a better way of creating a globally accessible value using jQuery (and other libraries). In jQuery, use the data() method to store values associated with DOM elements:
// store 'blah' at document root
$(document).data('mysite.option', 'blah');
// retrieve value
alert($(document).data('mysite.option'));
Notice "mysite"... it is a good idea to namespace your data keys for the same reason it is good to namespace global variables in javascript.
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
option = $(this).val(); //no declaration of new variable, JavaScript goes to what encloses the function
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Are you sure you want to? global variables are generally to be avoided. In the browser, window is the global object, so if you do window.option = ..., then option will be available globally.
I highly recommend naming a global variable something more unique than "option", to avoid clobbering existing stuff.
Another option, which I also don't recommend: leave off var
myvariable = 'foo';
If myvariable has never been delcared before, it will be declared as a property on window, making it global. This is generally considered to be (very) bad practice however.
You can use the window. prefix to access a global variable from within the scope of a function
window.option = ...;
Two approaches not mentioned by anybody else, applicable when you: 1. don't have access to the global LexicalEnvironment,10.2.3 and 2. are trying to write code that you wish to support systems wherein a direct reference to the global object15.1 (such as window in the HTML DOM, or GLOBAL in Node[1]) isn't guaranteed:
Make an indirect15.1.2.1.1 call to eval, by wrapping it in a superfluous PrimaryExpression, thus: (1,eval)(...) (the digit and comma operator are meaningless) … and then calling the result thereof. This forces the code to be run in the global execution context.10.4.2
We can then declare10.5 a new variable in the global lexical environment, as suggested above; or, for that matter, do anything else that we desire within that environment:
function global_define(ident, value){
(1,eval) ("var "+ident+"; (function(v){ "+ident+" = v })") (value) }
To be less round-about (and, to boot, avoid the FUD-ridden eval call), we can directly access the global object and set a property4.2 on it, which will then be available as a global variable elsewhere in our code.[2]
Instead of taking the eval approach above and gaining access to the global object via code we've written in the global context, it turns out we can access the global object as the this value10.4.3 within any function that is called with null:
var global = (function(){ return this }).call(null)
global[ident] = value
Phew.
Okay, more reading, for those of you who haven't fainted from specification links and eval calls, yet:
#kangax covers all of the bases quite thoroughly. Seriously, read that if you have any questions I haven't answered here (including those relating to the all-important idiosyncrasies browser support!)
Obviously, the relevant sections of the ECMAScript 5 specification itself, to get an idea for how things are intended to work in an ideal world. No, really though; I know that specifications are a scary idea, but the ES (“JavaScript”) specifications are one of the easiest-to-read and most comprehensible specs I've ever seen. They're truly excellent. Of immediate note, and in no particular order,
10.4, Establishing an Execution Context: Covers how ‘global code’ and ‘eval code’ are handled, specifically.
10.2, Lexical Environments: These describe “where variables are stored.” (The ‘Global Environment’ of interest is one of these.)
10.1, Types of Executable Code: Covers what ‘global code’ and ‘Program’s are.
15.1, The Global Object: Unfortunately, far less relevant than its title makes it sound. Still worth a skim.
[1]: The discussion in other answers, suggesting that exports in Node.js and other CommonJS-compliant systems is somehow related to the global object, about which this question asks, is misleading. In terms of system-design, one might be better suited to using their environment's module tools than poking around on the global object … but that's a discussion for another Stack Overflow post. (=
[2]: For those of you following along in the spec, it's harder to demonstrate that property-members of the global object are accessible as Identifier dereferences. Start with 10.2.1.2 Object Environment Records and 10.2.3 The Global Environment to understand how the global object is linked to an environment, then hop on over to 18.12.3, 18.12.2, and 18.12.1 in that order, collectively describing [[Get]] on the global object.
Nota bene: At no point in this elaboration did I suggest that doing either of these things was a good idea. Or, for that matter, that interacting with the global scope at all is a good idea. Of no relation to the question at hand, but proffered to soothe my own conscience, I add that I wrap all of my own code in a IIFE beginning immediately at the top of the file; this, along with religious application of the var keyword, ensures that I never interact with JavaScript's handling of the global object at all. A huge mess, avoided. You should do that. I said so. I'm smart. (;
just declare a global object
var obj={};
function my_function()
{
obj['newVariable'] = 'someValue';
}
in this way i achieved global variable.
http://jsfiddle.net/Kba5u/
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
// changeFooToBaz();
console.log(foo); #=> 'bar'
Now, uncomment the call to changeFooToBaz:
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
changeFooToBaz();
console.log(foo); #=> 'baz'
changeFooToBaz has indeed changed the contents of foo, a variable that was declared at a higher scope than the function.

Javascript: Get access to local variable or variable in closure by its name [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How can I access local scope dynamically in javascript?
Hi all.
We all know that you can access a property of a javascript object by it's name using the [] syntax.. e.g. ob['nameOfProperty'].
Can you do the same for a local variable? Another answer here suggested the answer is to use window['nameOfVar']. However, this only worked for the poster as he was defining variables at window-level scope.
I assume that this must be possible in general, as Firefox's Firebug (which I believe is written in javascript) can show local and closure variables. Is there some hidden language feature I'm not aware of?
Specifically, here's what I want to do:
var i = 4;
console.log(window['i']); // this works..
function Func(){
var j = 99;
// try to output the value of j from its name as a string
console.log(window['j']); // unsurprisingly, this doesn't work
}
Func();
I'm not aware of anything built into JavaScript to reference local variables like that (though there probably should be considering all variables are internally referenced by strings).
I'd suggest keeping all your variables in an object if you really need to access by string:
var variables = {
"j": 1
};
alert(variables["j"]);
Update: It kind of bugs me that there's no way to do this like you want. Internally the variable is a mutable binding in the declarative environment records. Properties are bound to the object they're a property of through the object's environment records, but there's actually a way to access them using brackets. Unfortunately, there's no way to access the declarative environment records the same way.
Accessing the variable with window or any other global accessor won't work because the variable is not globally accessible. But you can use can use eval to evaluate any expression:
<script>
function test(){
var j = 1;
alert(eval("j"));
}
test();
</script>
What about:
<script>
function Func(){
var fn = arguments.callee;
fn.j = 99;
console.log(fn['j']);
}
Func();
console.log(window['j']); //not global
console.log(Func['j']); //but not private
</script>
No, this isn't possible in general. JavaScript resolves identifiers inside a function using the scope chain; there's no single object that contains all the variables in scope, and the objects in the scope chain are inaccessible from JavaScript running in the page.
No, because the variable is only accessible from within the execution contexts that contain the variable's scope.
Put another way, the only way you can access j is if you are accessing it from something in the scope of test -- via an inner function, or whatever. This is because j, in a sense, doesn't exist to objects with a wider scope, like the global object. If it were otherwise, then variable names would have to globally unique.

JavaScript variable scope question: to var, or not to var

Many thanks in advance. I'm working out of a schoolbook and they're using one function to call another which opens a window:
function rtest(){
content='dans window';
oneWindow=open("","Window 1","width=450,height=290");
newWindow(oneWindow);
}
function newWindow(x){
x.document.close();
x.document.open();
x.document.write(content);
x.document.close();
x.moveTo(20,20);
x.focus();
}
So everything works fine, but my question is this: how is the newWindow() function able to access the contents of the "contents" variable in the rtest() function? And why, if I preface the "content" variable with "var", like this:
function rtest(){
**var content='dans window';**
oneWindow=open("","OneWindow","width=450,height=290");
newWindow(oneWindow);
}
...does an error get thrown (and the contents of the new window left blank)?
Can anybody explain to me what the difference between using var and not using var is?
Thank you!
Daniel
if you dont use var inside the rtest, it is automatically a global variable. which is why it is accessible from other javascript codes including newWindow. now, when you use var, it automatically a variable inside the rtest scope, so the ones that can use it now are those inside the same scope.
If you declare the variable using var inside the original function, it will become a local variable and will not be visible outside the function.
If you don't declare the variable at all, it will be global. However, best practice is to declare global variables. If your textbook doesn't do this, consider replacing it. If your professor doesn't do this, consider replacing (or reforming) him. :-) If you have trouble convincing him, you can (but not necessarily should) mention that I'm one of the top 200 users here.
For example:
var content;
function rtest(){
content='dans window';
oneWindow=open("","Window 1","width=450,height=290");
newWindow(oneWindow);
}
Also, the best way to open a blank window is to call open("about:blank", ...), not open("", ...).
It's about the function-scope, if you declare your variable with var, it will be available only in the scope of the function where you did it.
If you don't use the var statement, and you make an assignment to an undeclared identifier (an undeclared assignment), the variable will be added as a property of the Global object.
If you don't use var, then you are creating a global variable; that is, a variable that is accessible from any code anywhere in your program. If you use var, you are creating a local variable, which is a variable that is only accessible from within the scope in which it is defined (generally, the function it is defined in).
While global variables can be convenient at first, it's generally a bad idea to use them. The problem is that all of your code will share that one global variable; in the future, if you need to have two or more different versions of that variable for whatever reason, you won't be able to separate the two uses. Global variables can also be accessed or changed from anywhere within your program, so it can be hard to figure out what might be modifying or depending on one, while local variables can only be accessed within a limited, well defined section in code, which can easily be inspected.
With var you declare a local variable in the function which is thus not visible outside this function. Without var you are actually working on the window object and set or overwrite a field of it. Your global scope in client side Javascript is always the window object. So you could also have written window.content='dans window'; to make clearer what you are actually doing there, but otherwise it would be identical. By the way: the window variable is itself just a field of the window object that refers recursively back to the window.

Categories

Resources