Passing a global variable to a function - javascript

How come the following code is giving me a 0 instead of a 1? I want my function to change a variable declared outside the function but I do not want to specify the variable in the function declaration.
that = 0;
function go(input) {
input++;
}
go(that);
console.log(that);

As answered by Oriol, it doesn't work because the variable is passed by value, so you're not changing the "that" variable. A workaround would be to pass the variable name :
that = 0;
function test(input) {
window[input]++;
}
test("that");
console.log(that); // 1

That's because you are passing the variable by value, not by reference.
In javascript, all variables are passed by value, except objects, which are passed by reference (well, in fact they are passed by value too but they are a reference, see below).
And you can't change that behaviour.
Edit: If you don't know what passing by value/reference means, you should read a tutorial. But here you have some examples:
Variable passed by value
function foo(bar){
console.log(bar); // 1
bar++;
console.log(bar); // 2
}
var mybar = 1;
console.log(mybar); // 1
foo(mybar);
console.log(mybar); // 1
Variable passed by (value but used as a) reference
function foo(bar){
console.log(bar.a); // 'b'
bar.a = 'c';
console.log(bar.a); // 'c'
}
var mybar = {a:'b'};
console.log(mybar.a); // 'b'
foo(mybar);
console.log(mybar.a); // 'c'
In your case
You can do
Make your variable a property of an object (in your case, since it's a global variable, use window) and pass the object (reference), so you can alter it
window.that = 0;
function go(obj) {
obj.that++;
}
go(window);
console.log(that); // 1
Use a return value
var that = 0;
function go(input) {
return input++;
}
that = go(that);
console.log(that); // 1
Note that you can't do
Convert your variable into an object
var that = new Number(0); // Now it's an object number
function go(input) {
input++;
}
go(that);
that *= 1; // Now it's a literal number
console.log(that); // 0
That's because objects are passed by value too, but they are a reference. That means that inside the function you can change the properties of the outer object (because it's a reference) but you can't change the entire object, because it's passed by value.
See examples here: https://stackoverflow.com/a/3638034/1529630

This has to do with pointers, scope, passing variables by reference, and all that jazz.
If you really want to do this, you can pass an object in Javascript like this:
var that = {value: 0};
function go(input) {
input.value++;
}
go(that);
console.log(that.value);
All we've done is made that an object which is by definition passed as a reference in Javascript. Then we just make sure we properly modify the object's attributes.

Your code
that = 0; //Global variable
function go(input) { //input is argument and is not passed by reference
input++; //This just increments a local copy i.e 0
}
go(that); //Passed 0
console.log(that);
Instead do this
that = 0;
function go() {
that++;
}
go(); //Not passing any variable .. function can already see the gloabl "that"
console.log(that); // This will print gloabl i.e. 1

Actually you could just add console.log(input) inside the function and it would work just fine.
Please correct me if i'm wrong. Hope i helped !!
I would be glad if somebody could explain why im wrong

Related

JavaScript return by reference

