Variable not changing when function is called - javascript

Anyone see a bug in my code that stops the variable "player1Bananas" from changing? Everything else in the function works fine.
//update playerStats arguments:
//banana is a banana object
//x and y are the banana's position
//players bananas is player1Bananas or player2Bananas,
//ballPosition is "left" or "right"
updatePlayerStats: function(banana, x, y, playersBananas, ballPosition) {
playersBananas += 1;
gameController.bananasTaken += 1;
banana.x = x;
banana.y = y;
gameController.player1Score = 0;
gameController.player2Score = 0;
gameController.setUpPaddles();
gameController.setUpBall(ballPosition);
},
gameController.updatePlayerStats( gameController.Banana1, 20, gameController.canvas.height - 20 - gameController.Banana1.height,
gameController.player1Bananas, "left");
Thanks!

You're passing the value of gameController.player1bananas as a parameter to a function.
In the function that value is assigned to local variable playersBananas and is restricted by scope. When you make a change to it, you're no longer making a change to that variable you originally passed but instead the new variable playersBananas.
Example: http://jsfiddle.net/GHkJ6/
To fix this, you need to pass it as an object. JavaScript won't pass it as a value, but instead the object itself.
Example: http://jsfiddle.net/F446Q/

Because in JavaScript numbers are passed by value...
You have to pass something else than a single number, like a player state object({id:1, bananas:17} for example).

gameController.player1Bananas is a primitive type, so it is passed by value... not reference. This means that inside the function playerBananas no longer has any reference to player1Bananas, it is simply an integer value.
Try passing in an object instead... for example, you could have a player object with a bananaCount property. Then pass the player object into the function and increment the bananaCount property of the player object.
eg.
//update playerStats arguments:
//banana is a banana object
//x and y are the banana's position
//players bananas is player1Bananas or player2Bananas,
//ballPosition is "left" or "right"
updatePlayerStats: function(banana, x, y, player, ballPosition) {
player.bananaCount += 1;
gameController.bananasTaken += 1;
banana.x = x;
banana.y = y;
gameController.player1Score = 0;
gameController.player2Score = 0;
gameController.setUpPaddles();
gameController.setUpBall(ballPosition);
},
gameController.updatePlayerStats( gameController.Banana1, 20, gameController.canvas.height - 20 - gameController.Banana1.height,
gameController.player1, "left");
See this link for a good explanation.. http://snook.ca/archives/javascript/javascript_pass

change player1Bananas to global variable then change that same player1Bananas inside the function

Related

Having trouble understanding what is going on in code

Here is some code I'm really having issues understanding (JavaScript)
function func(x) {
var y = x + 2;
z = 20;
return function(y) {
var z = y * 3;
return function(z) {
return x + y + z;
};
};
}
console.log(func(3)(4)("z"));
output: 7z
I have a lot of experience with Java (only Java) and I'm really having issues understanding how JavaScript works.
I tried debugging and going step by step over code but I'm still very confused.
One sub-question I have is whether y on line 2 is the same y as in
return function(y) line.
Any help would be greatly appreciated!
When looking for value of variable, JS will pick it from the closest scope going upwards.
In line 5, the y is the y from the argument and not from the upper scope. That value although is enclosed (read closures), is not being used here.
Same, goes for the z below.
When running the statement return x + y + z; the outer scope (that is shadowing the variable y) is destroyed. So the other closes values are used ergo 3 and 4.
function func(x) {
var y = x + 2;
z = 20;
return function(y) {
var z = y * 3;
return function(z) {
return x + y + z;
};
};
}
console.log(func(3)(4)("z"));
Get yourself a good code editor for JS (vscode is great and free)
Go to a variable, press F2 and give it a more unique name.
check which occurrences are affected.
"use strict"! what is Strict Mode?
This is what your code then might look like.
"use strict";
function func(arg0) {
var var1 = arg0 + 2;
// undeclared/global variable
z = 20;
return function (arg2) {
var var2 = arg2 * 3;
return function (arg4) {
return arg0 + arg2 + arg4;
};
};
}
console.log(func(3)(4)("z"));
I think this makes it clearer what variable/parameter is what.
And if you run this, you'll get an error regarding your usage of the undeclared variable z, because strict mode doesn't allow this, whereas sloppy mode would create/use a global variable.
Sidenote: Take a look at Typescript. Coming from such a strict language like Java you might prefer the ability to type your code.
What I understand is from this function call is
fun(3)(4)("Z");
first call
x = 3;
y = 5;
z = 20;
second call
y=4;
z=60;
x=3;
third call
x=3; // from first function parameter
y=4; // y value from second function parameter
z="z" // third function parameter
In the it will return
3+4+"Z" = 7z
as string
All pre calculated values are useless
var is function scope, which means if you redeclare a variable in a function, it will be inside that function. It won’t mutate the outer scopes or global scopes same-named variable.
variableA = 16;
function incrementOne (localVariable) {
var variableA = localVariable + 1;
console.log("variableA internal", variableA);
}
incrementOne(10);
console.log("variableA", variableA);
And my request is not to use any syntax in js like this
variable = 16;
better use var if u really don't want to use let or cons.
var variable = 16
I can assure this that let and const will resolve your maximum understandings. Thanks.

