1

Snippet 1:

var a; // undefined variable named 'a'
function a(foo) { // a function named 'a'
  var foo = "Hello World";
  console.log(foo);
}
console.log(a); // output is: [Function: a], but why not undefined?

Snippet 2:

function a(foo) { // a function named 'a'
    var foo = "Hello World";
    console.log(foo);
}
var a; // undefined variable named 'a'
console.log(a); // output is: [Function: a], but why not undefined?

I could have just shown Snippet 1 to ask this question - however I showed both just for completeness purposes. I have wrote some brief comments in them as well.

My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?

I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine (during the creation phase)? i.e. which one gets hoisted above the other? I have read it is that the function declaration has precedence over the variable declaration - but why is this the case?

Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same? And since ‘a’, in both places of the code, represents the function declaration, what would be the value of ‘a’ at its memory location/address after parsing line 1 and line 6 during the creation phase? Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?

In both code snippets, ‘var a’ is undefined, so why isnt ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?) Does the Javascript engine simply say, “Ah, if we allow ‘var a’ to ‘overwrite’ ‘function a() {…}’, it would continue to be undefined and thus be unusable. Whereas, if we allow ‘a’ to represent said function, then at least the user can invoke said function (even prior to its declaration, without getting a reference error)". This is very unlikely to be the case but sounds logical/ideal, maybe?

So, my questions are:

  1. What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? Is it something we just accept prima-facie because it's an implementation of the ECMAScript specifications or can we explain this behaviour?

And

  1. If possible, could someone please answer what is happening in memory when this occurs every step of the way?

I have been trying to use my intuition for the last 8 hours (where I ended up spiraling into another dimension of the other peculiarities of JavaScript, but that’s another issue in itself) but I would to know if there is a simple or concrete explanation or answer to this behaviour.