I have a function that returns a variable and a function which edit the variable value.
But it's not working and I don't know why.
And what is the correct way to do this?
Here is my code:
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
The value of test is a primitive and so it is indeed not a reference.
A solution: make the exposed test property a getter, so that the value of the private test variable is retrieved at the moment the property is accessed:
return {
changeTest:changeTest,
get test() { return test }
}
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest,
get test() { return test }
}
}
var b = t();
b.changeTest();
console.log(b.test);
With this pattern, the test variable remains private, and you only expose the features you want to. So in this case you allow explicitly to read the test value, but not to write it.
NB: you can shorten the object literal notation to just:
return {
changeTest,
get test() { return test }
}
In changeTest you have to use this.test instead of test.
function t(){
var test = 1;
var changeTest = function(){
this.test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
If you would like to increase inside of the function, you need to use this keyword inside, just like the following:
function t(){
const changeTest = function() { this.test++; };
return { changeTest, test: 1 };
}
const b = t();
console.log('original value', b.test);
b.changeTest();
console.log('increased value', b.test);
The reason is why it is happening because you are not modifying the value inside, it is called lexical closure what you face with, as the documentations states:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Using the this keyword the code accesses the proper test variable.
For further explanation please read further here:
Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I hope this helps!

Why is non-static variable behaving like static?

function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.

Are all parameters to Javascript functions passed only by value?

If I have a variable like this:
I created something similar to an ENUM like this:
var ContentStatusId = {
All: 0,
Production: 1,
Review: 2,
Draft: 3,
Concept: 4
}
When I call a function like this:
doTask(myParam) {
var a =
}
With doTask(ContentStatusId.All);
Is there any way that I can find out anything about the parameter passed to the function or is it completely passed by value only? Are there any other ways to pass parameters to a function?
In JavaScript all parameters are passed by value.
In the case of a primitive, the value is the primitive value.
function test(arg) {
console.log(arg);
}
test(1);
arg will have the value of 1.
However, if you say
test({});
then arg will contain a value which is a REFERENCE to the object we just created.
Edit to address comment
You can do...
doTask(myParam) {
if (myParam === ContentStatusId.Review) {
// Do stuff
}
}
doTask(ContentStatusId.Review);
or
doTask(myParam) {
switch(myParam) {
case ContentStatusId.Review:
// Do stuff
break;
}
}
There is nothing calling pass by reference in javascript.
Everything gets passed by value only.
E.g
If in case of primitive value
e.g
var a = 10;
console.log(a); // 10
fun xyz(a); // passing a
function xyz(a) {
a += 10;
console.log(a); // 20
} // function will receive the value. If you modify it, It will still will not be reflected back to what you passed
console.log(a); // 10
Other way round,
When you pass object to a function, The references gets copied.
e.g
var obj = { 'a': 10 };
console.log(obj.a); // 10
function xyz(obj) {
obj.a = obj.a + 10;
console.log(obj.a); // 20
} // here the obj will be copied as reference. So when you modify it, It will get reflected back to original object.
console.log(obj.a); // 20

Why the global variable remain the same after calling a function to increase it?

Why the global variable is still 5 after calling the increment function? Thanks in advance for any help.
<script>
function increment(val) {
val+=1;
}
var val = 5;
increment(val);
alert(val);
</script>
function increment(val) {
val+=1;
}
declares a variable val local to your function. You change your local variable and not the external one. It's the same as
function increment(val2) {
val2+=1;
}
You could do this :
function increment(val) {
return val+1;
}
var val=5;
val = increment(val);
or
function increment(holder, varname) {
holder[varname] = holder[varname]+1;
}
var val=5;
increment(window, 'val');
This is because primitive variables in Javascript are passed by value, not by reference.
When passing in a primitive type variable like a string or a number,
the value is passed in by value. This means that any changes to that
variable while in the function are completely separate from anything
that happens outside the function
Check this great blog entry for more info on this subject:
http://snook.ca/archives/javascript/javascript_pass
You don't need to pass the global vars.
When you pass the argument to a function, its creating a local copy of the valriable. So if you want to effect the global variable from the function, you don't pass it when calling the function, because you can anyway access the global variable, without passing.
<script>
function increment() {
val+=1;
}
var val = 5;
increment();
alert(val);
Notice that when you are defining the increment() function you have specified the parameter as **val**. So inside the function every reference to val is for this local argument. If you want to access the actuall global variable use window.val.

javascript - can we have self invoking function modules assigned to variables

Can variable be assigned self invoking function module so that the variable reference would trigger calling the function without the () operator. I want the variable to have the latest value based on the code in the function module.
the code could be
count = 0
var x = function(){ return count }();
alert x; // should give 0
count = 7
alert x ; // should give 7
thanks
This behaviour can be achieved via a getter, using Object.defineProperty, for example:
// Add a `somemethod` property to `window`
Object.defineProperty(window, 'somemethod', {
get: function() {
return Math.random();
}
});
console.log(window.somemethod);
console.log(window.somemethod); // Different value
No, but you can use getters and setters of object properties: https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

Categories