Can I confirm that the reason code snippet 2 (&3) work is because something like: when variableA is fully, or partly, assigned to variableB, variableB always gets what variableA is at the time variableB is (last) initialised?
The aim: to make a function that continually prints "red0", "red1" "red2" etc.
In the first snippet, when we come to log out colorNum, colorNum doesn't dynamically update its num value. It's as if colorNum captures what num at the last moment colorNum was initialised.
num = 0;
colorNum = "red" + num;
function printObject() {
console.log(colorNum);
num++;
}
setInterval(printObject, 2000);
Here colorNum is continually reinitialised. So the updated value of num is captured in colorNum because colorNum is reinitialised after num is updated.
let num = 0;
let colorNum = "red" + num;
function printObject() {
colorNum = "red" + num;
console.log(colorNum);
num++;
}
setInterval(printObject, 2000);
Similarly the return expression of fun is a new expression every-time fun is called. The return expression captures the value of num at the point in time the return expression is created.
num = 0;
fun = function(){
return "red" + num;
}
function printObject() {
console.log(fun());
num++;
}
setInterval(printObject, 2000);
In languages like JavaScript (which is to say, most common programming languages), assigning a primitive value from one variable to another establishes absolutely no permanent relationship between them. The assignment operator is an immediate imperative, after which the two variables sail off into the night.
Also, note that the assignment
colorNum = "red" + num;
is evaluated by first computing the value of the right-hand side. The string constant "red" and the value of num are concatenated. After that has happened, before that result value is assigned, there is no remaining trace of num. All the runtime has is the result value from the concatenation, and that value has nothing whatsoever to do with the variable num.
Now, reference assignment is a different story, to some extent, or at least superficially, but as far as the language actually works it's the same story. So in
let x = { a: "hello" };
let y = x;
y.a = "goodbye";
console.log(x.a);
the value of property "a" in the only object involved will change. However, if subsequently:
let x = { a: "zebra" };
y.a = "giraffe";
console.log(x.a);
it'll still be "zebra" because assigning a new object reference to x has absolutely no effect on y.
From older languages like C, from which JavaScript syntax is at least loosely derived, an assignment expression is literally a request to copy a value stored in memory from one place to another. It looks like algebra but it does not work like pencil-and-paper algebra. JavaScript is conceptually a higher level language, but the semantics are still the same.
You're right in your assumption. In code snippet 2 and 3 num gets added every time. In 1 it is only added 1 time. At the moment of assignment the variable's value is taken. Whether it changes later doesn't matter.
Note that if you study Javascript a bit longer, you'll notice a different behaviour for Object and other types where assignment doesn't mean later changes to the original are disregarded, but this is a more advanced topic.
There is nothing like partial assignment; either you assign or don't assign.
In the first example, where you write colorNum = "red" + num;, you are not partially assigning num to colorNum. Rather you are using num in creating a new string, and then you are assigning that new string to the colorNum variable. So, as long as you don't update the colorNum with new value, it continues to hold the old value (As long as we are dealing with primitive values like numbers, strings, boolean, etc. This changes when we are dealing with objects which are usually passed around as references).
In example 2 & 3, you are updating the value of colorNum variable every time and hence they are working fine.
In your code examples there is no "magic" behind the variables assignment. The only difference is the order of commands.
Normally, all commands run synchronously, so one-by-one (we are not looking into parallel now). Of course, there are some differences between programming languages, for example in JavaScript all variable and function definitions (var) goes to the start of the code.
Let's return to your code.
Your first example:
num = 0;
colorNum = "red" + num;
function printObject() {
console.log(colorNum);
num++;
}
setInterval(printObject, 2000);
Actually it has var before variable creation. Also I will add line numbers, so it will be easier to understand the order of commands:
/* 1 */ var num = 0;
/* 2 */ var colorNum = "red" + num;
/* 3 */
/* 4 */ function printObject() {
/* 5 */ console.log(colorNum);
/* 6 */ num++;
/* 7 */ }
/* 8 */
/* 9 */ setInterval(printObject, 2000); // 9
First of all, functions and variables created, so first commands will be in line 1, 2, 4 (we create function, but do not run it, just create).
After command in line 1 we will have num equal to 0.
After command in line 2 we will have colorNum equal to "red" + num that is "red" + 0 that is "red0"
Now we come to line 9. Here we calling function printObject every 2 seconds, so...
...when 2 seconds passed we call function printObject, so:
we run command in line 5 and print to console our colorNum that is still equal to "red0"`
line 6 increase num by 1, so now we have num equal to 1
... another 2 seconds passed and we call function again, so:
we run command in line 5 and print to console our colorNum that is still equal to "red0"(because we did not change the value insidecolorNumafter it was set in line2`)
line 6 increase num by 1, so now we have num equal to 2
and so on... We print always the same colorNum as it was created on line 2 and we never change it again, so console.log will use its original value
Ok, now I will be quicker. Your second example has one additional line inside the function: colorNum = "red" + num;. That is very good, because now we change the value of colorNum before we print it to console.
Your third example has different idea of getting the value that we will print to console. You have added another function, that calculates the value. So your code:
num = 0;
fun = function(){
return "red" + num;
}
function printObject() {
console.log(fun());
num++;
}
setInterval(printObject, 2000);
Is equal to:
num = 0;
function printObject() {
console.log("red" + num);
num++;
}
setInterval(printObject, 2000);
This is because your function fun has only one line of code: "red" + num, so I can replace this function call with this line.
Actually, you even do not need to have a separate line for num++, or even the printObject can be "inlined":
var num = 0;
setInterval(() => console.log("red" + num++), 2000);
Related
I'm trying to wrap my head around the return statement but I can't see a reason why I should use one. My code works just fine without using one...
In both examples my console prints out 10 not matter if I use return or not.
Without return:
var sum = 5;
function myFunction() {
sum += 5;
}
myFunction();
console.log(sum);
With return:
var sum = 5;
function myFunction() {
return sum += 5;
}
myFunction();
console.log(sum);
By default, functions return the value undefined. If you want the function to return some other value, you need to have a return statement.
You may also use a return statement to halt execution of the function based on some logic, again returning a value that has some meaning or just undefined.
In the first example in the OP, the function is called and the return value is not used for anything, so it doesn't matter what the return value is and a return statement isn't necessary.
In another scenario, the return value might be important, e.g. a function that generates an integer random number between 0 and 10:
function getRandomInteger(){
return Math.floor(Math.random() * 11);
}
function showRandomNumber() {
document.getElementById('s0').textContent = getRandomInteger();
}
<button onclick="showRandomNumber()">Show random number</button>
<span id="s0"></span>
In the above, the getRandomInteger function needs to return a specific value, so it uses a return statement. The showRandomNumber function just displays the random number, so it doesn't need a return statement as the caller (the listener on the button) doesn't care what the return value is.
Here is what is happening with your example:
var sum = 5; //Sets the sum to =5
function myFunction() {
return sum += 5; // += reassigns the global (sum) to 10
}
myFunction();
console.log(sum);
A better example would be this:
sum = 5;
function myFunction() {
var sumOther = sum + 5;
return sumOther;
}
console.log(“sum:” + sum); // 5
console.log(“myFunction:” + myFunction()); // 10
This is how you would get the run of the function and not the global variable ‘sum’
This is because you use (global) variable declared outside the function (function modify it directly so there is no need to return value). However it is not good way of write functions because they are less reusable because they need proper global context to be used. Better is to use something like this:
function myFunction(num) {
return num += 5;
}
var sum = 5;
var result = myFunction(5) ;
console.log(result); // -> 10
this function can be easily used ind different context because it have parameter num and works only on it (function uses only values declared inside its declaration and body)
The trick in your case a is scope of a function. In both cases variable sum is defined in global scope. When you calling the function, it goes through the following steps:
Look whether var sum is defined in current step Since it not defined
inside the function, go one step over and take a look into outer
scope. Yes, it is defined here, start using it.
Perform calculation.
You are using incremental operator sum += 5 so actually it can be
written as sum = sum + 5. If you will look into second case,
you'll notice that variable have increased value now. And since that
variable is taken from global scope, your function just mutates it.
NOTE: At this point no matter whether you are returning something
from function or not. Your function just mutated outer variable.
The last step - exit from function. As I said earlier, return value
matters only if you want to use result of function call directly,
for instance: var result = myFunction()
Example 1
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
let counter = makeCounter();
alert( counter() );
alert( counter() );
Above alerts 0 and 1 respectively.
Example 2
function makeCounter() {
let count = 0;
return function() {
return count+1;
};
}
let counter = makeCounter();
alert( counter() );
alert( counter() );
This alerts 1 and 1 respectively
In programming count++ is equivalent to count+1 , then why is the difference in above two examples. I know its something related to closure property and hoisting. But understand perfectly. Could you guys help.
Note: Please let me know whether I should change the title of the question if it does not make sense.
The expression count++ evaluates count, adds 1, stores the result in count, but the overall result (the net value of count++) is the original value of count.
The expression count + 1 evaluates count, adds 1, and returns the result. The value of count is not changed.
Interestingly, while it's possible to mimic ++count (pre-increment) with an alternative expression
var inc = (count += 1);
there's really no way (I can think of) to mimic count++ cleanly without using a function, because there's no getting around the need for a temporary storage location:
var inc = () => { let tmp = count; count += 1; return tmp }();
The operator semantics of post-increment ++ dates from C in the 1970s and probably earlier, and has been copied by many other languages, including JavaScript. Folklore (as I remember it, being an old person) held that the pre- and post-increment operators were inspired by addressing modes available in the DEC PDP-11 instruction set, but that's always seemed fairly unlikely to me.
In your first example, you are post incrementing, i.e. adding 1 after the declaration and use. If you used ++count (pre incrementing) you would get 1 and 2 in your alerts.
In your second example, you do not store the value of count+1 back into count, so on the second time around, count is still 0 and you get the same result again.
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
return sum / arguments.length;
}
When I try to call this like:
var average = avg(2,3,5);
average; // It works fine;
But how do I call it without assigning to a variable?
If anybody can give any suggestion it will be delightful..Thanks.
You'd simply call it like this:
avg(2, 3, 5);
If you want to see the result, put it in an alert call:
alert( avg(2, 3, 5) );
You don't need to put the result from calling the function in a variable, you can do whatever you like with it.
For example, use it as the value in an alert:
alert(avg(2,3,5));
You can use it in another expression:
var message = "The average is " + avg(2,3,5);
You can use it directly in another call:
someFunction(avg(2,3,5));
You can even throw the result away by not doing anything with it, even if that's not useful in this specific situation:
avg(2,3,5);
If you don't put the result into a variable or in a compatible context, this function cannot output anything, which makes it difficult to use unless you make it output the result. Try this :
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
var retvalue = sum / arguments.length;
consoloe.log("avg: "+retvalue);
return retvalue ;
}
Then it may help you to see whenever the function is called or not.
You need to understand the concept of expressions.
Every expression as a whole represents one value. An expression can be made up of multiple subexpressions that are combined in some manner (for example with operators) to yield a new value.
For instance:
3 is an expression (a literal, to be specific) that denotes the numeric value three.
3 + 4 is an expression, made up of two literal expressions, that as a whole yields the value 7
When you assign a value to a variable – as in var average = – the right hand side of the =-operator needs to be an expression, i.e. something that yields a value.
As you have observed, average will have been assigned the value five. It thus follows, that avg(2, 3, 5) must itself be an expression that evaluated to the value 5.
average itself is an expression, denoting the current value of said variable.
The most important thing to take away from this is, that avg() is in no way connected to var average =. avg() stands on its own, you can just think it like an ordinary value such as 5 (there are other differences of course).
If you have understood the concept of expressions and values, it should be clear that if you can do
var average = avg(2,3,5);
average; // It works fine;
You can also do
avg(2,3,5);
I was reading the following topic How do JavaScript closures work? and found this code:
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);
The author commented:
As expected, each call to bar(10) will increment x.memb. What might
not be expected, is that x is simply referring to the same object as
the age variable! After a couple of calls to bar, age.memb will be 2!
I am confused why it will return 2 always. Can you explain me how it will come 2 always?
What's happening here is that: foo returns a function that, when called, increments the memb property of the object originally passed in to foo.
It would be clearer for that parameter object, age, to be a simple object; but the original author is perhaps having fun here, so passes in a new Number - which, as far a Javascript is concerned, is as valid an object as any.
So when bar is called, the memb property on that Number object is created/incremented.
The "internal value" of that number remains unchanged; it's always 2. But age.memb gets incremented by one each time. That's what the author means by:
After a couple of calls to bar, age.memb will be 2!
The 2 here refers to the value of memb after being incremented a couple of times (ie twice), it's not related to the value of the Number that age just happened to be at the start. Call bar again, and age.memb will be 3.
It will not "always" be 2.
Author says: "After a couple of calls to bar, age.memb will be 2" - and after 2 calls it will be "2".
After 4 calls it will be 4.
Just paste this to firebug console:
function foo(x) {
var tmp = 3;
return function (y) {
//console.log(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
console.log(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);
bar(10);
bar(10);
bar(10);
console.log('result: ', age.memb) // result: 4
bar(10) has a reference to foo(2)
So each time you call bar(10). It will execute the inner function(closure) of foo which
is having parameter y as 10 and since bar has age reference as 2. So age will be 2 always if you call bar(10) and y will be 10 or so depending on value provide. Closure basically saves the reference to inner function even if the outer function is not there.
If I understand correctly you obtain some like a function pointer in bar. This points to the nameless function. This nameless function always receives the same input because foo is only called once i.e. x never changes. As a result there is no memory in the nameless function giving you the input value of x as a result always.
I was reviewing some today, when I encountered the following convention :
TestParam(1);
function TestParam(p){
var p = p + 1;
alert(p); // alerts '2'
}
Now, obviously, the developer didn't mean to delcare 'p' within the function, instead maybe meaning:
p = p + 1;
But the code still worked, i.e. the value alerted was "2". So it got me to thinking. What would happen in the following scenario:
var a = 1;
TestParam(a);
alert(a); // alerts "1"
function TestParam(p){
var p = p + 1;
alert(p); // alerts '2'
}
Again the alerts were as I suspected (as intimated in the comments above). So then I was curious as to what would happen if I used an object:
var a = { b: 1 };
TestParam(a);
alert(a.b); //alerts 1
function TestParam(p) {
var p = {b:p.b + 1};
alert(p.b); //alerts 2
}
So, in this instance, JavaScript has 'remembered' the variable a, even though when it is passed to TestParam as p, p is redeclared.
Now if I were to have done the following within the function, then both alerts would have been "2"
p.b++;
//var p = {b:p.b + 1};
I.e. it would have modified the member b of the original object. I get this. Its the previous scenario that baffles me!
I realise this is quite a hypothetical question that is unlikely to carry much real-world usefulness, but it still made me quite curious, as to what is going on in the background, and how exactly JavaScript is scoping and referencing these variables.
Any thoughts?
Variables are scoped to the enclosing function in JavaScript. And you can declare them as many times as you like.
Objects are not tied to variables; many variables can refer to the same object. (This is sometimes called aliasing.) This is what's happening in your last example. JavaScript has not "remembered" the variable a at all; rather, p and a refer to the same object, so when it is changed via p, you can see those changes via a.
Here's an example that might make more sense to you. Sometimes a person has more than one identity.
var Clark = new Person;
var Superman = Clark; // Maybe not everybody needs to know these two are
// the same person, but they are.
Clark.eyes = "brown";
alert(Superman.eyes); // should be brown, right?
Knowing the rules of the language you're using has tremendous "real-world usefulness". Not understanding these two rules is the source of a lot of confusion and bugs.
Javascript generally passes all arguments to functions by reference except when the argument is a number or a string. Javascript passes numbers and strings by value which is why your first example works the way it does.
I believe there's a typo in your code. I think you mean:
function TestParam(p) {
var p = {b:p.b + 1}; // p.b, not p.a (p.a == undefined)
alert(p.b);
}
In your example:
var a = { b: 1 }; // "a" is defined in the global scope
TestParam(a);
alert(a.b); // alerts 1
function TestParam(p) {
var p = {b:p.a + 1}; // "p" is defined in TestParam()'s scope
/* But not until after the expression on the right side of the assignment
has completed--that's why you can use p.a
alert(p.a); //alerts 2
}
At first, "p" is passed as a reference to the global variable "a", but then you redefine it in the first line. So, for example:
var a = { b: 1 };
alert(a.b); // Alerts 1
TestParam(a);
alert(a.b); // Alerts 2
TestParam(a);
alert(a.b); // Alerts 3
function TestParam(p) {
p.b++;
}