Any help in understanding all of this would be much appreciated.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
151SoBad
  • 115
  • 9
  • 1
    Are you working through a set of homework questions because this question is [very similar to your other question posted not so long ago](https://stackoverflow.com/questions/46014533/variables-with-the-same-name-but-the-local-scope-variable-isnt-being-used-why). – Andy Sep 02 '17 at 15:45
  • I don't think I've ever seen such a homework question before. I initially planned to ask this question in those threads, but they would end up being too long. It is related, but has nothing to do with that question, hence this separate thread. Any amalgamation would confuse and detract away from complete understanding of my queries. Regardless, the point is to not only to help myself but to help others who may have a similar question in the future... and fortunately, I have not found a similar question like this - can you? – 151SoBad Sep 02 '17 at 15:46
  • 1
    "*In both code snippets, ‘var a’ is undefined*" - uh, no it's not? – Bergi Sep 02 '17 at 16:14
  • @Bergi I did not want to write too much in the comments in the snippet. What I meant was, if 'var a' was on its OWN (and there was no function 'a'), prior to the execution phase occurring, var would be undefined, correct? because it has no value... – 151SoBad Sep 02 '17 at 16:30
  • Yes, `a` would have the value `undefined` if there was no function declaration – Bergi Sep 02 '17 at 16:45
  • Thanks Bergi. In that case, why does JS spec and MDN describe 'undefined' as a value? Is that an engine implementation that follows suit? Is a variable that holds an 'undefined' value ACTUALLY a value in memory that is undefined? If so, what's this value? I doubt it's a string that says "undefined". Is it null (0x00)? is it a nop (0x90)? Or is it nothing, but rather just represents a 'state'? That's what I always thought it was - until the JS spec, MDN and a multitude of stackoverflow threads descirbed it as a 'value' - hence I interpreted that as, in memory, the undefined variable has a value – 151SoBad Sep 02 '17 at 16:49
  • @151SoBad Yes, it is a value (why wouldn't it?). How it's implemented in engines doesn't matter (and will likely differ). – Bergi Sep 02 '17 at 17:27
  • @Bergi because from some of the comments provided below, it's been said that it does not give a value. "The statement var a; means "I announce that a variable named a exists"", "var a; does not give a a value, so it has no effect on a's value.". But I'll just accept it. – 151SoBad Sep 02 '17 at 17:42
  • @151SoBad I said that the value `undefined` is a value. Not that `var a` does assign that to the variable when the statement is encountered in the execution. – Bergi Sep 02 '17 at 18:30
  • Again to clarify, any variable initialisation (i.e. `var a = 100`, **prior** to execution, has its variable declaration (i.e. `var a`) hoisted and at the same time assigned **undefined** as its value. It is only until the variable initialisation statement is encountered during execution where it will be assigned the value `100`. Is that correct? Thus your statement that `var a` is assigned undefined when the statement is encountered in execution is contradicts that, isn't it assigned undefined _prior_ to execution, not _during_ execution? Yes it's semantics but I just want to be clear on this. – 151SoBad Sep 03 '17 at 21:21
  • @151SoBad Again, I did *not* say that `var a` is assigned `undefined` when the statement is encountered in execution. Yes, the rest is still correct. – Bergi Sep 04 '17 at 11:11
  • Hope this thread clarifies things for anyone with the same concerns and queries. Many thanks Bergi. – 151SoBad Sep 04 '17 at 11:46

2 Answers2

4

My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?

There is only one place in either snippet where the variable a is given a value, and that's the function declaration. The statement var a; means "I announce that a variable named a exists". Since the function declaration is taking care of announcing that it exists and giving it a value, the var a; statement doesn't really have any effect.

In fact, if we refer to Section 10.5.8 of the JavaScript spec, we can see that the end result of this var a; is literally to do nothing because the a variable is already declared by the time the var a; declaration is processed.

I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine during the creation phase?

Nothing is taking "precedence" here. There is only one variable named a. var a; does not give a a value, so it has no effect on a's value.

Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same?

There is only one a variable and it only takes on one value, so this question is mostly nonsensical, but in rough terms, the a variable itself would only exist in one place and it would only refer to one value (memory location), which would be the definition of that function.

Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?

My knowledge of the creation phase isn't that great, but in the course of this code's execution, a only ever refers to one value, as I said above.

In both code snippets, ‘var a’ is undefined, so why isn’t ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?)

See my first and second answers.

What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? And

As I've said, it's not taking "precedence", but the reason JavaScript has function hoisting is in order to allow people to call functions from a line in the code before the function's actual definition, similar to how other major languages like C# and Java do.

If possible, could someone please answer what is happening in memory when this occurs every step of the way?

The JavaScript spec doesn't define what happens in memory. It defines the code's external behavior. So this would be an implementation detail and would be engine-specific.

Here is a rough blow by blow of what happens when your code is executed (in both cases):

  1. Create a variable called a and assign it the value of that function you have there.
  2. Check whether there is a variable called a. There already is one, so do nothing.
  3. Execute console.log and pass it the value of a (which is that function)
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Interesting - thanks for your response. My understanding was that nothing is assigned a value during the creation phase, prior to the step-by-step code execution by the engine. Is this false for objects (including function objects, of course)? In addition, let's just say they were differently named, i.e. var a, function b(foo) { ...}, these are different memory locations aren't they? You're saying there is only one memory location, and that is for variable 'b' in this case. But what about variable 'a'? Why then do we not get a reference error when we compile, but instead get undefined? – 151SoBad Sep 02 '17 at 16:03
  • @151SoBad Broadly speaking, there would be three memory locations involved in your a/b example: (1) The location where the `a` variable exists (2) The location where the `b` variable exists (3) The location of `b`'s value. As I said above (in slightly less clear terms), there are two memory locations involved in your initial example: (1) The location of the `a` variable itself (2) The location of `a`'s value (the function). – JLRishe Sep 02 '17 at 16:07
  • I completely agree and totally understand all that you've said there in your comment. My question too, might have been stated in less clear terms. I understand there exists only one variable, a, which is at one location in memory. My question should and could be better posed as: how is the value for that memory address changing as we step through the code, during the creation phase of the execution context? – 151SoBad Sep 02 '17 at 16:15
  • By extension, on a similar note, could you please tell me what the value of the variable 'a' would be in my a/b example in the comments? (This is actually another one of my questions in another thread, which currently is still unanswered, but you appear to have some knowledge of memory so if you know that'd be greatly appreciated!) – 151SoBad Sep 02 '17 at 16:17
  • @151SoBad I think you have a misunderstanding of how a javascript engine works. There is no "step-by-step execution" of lines, and there is no "hoisting" that does in some way re-order lines. There's a parsing phase which discovers the variables introduced to a scope, and when executing the code the scope is created as one - with all variables, and their respective initial values (`undefined` for `var`, functions for `function`, or none at all for `let` and `const`). – Bergi Sep 02 '17 at 16:19
  • @151SoBad If you want to know what value a variable has, just `console.log` it or use a debugger to step through your code. – Bergi Sep 02 '17 at 16:22
  • @151SoBad Again, I'm not that clear of what the creation phase is so I couldn't answer what's happening during the creation phase. What I can say, based on the spec, is that because there is a function declaration for `a`, it is similarly created and given a variable during step 5.f of the Declaration Binding Instantiation procedure and it does not take on any value after that. – JLRishe Sep 02 '17 at 16:22
  • @151SoBad _By extension, on a similar note, could you please tell me what the value of the variable 'a' would be in my a/b example in the comments?_ Is value would be `undefined` because it is not given a value. – JLRishe Sep 02 '17 at 16:23
  • @Bergi The comment where I discussed about "step-by-step execution" of line I did mention the context was when the code is executed. Is that actually not the case? I agree and understand what you just talked about is what occurs during the creation phase of the execution context, which essentially involves parsing -- exactly what you described. – 151SoBad Sep 02 '17 at 16:28
  • @JLRishe I don't particularly understand what's said in step 5.f as it's a bit too jargonistic for me, as I will need to do some research on "SetMutableBinding". But when you said "it does not take on any value after that", is that because it becomes immutable, or simply because nothing 'overwrites' that variable, in my code, after that? I presume the latter of course, but just wanted to confirm. – 151SoBad Sep 02 '17 at 16:52
  • @151SoBad It is the latter. The variable remains entirely mutable. – JLRishe Sep 02 '17 at 17:12
0

The function declaration gets hoisted before the variable hoisting.

console.log(a);

var a = 42; // assignment

console.log(a);

function a(foo) { // a function named 'a'
  var foo = "Hello World";
  console.log(foo);
}

console.log(a);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • I totally agree and I understand it's an entirely different scenario when there's an assignment that's happening. I just want to know, in the scenario where no assignment is occurring, why function declaration gets hoisted before the variable hoisting. Is it something we just accept prima-facie because it's an implementation of the ECMAScript specifications or can we explain this behaviour? – 151SoBad Sep 02 '17 at 15:54
  • @151SoBad _I just want to know, in the scenario where no assignment is occurring, why function declaration gets hoisted before the variable hoisting._ Because that's how the spec defines the behavior? Is there anything you need to know beyond that? – JLRishe Sep 02 '17 at 16:01
  • @JLRishe, well no, that's exactly what I was wondering. Further, I also could not find a reference that exactly says that in the spec, hence that question I just posed in the comments here. Further to 'spec, for all I know, different implementations of the spec persist different behaviour. I am not too sure what's with the hint of attitude here. Yes, my questions may not be specifically coding related, and perhaps on the nitty-gritty and trivial side of things, but surely someone out there is just as curious (maybe not actually, but am I on the wrong site to ask these questions?). – 151SoBad Sep 02 '17 at 16:07
  • @JLRishe look for all I know I could be approaching how to learn Javascript incorrectly and to just accept things prima-facie, but in most cases, I've seen people describe phenomenons and idiosyncrasies within this language that logically make sense (and things that don't make sense which aren't described in the spec either). It seems some may have better understanding of the implementation and how it works, so I was interested to see if such an understanding existed. I don't come from a technical background so my line of questioning may come across as unusual but they are good intentions. – 151SoBad Sep 02 '17 at 16:11
  • @151SoBad Yes, hoisting is concretely defined in the spec (though it's not actually called hoisting and it's defined across a few different sections of the spec), so the observable effects of it should not vary from one implementation to another. Here is an MDN page that thoroughly explains hoisting in easy to understand language: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting and here is a blog post that points out all the parts of the spec that define the hoisting behavior: http://johnkpaul.com/blog/2013/02/11/what-is-hoisting-really/ – JLRishe Sep 02 '17 at 16:12
  • No I agree hoisting is defined in the spec albeit not called hoisting, but I couldn't find anywhere that discussed the behaviour that function declaration are hoisted before variable declarations. It may be the interpretations, but I've seen numerous sources that talk about how hoisting is different for functional declarations and variable declarations. Noting that, I wanted to know why the former, is hoisted 'before' the latter (I understand you said nothing takes 'precedence' and that this isn't the case), but why do a multitude of sources discuss it? What's actually happening then? – 151SoBad Sep 02 '17 at 16:23
  • 1
    @151SoBad Look at [section 10.5](http://es5.github.io/#x10.5) of the spec. Function hoisting takes place in step 5 of that procedure. Variable hoisting takes place in step 8. Step 5 is before step 8, ergo function hoisting happens first. – JLRishe Sep 02 '17 at 16:27
  • Thanks - I'll take a look at that now - just noted that on your above post. – 151SoBad Sep 02 '17 at 16:30
  • @151SoBad A point I tried to make in my answer is that it is really irrelevant which one happens first. If it were in the opposite order, the observable result would be the same: `var a;` would create a variable named `a` and the function declaration would give it a value before any statements started executing. And your `console.log(a)` would still log the same value. – JLRishe Sep 02 '17 at 16:34
  • @JLRishe thanks for re-iterrating that. I completely agree. In fact, if I am interpreting you correctly, I believe I mentioned that immediately below the end of my snippets. I understand both achieve the same result, due to hoisting. In other words, ignore snippet 2, snippet 1 would be enough to pose my question. I was confused as to why it resulted in the variable 'a' referring to the function 'a', and not the data variable 'a'. I believe my confusion stemmed from the point you made that func declarations result in a value assigned to the variable, whereas variable decls don't. Is that right? – 151SoBad Sep 02 '17 at 16:39
  • That question related to value assignment depending on whether it's a function declaration or a variable declaration was my first comment to your insightful reply. I think the answer to that would clear up my main unease. In fact, as mentioned earlier, I discussed the other side to that here: https://stackoverflow.com/questions/46013456/undefined-if-its-defined-as-a-primitive-value-what-is-it-defined-in-terms – 151SoBad Sep 02 '17 at 16:42
  • There's no answer yet - but I thought since Javascript spec (as well as MDN) defines 'undefined' as a primitive VALUE, yes it's defined as a VALUE, hence I took that to mean YES a variable that's not assigned a value, would be 'undefined' and thus IN MEMORY WOULD BE assigned a value. So my question in that thread was... what is that value exactly in memory? However, from your comments, it appears as though THERE IS NO VALUE for variable declarations, is that correct? If so, genius! Please let me know. My apologies for the caps, there is no BBcode here so I can't bold and have to rely on caps. – 151SoBad Sep 02 '17 at 16:43
  • @151SoBad My point was not that your two code samples are equivalent, but rather that even if the spec were written in such a way that variable hoisting took place first, it would have no observable difference as compared to the actual situation where function hoisting takes place first. – JLRishe Sep 02 '17 at 16:51
  • @JLRishe again, thanks for reiterating that to force that point. The premise of your point however relies on a more fundamental idea, which I just asked about. That is, it assumes no arbitrary value that represents 'undefined' (as somewhat insinuated by the ES spec, etc) is assigned in memory to the variable? In other words, if a value was assigned in memory to the variable 'a', your point there would not be correct, is that right? I think after we answer this (which is only to clear my own confusion and most likely not yours), your points would make PERFECT sense. – 151SoBad Sep 02 '17 at 16:57
  • @151SoBad I said there would be no observable difference, as in, you would not be able to write code that would have a different output in function-hoisting-first land vs. variable-hoisting-first land. The variable may momentarily take on the value `undefined` in the latter (and in a matter of speaking, `undefined` _is_ a value), but not long enough for you to observe it. – JLRishe Sep 02 '17 at 17:18
  • Didn't u say in ur original post that it does not give a value? "The statement var a; means "I announce that a variable named a exists"", "var a; does not give a a value, so it has no effect on a's value."? I am a bit confused now. Further, in ur example above, in either func-hoisting-first land vs. var-hoisting-first land, instead of snippet 1, if we look at snippet 2, wouldn't that mean the variable is taking on the value of the function momentarily, before it is then ultimately taking on the value of undefined where it's output to the console? So it WOULD make a diff b/w the 2 snippets? – 151SoBad Sep 02 '17 at 17:47