I was asked what happens when we assign a value to a variable?
Meaning, let's say we have a variable data and we assign some value to it,
var data = 5
What actually happens in the background? What is the initial value of data and what happens, how value is assigned?
I tried to google articles for it, but I couldn't find anything related to working, may be I was not using correct keywords. If anyone have any article that I could follow or provide me some explanation that would be really great.
Because you are using var, the variable named data is first created by the interpreter at the start of the containing function block and its initial value at that point is undefined. This concept of moving the declaration to the start of the function block is called variable hoisting. This data variable will be a piece of memory internal to the interpreter. It will probably be allocated within a stack frame object.
A reference on hoisting:
Hoisting on MDN
Basics of hoisting in Javascript
Note also that functions declared like this:
function x() {
// code here
}
Are also hoisted so two functions in the same scope can call each other without worrying about declaration order.
When the interpreter gets to the point of executing the code where the declaration/assignment line is located, it will assign the value of 4 to the variable.
So, if your code was like this:
function myFunction() {
var sum = 3 * 4;
console.log(sum * 3);
var data = 5;
console.log(sum * data);
}
myFunction();
Then, what the interpreter actually does internally is this:
function myFunction() {
var sum = undefined, data = undefined;
sum = 3 * 4;
console.log(sum * 3);
data = 5;
console.log(sum * data);
}
myFunction();
In fact, you can even write this (somewhat ugly) code:
function myFunction() {
var sum = 3 * 4;
data = 6; // this will not be an error
console.log(data);
console.log(sum * 3);
var data = 5; // the declaration of data is hoisted
console.log(sum * data);
}
myFunction();
because, this is how the interpreter handles that:
function myFunction() {
var sum = undefined, data = undefined;
sum = 3 * 4;
data = 6; // this will not be an error
console.log(data);
console.log(sum * 3);
data = 5;
console.log(sum * data);
}
myFunction();
Note that let and const are block-scoped, not function-scoped and, if you try to reference them before their declaration, it is an error whereas var lets you do that. var is somewhat legacy and there is rarely (if ever) a reason to use var any more. It is safer to code with let and const instead. If you want function scope, you can still put your let or const at the top level of your function. But, you should generally declare your variables within the block that they are used/needed (restrict the scope to only what is needed).
The cpu will try to find a location in memory to hold the value of 5 and store the value in that address and store the address in the variable declared by var.
Related
This question already has answers here:
What is the temporal dead zone?
(3 answers)
Closed 2 years ago.
function pickColor() {
var random = Math.floor(Math.random() * colors.length);
return colors[random];
}
let pickColor = () => {
var random = Math.floor(Math.random() * colors.length);
return colors[random];
}
when I try and call the second one, I get an error that says "Cannot access 'pickColor' before initialization"
This is due something called "hoisting".
Basically when you use function, JavaScript moves the function to the top of the scope, so you can access it before initialization. Using let does not do this.
func_1();
function func_1() {
console.log("Thing");
}
func_2(); // will cause an error
let func_2 = () => console.log("Thing");
Details: Everything is technically hoisted, but let and const don't initialise until you get to their line. If you used var, the variable would start off as undefined
console.log(aa); //undefined
var aa = "hello";
console.log(aa); //hello
console.log(bb) // error
let bb = "hello";
Sidenotes (This part is not a solution to the above problem):
1. You should use const instead of let because I don't imagine you will need to change the value of a function.
2. Another difference between these declarations, is the value of the keyword this (it's the same in this situation but it can be different). I won't explain it here, you will probably come across it if you do more Javascript so worth looking into.
let pickColor = ... acts like a normal variable declaration + assignment.
The assignment = is done only when the actual line of code is executed.
You can call the function defined this way only if the call happens after the declaration, and in a visible scope.
On the contrary, function() definitions are completely 'hoisted', meaning they act like if they were defined on top of the JS block, and may be called "before" their definition.
Example inspired from http://adripofjavascript.com/blog/drips/variable-and-function-hoisting.html :
isItHoisted();
function isItHoisted() {
console.log("Yes! This function declaration acts the same as if it was declared _before_ the call.");
}
isThisOtherOneHoisted(); // throws an ReferenceError if used before it is assigned
let isThisOtherOneHoisted = () => console.log("Javascript sees that the name exists, but the assignment has not been done.");
/**
like :
There is this variable isThisOtherOneHoisted defined later, just so you know.
isThisOtherOneHoisted(); // error, variable does not even containt a function yet
isThisOtherOneHoisted = () => console.log(...)
*/
As additional details, javascript still "see" that it is used before it is intitialized, so that's why the error message is different than if you used a variable that doesn't exist at all.
The declaration is hoisted for any variable, but only the fact that the variable exist. The assignments with = is only executed where it is written.
The function declaration
function pickColor(){...}
is moved to the top of the scope (hoisted first) along with any variables declared with var.
where as function expression declared with let is only accessed when the interpreter comes across that line of code.
Example -
let two = () => {
console.log('something else');
}
var x = 'demo'
let y = 'demo123'
function one() {
console.log('something');
};
function three(){
one();
}
variable x , function one(){...} , function three(){...} are moved to the top of the scope as soon as the execution starts,
x is undefined until the line
x = 'demo'
then
x is assigned a value of 'demo'.
Variable y is not initiated or assigned any value until the line
let y = 'demo123'
since let is used to initiate the variable, same goes for the function expression initiated with let.
I have this code:
var point = 2;
var change = function(){point = 5};
function makeChange(point,change){
change();
alert(point);
}
makeChange(point,change);
The idea is to give the user the ability to pass a condition for the value of point before using it in the function.
But it doesn't take effect.
When I add alert(point) into the change function it alerts 5 but then alerts 2 in the makeChange function.
you can return point in change()
var point = 2;
var change = function(){ return point=5; };
function makeChange(point,change){
alert(change);
}
makeChange(point,change());
The problem is because of your parameter having the same name as the global variable point. In the code below:
var point = 2;
var change = function(){point = 5};
function makeChange(point,change){
change();
alert(point);
}
The call to change() inside makeChange will assign the local parameter point defined here makeChange(point,change) to 5. Not the global point which will remain as 2.
A easy way to solve this is to not use the same name point in the paramater as the global variable. Otherwise due to scoping JavaScript will think you are taking about the locally defined point inside makeChange:
var point = 2;
var change = function(){point = 5};
function makeChange(Point,Change){
Change();
}
makeChange(point,change);
alert(point);
You can do something like this when you call function.
makeChange(point,function(){return change})
Your code is doing fine - in fact, if you do a alert(point); right after makeChange(point,change); you'll see that 5 is returned.
The confusing bit is that the number (namely, 2) is passed into the makeChange function by value instead of the reference (namely, point). Therefore, if you alert point inside makeChange, the originally passed value will be given: 2.
I think the problem with this code is confusion between local and global variable.
So when you are passing variable in function makeChange(point,change) its behaving like local variable for function makeChange now in the next line when you calling the change function its changing global point value.
and then when you are doing alert since in function priority is local variable so you are getting 2.
You can use return approach for same.
var point = 2;
var change = function(){point = 5 return(point)};
function makeChange(point,change){
point=change();
alert(point);
}
makeChange(point,change);
This question may be answered elsewhere but I wasn't even sure how to begin searching for the answer. I'm new to JavaScript so this one is a struggle for me to understand.
Given the following code:
function multiple(n) {
function f(x) {
return x * n;
}
return f;
}
var triple = multiple(3);
var quadruple = multiple(4);
When I pass the following into the console:
console.log(triple(5));
I get what I expect, that is, 15. Likewise with any number, it will be tripled (or quadrupled if I used the second function).
But when I type triple into the console I get the following code:
f(x) {
return x * n;
}
Shouldn't the console return...
f(x) {
return x * 3;
}
...since 3 is coded into the function by virtue of the following code:
var triple = multiple(3);
3 is not hard-coded into the function. The code of f refers to the variable n, not the number 3. In your code, it so happens that there is no way to modify n, but imagine some code where there is a way to modify n:
function multiple(n) {
function f(x) {
return x * n;
}
function modifyN(newN) {
n = newN;
}
return { f: f, modifyN: modifyN };
}
var resultFor3 = multiple(3);
var triple = resultFor3.f;
var modifyTripleN = resultFor3.modifyN;
As you can see n is not hard-coded; it's no different from any other variable. In your specific example there is no way to modify n after the termination of multiple, but that does not make the values inside of the closure created by the invocation of multiple in any way "hard-coded".
Typing triple simply shows the source code of your function.
since 3 is coded into the function by virtue of the following code
That is an incorrect statement. You're not changing the source code of the function. To change the source code, you would have to redefine the entire function. All you're doing is passing in a parameter. The console is giving you the correct output.
When you're passing in a parameter to a function, on a high-level, at runtime it's just looking for whatever value is stored at the memory address for that variable (or something like that). But it is not rewriting the source code of the function.
Well, it is the same as it would if you had:
var n = 3;
function f(x) {
return n * x;
}
If you log f you will see the function above, but when you call it n will get its value from the closest variable called n in the scope chain, in our case n = 3, the value for the n declared in the global scope.
I don't know the exact way in which the JS engine stores the n variable inside that closure (in your case the closure created by the multiple function), but what is the important thing is that variables inside a closure are saved by reference not by value.
When writing a Javascript function I have always made the first assignment to a variable with var as in
var x = 1;
Later x may be something else. Should I write
if (something ) {
x = 2;}
or
if (something) {
var x = 2;}
If you could say why that would help.
You shouldn't use the var keyword if you're changing the value of a variable that's already been declared.
So:
var x = 1;
if(something) x = 2;
If the test was that simple, you could also write it like this:
var x = something ? 2 : 1;
It's also got to do with scoping. A new scope is created within functions.
For example:
var x = 1;
function myFunction(){
var x = 2;
}
myFunction();
console.log(x); // 1
Whereas, if you omitted the var keyword within the function, you would be altering the value of the x variable in the outer scope and the console.log(x) would show 2.
In code that simple, it actually makes no difference whatsoever to the JS interpreter.
For the sake of all who have to read the code, however, it is best to declare variables once at the top of the scope in which they are needed. This helps make it very clear to all who work with the code where a variable is scoped. It also helps you avoid running into confusing issues caused by the JavaScript hoisting mechanism (which mechanism is actually the very reason it doesn't matter in your code).
I'm trying to wrap my head around closures in Javascript.
Here is an example from a tutorial:
function greeter(name, age) {
var message = name + ", who is " + age + " years old, says hi!";
return function greet() {
console.log(message);
};
}
// Generate the closure
var bobGreeter = greeter("Bob", 47);
// Use the closure
bobGreeter();
The author said that this is an effective way of using closure to make private variables, but I don't get the point.
Could someone enlighten the benefits of coding like this?
A closure is a pair of a function and the environment in which it was defined (assuming lexical scoping, which JavaScript uses). Thus, a closure's function can access variables in its environment; if no other function has access to that environment, then all of the variables in it are effectively private and only accessible through the closure's function.
The example you provided demonstrates this reasonably well. I've added inline comments to explain the environments.
// Outside, we begin in the global environment.
function greeter(name, age) {
// When greeter is *invoked* and we're running the code here, a new
// environment is created. Within this environment, the function's arguments
// are bound to the variables `name' and `age'.
// Within this environment, another new variable called `message' is created.
var message = name + ", who is " + age + " years old, says hi!";
// Within the same environment (the one we're currently executing in), a
// function is defined, which creates a new closure that references this
// environment. Thus, this function can access the variables `message', `name',
// and `age' within this environment, as well as all variables within any
// parent environments (which is just the global environment in this example).
return function greet() { console.log(message); };
}
When var bobGreeter = greeter("Bob", 47); is run, a new closure is created; that is, you've now got a new function instance along with the environment in which it was created. Therefore, your new function has a reference to the `message' variable within said environment, although no one else does.
Extra reading: SICP Ch 3.2. Although it focuses on Scheme, the ideas are the same. If you understand this chapter well, you'll have a good foundation of how environments and lexical scoping work.
Mozilla also has a page dedicated to explaining closures.
The purpose of a closure is so that the variables you use inside a given function are guaranteed to be "closed" which means they do not depend on external variables - they only depend on and use their arguments. This makes your Javascript methods closer to a pure function, that is, one that returns the same value for the same given arguments.
Without using closures, your functions will be like Swiss cheese, they will have holes in them. A closure plugs up those holes so the method doesn't depend on variables higher in the scope chain.
Now, up until this point, my answer has been simply about organizing your code and style. So take this simple example. At the line with the comment, I invoke a function and the value of the variable a is captured for future use.
var a = "before";
var f = function(value) {
return function()
{
alert(value);
}
} (a); //here I am creating a closure, which makes my inner function no longer depend on this global variable
a = "after";
f(); //prints "before"
Now, why would you need to do this? Well, here's a practical example. Consider the following code that uses jQuery to add 5 links to the document. When you click a link, you would expect it to alert the number associated with the link, so clicking the first you would think would alert 0, and so on. But, this is not the case, each link will alert the value of 5. This is because the function I define depends on the variable i which is being modified outside the context of the function. The function I pass into bind is a Swiss cheese function.
for (var i = 0; i < 5; i++)
{
var a = $('<a>test link</a>').bind('click', function(){
alert(i);
});
$(a).appendTo('body');
}
Now, let's fix this by creating a closure so each link will alert its correct number.
for (var i = 0; i < 5; i++)
{
var fn = function (value) {
return function() {
alert(value);
};
} (i); //boom, closure
var a = $('<a>test link</a>').bind('click', fn);
$(a).appendTo('body');
}
I don't think this is a good example for private variables, because there are no real variables. The closure part is that the function greet can see message (which is not visible to the outside, hence private), but it (or anyone else) is not changing it, so it is more of a constant.
How about the following example instead?
function make_counter(){
var i =0;
return function(){
return ++i;
}
}
var a = make_counter();
console.log(a()); // 1
console.log(a()); // 2
var b = make_counter();
console.log(b()); // 1
console.log(a()); // 3
A better example may be
function add(start, increment) {
return function() {
return start += increment;
}
}
var add1 = add(10, 1);
alert(add1()); // 11
alert(add1()); // 12
Here, every time you call the returned function, you add 1. The internals are encapsulated.
The returned function still has access to its parents variables (in this case, start and increment).
On a lower level of thinking, I think it means that the function's stack is not destroyed when it returns.
Once you "get it" you will wonder why it took you so long to understand it. That's the way way I felt anyways.
I think function scope in Javascript can be expressed fairly concisely.
The function body will have access to any variables that were visible in the lexical environment of the function declaration, and also any variables created via the function's invocation -- that is, any variables declared locally, passed through as arguments or otherwise provided by the language (such as this or arguments).
It's called "closures" because they are "closed" around free variables, and there are much more ways to use it then only hiding state. For example, in functional programming, where closures came from, they are often used to reduce parameters number or set some constant for a function. Let's say you need function goodEnough() that will test if some result is better then some threshold. You can use function of 2 variables - result and threshold. But you can also "enclose" your constant inside function:
function makeThresholdFunction(threshold) {
return function(param) {
return (param > threshold);
}
}
var goodEnough = makeThresholdFunction(0.5);
...
if (goodEnough(calculatedPrecision)) {
...
}
With closures you can also use all the tricks with functions such as their composition:
function compose(f1, f2) {
return function(arg) {
return f1(f2(arg));
}
}
var squareIncremented = compose(square, inc);
squareIncremented(5); // 36
More on closure design and usage can be found at SICP.
I found this a pretty helpful article.
When is a function not a function?
//Lets start with a basic Javascript snippet
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(i);
}
return denomination;
}
This a basic function statement in Javascript that returns an array of [10,20,30]
//--Lets go a step further
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(console.log(i));
}
return denomination;
}
This will print 10, 20 ,30 sequentialy as the loop iterates, but will return an array of [undefined, undefined, undefined], the major reason being we are not pushing the actual value of i, we are just printing it out, hence on every iteration the javascript engine will set it to undefined.
//--Lets dive into closures
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(function() {
console.log(i)
});
}
return denomination;
}
var dn = generateCash();
console.log(dn[0]());
console.log(dn[1]());
console.log(dn[2]());
This is a little tricky, what do you expect the output will be, will it be [10,20,30]? The answers is no, Lets see how this happens. First a Global execution context is created when we create dn, also we have the generatecash() function. Now we see that as the for loop iterates, it creates three anonymous function objects, it might be tempting to think that the console.log within the push function is getting fired too, but in reality it is not. We haved invoked generateCash(), so the push function is just creating three anonymous function objects, it does not trigger the function. At the end of the iteration, the current local context is popped from the execution stack and it leaves the state of i : 40 and arr:[functionobj0(), functionob1(), functionobj2()].
So when we start executing the last three statements, all of them output 40, since it is not able to get the value of i from the current scope, it goes up the scope chain and finds that the value of i has been set to 40. The reason all of them will fire 40 is beacause every single component of dn lies in the same execution context and all of them on being not able to find the value of i in their current scope will go up the scope chain and find i set as 40 and output it respectively