Having trouble understanding what is going on in code - javascript

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.

Related

It errors when I define variable in function

function addNumbers(x,y) {
sum = x + y;
var sum;
return sum;
}
addNumbers(5,9);
alert(sum);
It says: Uncaught ReferenceError: sum is not defined
When I put "var sum" before the function it works. What is the reason?
sum is only defined within the function. To use the function's return value, you do that directly:
function addNumbers(x,y) {
var sum;
sum = x + y;
return sum;
}
alert(addNumbers(5,9));
or
function addNumbers(x,y) {
var sum;
sum = x + y;
return sum;
}
var outerSum = addNumbers(5,9);
alert(outerSum);
Also note that I moved the var sum; to the top of the function. It doesn't really matter with var (I wrote a blog post about that), but it's better form. (It does matter with let and const, which you should probably be using instead of var.)
A variable only exists inside of it's scope (rule of thumb: starts at the previous { ends at the matching }), which especially makes sense for functions, as the variables inside the function only exist as long as the function gets executed.
function addNumbers(x,y) { // sum can be used from here on
var sum = x + y; // always declare variables where you ise them first, otherwide you get funny behaviour
return sum; // <-
} // you cannot use sum from here on
Now that means that you cannot access sum outside of addNumbers. However as your function returns the value of sum, you can store that in another variable:
var cool = addNumbers(1, 2);
Now you can use that cool variable and eventually log it.

Adobe javascript object undefined after function

I'm trying to learn some javascript by making a script for adobe after effects cs6. However i got stuck and can't figure out why. Let me explain my problem.
at row 156, in the doMath function is where my problems start. I can't figure out why the copyarray makes the layers variable undefined. it's not only the copyarray function that makes the variable undefined. The getSmallest and the getLargest does it aswell.
Some data from my code that i printed out (Might be useful).
Layername +Y max="80" target="4" inverted
axis Y
maxValue 80
target 4
positive true
inverted true
http://pastebin.com/tWQs4mf8 <--- my code
function doMath(layers){
for(i=0;i!=layers.length;i++)
{
if(layers[i].axis=="X")
{
layers[i].convertedData=layers[i].Xdata;
}
else
{
layers[i].convertedData=layers[i].Ydata;
}
alert(layers[i]) //Shows on the alert "Object object"
var copy = copyArray (layers[i].convertedData);
alert(layers[i]); //Shows undefined
var smallest = getSmallest(copy);
var largest = getLargest (copy);
var range = largest-smallest;
$.writeln(smallest + " " + " " + largest + " " + range);
if(layers[i].Positive==null)
{
var temp = getConverted(layers[i].convertedData,smallest,range,layers[i].maxValue,layers[i].inverted);
layers[i].convertedData=temp;
}
}
};
function copyArray(a){
var b = [a.length];
for(i=0;i!=a.length;i++)
{
b[i] = a[i];
}
return b;
}
Since i'm very new to javascript a simple reason what's happening is very appreciated.
It's not making layers undefined, it's making layers[i] undefined.
The problem is that you're using the global variable i in both loops. So when copyArray is done, i is set to layers.length. But the last element in layers is layers[layers.length-1].
You should always use local variables, not global variables, unless you have a good reason to need the data to be visible in multiple functions. So you should write:
for (var i = 0; i < a.length; i++)
in your loops.

Closures & JavaScript Syntax