Cannot use variables to change css property

I am trying to change the background-color of an element by clicking on a button. In 2 implementations of javascript, I am storing slightly different values in the same variable, and using the variables to change the background-color. I expect both implementations to work, but only one works. Here are the details.
In HTML, I have a <div id="foo">Lorem</div> element and a <button id="button">Click</button> element.
I have 2 different codes for JavaScript. The first one is:
var button = document.getElementById("button");
var x = document.getElementById("foo").style;
button.addEventListener("click",function(){
x.backgroundColor="red";
});
The second one is:
var button = document.getElementById("button");
var x = document.getElementById("foo").style.backgroundColor;
button.addEventListener("click",function(){
x="red";
});
The first one works, but the second one does not. The only difference between the two code snippets is in the first one, the variable x did not include backgroundColor and the background color of x was changed using x.backgroundColor="red";. In the second one, the variable x did include backgroundColor and the color was changed(tried to change) using x="red";.
Why does the first way work, but the second way does not?
In the first example, you are pointing x at the style object that exists for the foo component. When you assign a string to x.backgroundColor, you are effectively assigning a string to document.getElementById("foo").style.backgroundColor since x and style point to the same object in memory.
In the second example, you are simply assigning the style.backgroundColor string to x. You then assign a new string to x.
All that second attempt does is reassign x away from the current backgroundColor property value to the value of red. It's no different than this:
var x = 10;
x = 20;
console.log(x); // 20
In other words, x is not a reference to the backgroundColor property, it's a reference to the value stored in that property, so let's say the original value of the property was "Yellow", then x would be storing the string Yellow, it's not a reference to where that value came from - - only the value itself. So, when you change it, you aren't doing anything to the backgroundColor property, you are just changing the value of x from "Yellow" to "Red".
You can store the value you'd like to assign to backgroundColor as shown below:
// x doesn't store a reference to the object property. It stores
// the VALUE of the property at this moment in time.
var x = document.getElementById("foo").style.backgroundColor;
var color = "green";
document.getElementById("button").addEventListener("click", function(){
console.log("Original color of element: " + x);
x = "red"; // All this does is make x point away from it's previous value
console.log("New value of 'x': " + x);
// You need a statement that assigns a new value to the property
document.getElementById("foo").style.backgroundColor = color;
console.log("New color of element: " + document.getElementById("foo").style.backgroundColor);
});
<div id="foo" style="background-color:orange;">Lorem</div>
<button id="button">Click</button>
var x = document.getElementById("foo").style;
in this example, x is a style object, like:
{
padding: 0;
backgroundColor: blue;
}
while in the second example, x is actually a string, and in the callback function, x only is assigned with new string.
you can console.log(x) to see the differences of these two "x"s.

Unable to dynamically increment a property of an object

