I am writing a javascript programme which involves passing values between functions.
I have 3 functions called A,B and total and want to pass variable values from A and B into total.
function a() {
var result = 10;
total(result);
}
function b() {
var result1 = 20;
total(result1);
}
function total(r1, r2) {
var x = r1;
var y = r2;
console.log(x + y);
//remaining logic will go here
}
a();
b();
total();
For testing purposes i am only logging values from function a and b. But it is only getting value r1 from function a but fails for r2 from function b and says that r2 is not defined. I think it can only do one function at a time but I want it to get values from both a and b.
Try adding the variables at the top of your page then when they are used by your function they will be edited as your code runs through
function a(){
var result = 10;
total.a = result;
}
function b(){
var result = 20;
total.b = result;
}
var total = {
a: 0,
b: 0,
getTotal: function(){
console.log(total.a + total.b);
}
}
a();
b();
total.getTotal();
jsfiddle
Related
I'm trying to pass variables across functions,
something like
function one() {
var x = 1
}
function two() {
var y = x + 1;
}
alert(y);
Is there a way to do it?
edit:Thanks everyone for being so helpful, but maybe I should have been more specific with my question.
You current way has x and y in the scope of the function, which means the other function doesnt know it exists. Also, its good practice to name functions according to what they do. 3 straightforward ways to do this.
Global
Params
Inline
Set two variables outside of the functions scope that any function can reach.
var x, y;
function assignOne() {
x = 1;
}
function addOne() {
y = x + 1;
}
assignOne();
addOne();
console.log(y);
Pass in a parameter to to the function and return values.
function one() {
return 1;
}
function addOneTo(x) {
return x + 1;
}
const y = addOneTo(one());
console.log(y);
Perform functions inline
var x = null;
function one() {
x = 1;
}
function two() {
return x + 1;
}
one();
const y = two();
console.log(y);
You will need to hoist the scope, by extracting the variable declaration to outside of the functions. That is to say, define x and y outside of the functions. Note that you can still update their values from within the functions. However, don't forget that you'll actually need to invoke both functions as well!
This can be seen in the following:
var x, y;
function one() {
x = 1;
}
function two() {
y = x + 1;
}
one();
two();
console.log(y);
If you really want to get variable declared in one method, return it
function one(){
var x = 1;
return x;
}
function two() {
var x = one();
var y = x + 1;
return y;
}
alert(two());
Seems like you want to have shared state between both functions instead of passing arguments. So, an object oriented pattern seems to be appropriate.
class Thing {
constructor() {
this.x = 1;
}
one() {
return this.x;
}
two() {
return this.x + 1;
}
}
const t = new Thing();
console.log(t.one());
console.log(t.two());
If you want to share variables between functions but don't want to declare them in global scope, you can use a closure like this:
(function() {
var x, y;
function one() {
var x = 1
}
function two() {
var y = x + 1;
}
one();
two();
alert(y);
})();
I have a question about how javascript stores functions internally.
Given this code:
var makesomething = function (x) {
var thing = {
x: x
};
thing.do = function () {
this.x++;
};
return thing;
};
var x1 = makesomething(1);
var x2 = makesomething(2);
Since I called the makesomething function twice, does that mean that there are essentially two copies of the "do" function or do the objects have reference to the same function but get called with different closure?
There are two copies, one created each time you called makesomething().
You'll notice that x1.do === x2.do is false.
If instead you do this:
var doIt = function() {
this.x++;
};
var makesomething = function (x) {
var thing = {
x: x
};
thing.do = doIt;
return thing;
};
var x1 = makesomething(1);
var x2 = makesomething(2);
Then both refer to the same function, and x1.do === x2.do will be true.
function test(a, b){
a = a + 2;
b = b + 5;
}
var a = 1;
var b = 2;
test(a, b);
console.log(a);
console.log(b);
This return 1 and 2, but i would like 3 and 7.
Is possible to make two operation in one function? This working if i use return, but how to use return to two operation?
live: http://jsfiddle.net/anCq6/
The reason you are getting 1 and 2 instead of 3 and 7 is because there are two different a and b variables. There's the a and b you declared outside the function, and there is the a and b which represent the values you passed into the function. (Basically, the parameters declared in the function's parentheses are newly declared variables.)
If you want to change the external a and b, change your test function to the following:
function test(x, y) {
a = x + 2;
b = y + 5;
}
Or, alternatively, don't pass a reference into the function, so that the a and b in the inner scope refer to the same a and b as the outer scope:
function test() {
a = a + 2;
b = b + 5;
}
Just send it back as an object...
function test(a, b){
a = a + 2;
b = b + 5;
return {a:a,b:b};
}
var a = 1;
var b = 2;
var test = test(a, b);
alert(test.a);
alert(test.b);
DEMO HERE
This doesn't work because since numbers are passed by value and not by reference, you're modifying the local copies of those variables, however the ones in the outer scope remain unmodified.
If you remove the a and b parameters from your function, you'll get the behavior that you want since the a and b parameters that are being modified will be the ones in the outer scope.
What are references?
Here's a pretty decent answer - Javascript by reference vs. by value
In short, only objects and arrays are passed by reference. Although in reality it's more complex than this depending on how functions are defined and syntax, at this point you can assume that anything that's defined by calling new or the syntactic shorthands [] ( array ) and {} ( object ) are passed by reference. Other types like numbers and strings are passed by value.
Another solution: because of how variable scope works in JavaScript, you can just remove the parameters of "test" function and it will work.
function test(){
a = a + 2;
b = b + 5;
}
function test(){
a = a + 2;
b = b + 5;
}
var a = 1;
var b = 2;
test();
console.log(a);
console.log(b);
I thought I have understood the idee of closures, but the following code
behaves surprisingly for me:
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
var a1 = new A(1);
var a2 = new A(2);
console.log ('a1.getX1()=%d', a1.getX1 ()); // 1
console.log ('a2.getX1()=%d', a2.getX1 ()); // 2
console.log ('a1.getX2()=%d', a1.getX2 ()); // 2 ???
console.log ('a2.getX2()=%d', a2.getX2 ()); // 2
I could understand if prototype methods behave differently from
instance methods, but this looks like x has become a static variable.
Changing the order of calls does not change results.
When you change the prototype you're changing the function for all instances of the given class, including those that already exist.
Therefore when you call...
A.prototype.getX2 = function () { return x; }
You're setting that for the existing a1 instance of A. So effectively you're ending up with the following pseudo code:
<all instances of A>.getX2 = function () {
return <latest value of x passed to A constructor>;
}
The static member here is A.prototype.getX2. The second call to A.prototype.getX2 = function () { return x; } (due to var a2 = new A(2);) replaces the first one. To understand it you can reverse the order of instantiations:
var a2 = new A(2);
var a1 = new A(1);
Then you'll have:
a1.getX1()=1
a2.getX1()=2
a1.getX2()=1
a2.getX2()=1
You're defining getX2 twice, each time you create a new A. The result for that function will always be the last X. Considering rewriting your code like this:
function A(x) {
this.x = x;
this.getX1 = function() {
return this.x;
}
}
A.prototype.getX2 = function() {
return this.x;
}
var a1 = new A(1);
var a2 = new A(2);
console.log('a1.getX1()=%d', a1.getX1()); // 1
console.log('a2.getX1()=%d', a2.getX1()); // 2
console.log('a1.getX2()=%d', a1.getX2()); // 1
console.log('a2.getX2()=%d', a2.getX2()); // 2
This way, you only define getX2 once and it works as expected.
You have written
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
This constructor overwrites A.prototype.getX2 each time.
So first
var a1 = new A(1); // This invokes A and adds a function `getX2` to the prototype of `A`which returns `x` that is `1`
var a2 = new A(2); // This invokes A and overwrites the function `getX2` in the prototype of `A` with a function which returns `x` that is `2` now.
So it should be like this
function A(x)
{
this.getX1 = function () { return x; }
}
A.prototype.getX2 = function () { return this.getX1(); }
I'm trying to add 10 over and over for every invocation of d. It stays 20 every time, why?
function d() {
var c = [10];
c[0] += 10;
alert(c[0]); // always 20
}
d(); d(); d(); // supposed to be 20, 30, 40...
You create a new array and assign it to c each time the function is called. That resets it.
Move the assignment so it is outside the function (so it only runs once).
var c = [10];
function d() {
c[0] += 10;
alert(c[0]);
}
d(); d(); d(); // will be 20, 30, 40...
But globals are good source of bugs, so it is considered good style to wrap such things in closures to minimise the use of globals.
var d =(function () {
var c = [10];
function d() {
c[0] += 10;
alert(c[0]);
};
return d;
})();
d(); d(); d();
#Quentin already explained the reason for your problem and provided a solution. For more information about variable scope, have a look at the MDN JavaScript Guide.
As an alternative, you can assign the value to a property of the function:
function d() {
var c = d.c || (d.c = [0]); // initialize property if not set
c[0] += 10;
alert(c[0]);
}
What you have is local variable. Which gets initialized to 10 every time you invoke the function.
Try using global variable as
var c = [10];
function d() { c[0] += 10; alert(c[0]); // always 20 }
Why not just
var c = 10;
function d(){
c+=10;
alert(c);
}
d();d();d();