I ran this in the console to find the value of result but I am stumped as to why it is 122. I cannot figure why, nor can I figure out how bonus is used in the code blow. Could someone explain the value of bonus and how they attained the values of each variable declared at the beginning please. I think it will help me and the rest of the world understand what's going in this learning script:
var hidden = mystery(3);
var jumble = mystery3(hidden);
var result = jumble(2);
function mystery ( input ){
var secret = 4;
input+=2;
function mystery2 ( multiplier ) {
multiplier *= input;
return secret * multiplier;
}
return mystery2;
}
function mystery3 ( param ){
function mystery4 ( bonus ){
return param(6) + bonus;
}
return mystery4;
}
Thank you very much in advance! (i've reviewed many resources and can't quite figure this rather basic one out). :(
Logging out or even better, writing out the returned values by hand and looking at one statement at a time helps you simplify the problem.
var hidden = mystery(3);
mystery(3) returns the function:
function mystery2 ( multiplier ) {
multiplier *= input; //notice input is 5
return secret * multiplier; // and secret is 4
}
Note that input and secret in this case will always be constant. This is not always the case though. Normally the reason why closure is used is to encapsulate variables in a private environment and the closure functions provide a way for non-local function to "reach" into the private scope. Those variables are not garbage collected after the function has finished executing because the returned functions still have access to them. Those function can still change the value of the variables inside the function even after the function has already ended.
var jumble = mystery3(hidden);
mystery3(hidden) returns the function:
function mystery4 ( bonus ){
return param(6) + bonus; //param(6), which points to mystery2 above,
// is just 6*5*4 = 120
}
var result = jumble(2);
Well, jumble(2), which "is" mystery4 above, is just 120 + 2 thus 122.
Well that's a pretty convoluted set of functions, but...
You can think of var hidden = mystery(3) as:
function mystery2( multiplier ) {
multiplier *= 5;
return 4 * multiplier;
}
Then, you can think of var jumble = mystery3(hidden) as:
function mystery4( bonus ){
return mystery2(6) + bonus;
}
...or
function mystery4(bonus) {
return 120 + bonus; // 120 is the result of 6 * 5 * 4
}
And then when you call jumble(2) it calls mystery(bonus) which does return 120 + bonus, or return 120 + 2;

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`

Understanding Snippet of Javascript

My professor has given us the following snippet of Javascript which we are supposed to analyze:
function createMultiplyer(multiple) {
n = multiple;
return function(num) {
return num * n;
};
}
var fiveMultiplyer = createMultiplyer(15);
var x = fiveMultiplyer(10);
alert(x);
alert(fiveMultiplyer);
This piece of code outputs an alert containing the text "150" followed by another alert which reads function(num) { return num * n; }. However, I cannot seem to understand why that is the case.
Can someone help me trace through the code and explain what is happening?
1 Let's consider line
var fiveMultiplyer = createMultiplyer(15);
After it, fiveMultiplyer variable will have return value of createMultiplyer function (that's how functions work). And that return value is
function(num) {
return num * n;
};
So, the code is similar to this (about n later)
var fiveMultiplyer = function(num) {
return num * n;
};
2 The next line is
var x = fiveMultiplyer(10);
Here we just invoke the function above. It also uses variable n: that variable is set in createMultiplyer function: n = multiple;. Thus, in our case n is 15 and fiveMultiplyer(10) is equivalent to 10 * 15.
That's all. Hope it helps.
edit
I'll also note that n is a global variable the way it's declared. So, you can access it from anywhere in the code.
var fiveMultiplyer = createMultiplyer(15); // Create a function that multiplies with 15
This function is locally known as fiveMultiplier
var x = fiveMultiplyer(10); // Invoke the multiply-by-15 with argument 10
The result is locally known as x
alert(x); // 150
alert(fiveMultiplyer); // The definition of multiply-by-15 as
// it is returned from createMultiplyer
function createMultiplyer(multiple) { // Returns a new function which
// multiplies with "multiple"
[var] n = multiple; // Note: "var" should have been used to keep "n"
// in scope (within "createMultiplyer").
return function(num) { // Return definition of multiplier function
return num * n; // "num" = arg. when invoked, "n" = multiplier at
// define time (when "createMultiplyer" was called)
};
}
The best way to think of it is as a class or object. var fiveMultiplyer is creating an object that holds a value n = 15 and has a function that accepts a number and multiplies it by n.
In Java this would look something like this
public class Multiplyer {
private int n;
public Multiplyer(int n) {
this->n = n;
}
public int multiple (int m) {
return n*m;
}
}
Multiplyer myMultiplyer = new Multiplyer(15);
System.out.println( myMultiplyer.multiple(10) );
In the JavaScript however the variable fiveMultiplye does not have to call its method, you simple pass it the required variables and it calls the method and returns for you.
Hope that helps.
In JavaScript, you can have a variable which acts as a function too.
var fiveMultiplyer = createMultiplyer(15);
You are calling a CreateMultiplyer(15) function.
This function returns you another function and that is associated
with the fiveMultiplyer var.
var x = fiveMultiplyer(10);
You are actually invoking the function which was returned in previous step.
hence evaluating the value to 10 * 15 = 150
alert(x);
As explained this returns 150
alert(fiveMultiplyer);
As explained this returns the complete function
returned by createMultiplyer().

Categories