I'm trying to create a dynamic canvas animation using javascript. The intent is to increment the x property of many image objects and then draw them in the x position of the updated x property each time a draw() function runs. I'm not able to successfully increment this x property though - for some reason it always resets to 0.
I defined this global array to contain all the objects I will draw:
window.character = [];
I have this object constructor to create new image objects:
function Character(name, x, y){
//define the image object within the Character
this.imageObject = new Image();
this.imageObject.src = name+'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==';
window.character.push(this);
window.characterPosition = window.character.indexOf(this);
//set natural width and natural height once the image is loaded
if (this.imageObject.addEventListener){
this.imageObject.addEventListener('load', function(){
window.imgWidth = this.naturalWidth/2;
window.imgHeight = this.naturalHeight/2;
//set natural width and natural height to object
window.character[characterPosition]['imageObject']['w'] = window.character[characterPosition]['imageObject']['w0'] = window.imgWidth;
window.character[characterPosition]['imageObject']['h'] = window.character[characterPosition]['imageObject']['h0'] = window.imgHeight;
//set initial x and y position
console.log(x);
window.character[characterPosition]['imageObject']['x'] = x;
window.character[characterPosition]['imageObject']['y'] = y;
console.log(window.character[characterPosition]['imageObject']['x']);
//set loaded property for the object once loading is done
window.character[characterPosition]['imageObject']['loaded'] = true;
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
//test whether every object in array has the image loaded
if(character.every(imageLoaded)){
$('button#play').show();
};
});
} //end object constructor
Inside that constructor function, there is some weird behavior. I created a new object using:
var sun0 = new Character('data:text/javascript;base64,', 12, 12);
Then here's what I see from the console.log messages inside the object constructor:
console.log(x); //returns 12, as expected
window.character[characterPosition]['imageObject']['x'] = x;
window.character[characterPosition]['imageObject']['y'] = y;
console.log(window.character[characterPosition]['imageObject']['x']); //returns 0. Thought it would be 12
Ultimately, here's how I intend to animate the object across the screen. This draw() function runs on an interval every 10ms.
function draw(){
clear();
//draw characters
drawCharacter(window.character[0]['imageObject'],window.character[0]['imageObject']['x'],window.character[0]['imageObject']['y'],window.character[0]['imageObject']['w'],window.character[0]['imageObject']['h']);
window.character[0]['imageObject']['x'] += 10;
console.log(window.character[0]['imageObject']['x']); //returning 0 every time, not incrementing the way I expected it to.
}
How can I get this 'x' property to increment?
here's the JS Fiddle
Pointy answered your question in the comments, but to expand on this... you're trying to set x on an Image which can't be set. For instance, try this in your browser's console:
var img = new Image();
img.x = 1;
console.log(img.x); // this will be zero
That's effectively what you're doing. Additionally, in your code try changing ['x'] to ['myX'] and then it will work as expected.

Function updating a number var through a parameter doesn't correctly update number var

So I have this bit of code that goes like this
var number = 0;
function addnumber(numbertype){
numbertype = numbertype +50;
}
function numberupdate() {
document.getElementById('adiv').innerHTML = number;
}
Somewhere, I call
onClick="addnumber(number);"
Now, if I check the value of number with an alert, it displays correctly. But the number only goes to 50 once and doesn't climb the more I click, and even though an alert called within the addnumber() function will caluclate number correctly, it will not update the value of number when checked outside of that function.
I'm sure I'm missing something simple.
In your addnumber function, the variable that you're passing in is getting increased by 50, not (I'm assuming) number.
You could change it to:
function addnumber(){
number += 50;
}
You are confused with number and numbertype variable.
var number = 0;
function addnumber(numbertype){
number = number + numbertype +50;
}
function numberupdate() {
document.getElementById('adiv').innerHTML = number;
}
Arguments to a javascript function are either passed 'by value' in case of primitives, or 'by reference' in case of objects. Your var 'number' is a primitive. In this case, a copy is made of the primitive value, and passed as the argument. Addnumber therefore adds 50 to a copy of number, not to number itself.
When you want to change the value of a variable in this way, use an object, then it will work as you initially expected:
var number={value:0};
function addnumber(numbertype){
numbertype.value = numbertype.value +50;
}

Can I change a javascript variable within another variable?

Here is my problem. After hitting the increment button, y is equal to 7, but z stays equal to 7 instead of changing to 8. Why don't javascript variables update within other variables? Is there a solution to this problem? I'm sure there is a fundamental property of javascript I am failing to understand, but I can't seem to figure it out.
<body>
<script>
var y=6;
var z=1+y;
</script>
<button onclick="y++">Increment</button>
<button onclick="alert(y)">What is y?</button>
<button onclick="alert(z)">What is z?</button>
</body>
The value held on variable z is calculated the moment you assign it to the variable:
var z=1+y;
If you want it to change, you have to update it manually:
<button onclick="z=++y+1">Increment</button>
Most computer languages behave like that, I believe.
In JavaScript and other languages you can use "getters" and "setters" to achieve what you want, but the code will become more complex. Judge if you really think it's necessary:
<body>
<script>
var vals = {
_y : 0,
z : 0,
set y(val) {
this._y = val;
},
get y() {
this.z = this._y + 1
return this._y;
}
}
vals.y = 6;
vals.z = 1 + vals.y;
</script>
<button onclick="vals.y++">Increment</button>
<button onclick="alert(vals.y)">What is y?</button>
<button onclick="alert(vals.z)">What is z?</button>
</body>
http://jsbin.com/udediy/1/edit
Another simpler solution is to just use a function. That would work well for the example you gave:
<body>
<script>
var y=6;
var z = function() {
return 1+y;
}
</script>
<button onclick="y++">Increment</button>
<button onclick="alert(y)">What is y?</button>
<button onclick="alert(z())">What is z?</button>
</body>
http://jsbin.com/ojorax/1/edit
y is evaluated when you set z. At that time y is 6 so z is 7. When you increase y then z is not re evaluated (as you've found out).
y=1;
z=++y;//increment y and assign the value to z
// z will be 2;
z=y++;//set z to the value of y and then increment y
// z is now 2 and y is 3
If you want one variable to be dependent on the value of another variable you can't just assgin new values to them. You have to use getters and setters functions:
var myObj={
y:0,
x:0,
setY:function (value){
this.y=value;
this.x=value+1;
},
setX:function (value){
this.x=value;
this.y=value-1;
}
}
myObj.setY(4);
console.log(myObj.x);//=5
myObj.y=2;//breaks setting x, you have to use setters
console.log(myObj.x);//=5
As you can see the line myObj.y=2 breaks setting z so you can't assign values to either myObj.y or myObj.z without breaking it.
To prevent this from happening you have to make x and y private. In JavaScript you can simulate private variables using closures.
A warning for the folling code: if you plan to create multiple instances of your object use constructor functions and have private variables using code conventions (like _privateVar) instead of real privateness since JS doesn't support it unless you're planning on not using prototype.
var myObj=(function(){
var x=0;// x and y only exist in the funciton body
var y=0;// you cannot access them in myObj.x or .y
return{
setX:function(value){
//maybe check if value is a number here
x=value;
y=value-1;
},
setY:function(value){
//maybe check if value is a number here
y=value;
x=value+1;
},
getX:function(){
return x;
},
getY:function(){
return y;
}
}
})();
myObj.setX(6);
console.log(myObj.getY());//logs 5
myObj.y=22;
console.log(myObj.getY());//still logs 5
Using bfavaretto's syntax with get and set you can assign new values but internally JavaScript will use the getters and setters functions. This does not work in older browsers like IE8 and under.
var myObj={
_y:0,
_x:0,
set y(value){
this._y=value;
this._x=value+1;
},
get y(){
return this._y;
},
set x(value){
this._x=value;
this._y=value-1;
},
get x(){
return this._x
}
}
myObj.x=4;
console.log(myObj.y);//=3
once you assign the value of z = 1 + y z references a different location and there is no further relation between z and y
One way to do it is to wrap the variable in an object, which is passed by reference rather than by value:
var obj = { y : 6 };
var obj_2 = obj;
alert(obj.y); //6
alert(obj_2.y); // 6
obj.y++;
alert(obj.y); // 7
alert(obj_2.y); // 7`

Categories