What happens when two variables hoisting with the same name? - javascript

So if i declare two variables like this:
var a = 5;
var b = 10;
Javascript compiles code and until the assignment occurred these variables are undefined.
But if i write like that:
var a = 5;
var a = 10;
what happens when these variables hoisting?They both have name a and
they are undefined?Or maybe it's one variable and undefined is written twice in it?

Hoisting isn't really relevant here. You can't have two variables with the same name in the same scope. As many times as you write var a, there is just one variable a, which is hoisted no differently than if you had a single var a.
This code...
function() {
var a = 5;
var a = 10;
}
is functionally equivalent to this code, with a hoisted:
function () {
var a;
a = 5;
a = 10;
}

Related

Why am i not getting a type error in the below javaScript function?

Shouldn't the value of research be undefined as it has been declared as var research in the end. And hence the output be a type error. But I am getting the output as 'hello'. Any idea why?
function newFunc() {
function research() { console.log('hello') };
research();
var research;
}
newFunc();
Because of hoisting, what actually happens is more like this:
function newFunc() {
var research;
research = function() { console.log('hello') };
research();
}
newFunc();
The variable declarations and function definitions are hoisted - moved to the top of the function scope. So even though you are declaring it at the end, the compiler will move it to the top of the function so it ends up like:
function newFunc() {
var research = function () { console.log('hello') };
research();
}
newFunc();
JS only hoists declarations, not initializations. JS also hoists the actual function definition.
JavaScript only hoists declarations, not initializations. Documentation
So values will be assigned in the order they are placed, for instance:
x = 2;
console.log(x); //2
x = 3;
console.log(x); //3
var x ;
or in your case:
var x = 2;
console.log(x); //2
var x = 3;
console.log(x); //3
var x ;
Another thing is that, research in the var research; part is not undefined; it's rather a function expression till you override it by another assignment, like var research = '';
So in your case, it's like the following:
function newFunc() {
function research() { console.log('hello') };
research(); //'hello'
var research;
console.log(research) //function research(){console.log('hello');}
}

javascript scope privacy breaking?

So I came across something very odd while working on a javascript project just now and here's a boiled down example of the situation I'm confused about:
function doSomething() {
for(var d = 0;d < 10;d++) {
var shouldBePrivate = 5;
}
for(var d = 0;d < 10;d++) {
console.log(shouldBePrivate);
}
}
When you call doSomething() the shouldBePrivate variable is accessible in the 2nd for loop.
Shouldn't that not be possible?
All local variables in javascript have function scope and not the block scope (atleast before ECMAScript 2015). Which means that declared variables inside the function , available for whole function.
What you are referring is block scope. Unfortunately noblock scope in Javascript till ECMA2015. From ECMAScript 2015, you can declare your variables with let which can be referred only with in the block and they die as soon as you come out of that block.
MDN docs says (with examples)
Block Scoping Rules
With var
Variables declared with var do not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java. For
example:
var x = 1;
{
var x = 2;
}
console.log(x); // logs 2
This logs 2 because the var x statement within the block is in the same scope as the var x statement before the block. In C or Java, the equivalent code would have outputted 1.
With let and const
By contrast, identifiers declared with let and const do have block scope:
let x = 1;
{
let x = 2;
}
console.log(x); // logs 1
The x = 2 is limited in scope to the block in which it was defined.
You've stumbled upon something called hoisting. Because all variables are scoped to their containing function, var statements are internally moved to the top of the function.
That means that the interpreter will actually be running this code:
function doSomething() {
var shouldBePrivate;
var d;
for(d = 0;d < 10;d++) {
shouldBePrivate = 5;
}
for(d = 0;d < 10;d++) {
// now it's easy to see why this works
console.log(shouldBePrivate);
}
}
As of ES2015, you can use the let keyword instead of var which is lexically scoped - i.e. scoped within blocks, meaning that let shouldBePrivate = 5; will not exist outside the first loop.
function doSomething() {
for(let d = 0;d < 10;d++) {
let shouldBePrivate = 5;
}
for(let d = 0;d < 10;d++) {
// Reference Error for shouldBePrivate
console.log(shouldBePrivate);
}
}

Strict mode constrictions in Javascript

Hey so I have a function that takes a string from an input box and splits it up to numbers and letters, seen here:
function sepNsLs() {
"use strict";
var letterArray = [];
var numberArray = [];
separatorSpacerator();
var L = 0;
var listResult = document.getElementById("listInput").value;
var splitResult = listResult.split(separator.sep);
for (; L < splitResult.length; L++) {
if (isNaN(splitResult[L])) {
letterArray.push(splitResult[L]);
} else if (Number(splitResult[L])) {
numberArray.push(splitResult[L]);
}
}
}
My program has to pass through JSLint perfectly, meaning I need to use my functions in strict mode. I've only put them in strict mode now, meaning that my later functions that try to call the letterArray and numberArray that I declared and filled in the SepNsLs function no longer call those arrays and the arrays come up undeclared. Here's the code for one of them:
function addNumbers() {
"use strict";
var sum = 0;
var i = 0;
sepNsLs();
while (i < numberArray.length) {
sum = sum + Number(numberArray[i]);
i++;
}
As you can see, I call the sepNsLs function in the addNumbers function, but because of strict mode, I can't use the arrays sepNsLs creates. How do I fix this? Also, is there a website like the javascript beautifier that will fix my current code to fit strict mode conventions?
EDIT: Separator is declared a global variable here:
var separator = {
sep: 0
};
separatorSpacerator makes it so that if I choose to split my input strings at a space, the input box to tell my program to split at the spaces declares the word "Space" so I can see it is a space I'm splitting my string at.
function separatorSpacerator() {
"use strict";
var list = document.getElementById("listInput").value;
if (document.getElementById("separatorInput").value === "space") {
separator.sep = " ";
} else if (document.getElementById("separatorInput").value === " ") {
separator.sep = " ";
document.getElementById("separatorInput").value = "space";
} else {
separator.sep = document.getElementById("separatorInput").value;
}
if (list.indexOf(separator.sep) === -1) {
alert("Separator not found in list!");
clearResults();
}
}
I can't use the arrays sepNsLs creates. How do I fix this?
One way of fixing this would be to return arrays sepNsLs creates with e.g. a tuple - return [numberArray, letterArray]; , and then use it like:
a) es6 syntax:
var [numberArray, letterArray] = sepNsLs();
b) pre-es6 syntax:
var split = sepNsLs(),
numberArray = split[0],
letterArray = split[1];
Your addNumbers function should also probably return sum - otherwise, it doesn't produce any meaningful results as it stands.
Although not relevant to the question and is more of a matter of naming convention preference - you might want to explore on Hungarian notation and its' drawbacks.
Your problem is one of scope. When you try to access numberArray inside of addNumbers it doesn't exist.
You have a couple of options:
Make all the variables that need to be accessed in each function global.
Wrap all of your functions in an outer function and place the 'global' variables into that outer scope.
The better option is #2, because you won't actually be polluting the global scope with variables. And you can declare "use strict" at the top of the outer function and it will force everything in it into strict mode.
Something like this:
(function() {
"use strict";
// These are now in-scope for all the inner functions, unless redclared
var letterArray = [], numberArray = [], separator = {sep: 0};
function sepNsLs() {
// code goes here
}
function addNumbers(){
// code goes here
}
function separatorSpacerator(){
//code goes here
}
// ...more functions and stuff
// and then call...
theFunctionThatKicksOffTheWholeProgram();
}());
The variables letterArray and numberArray are declared local to the function sepNsLs, they are only accessed in that scope (strict mode or not). Here is an example:
function foo() {
var fooVar = 5;
console.log(fooVar);
}// fooVar get destroyed here
function bar() {
console.log(fooVar); // undefined because fooVar is not defined
}
foo();
bar();
A scope usually is from an open brace { to it's matching close brace }. Any thing declared inside a scope is only used withing that scope. Example 2:
var globalVar = 5; // belongs to the global scope
function foo() {
var fooVar = 6; // belongs to the foo scope
function bar1() {
console.log(globalVar); // will look if there is a globalVar inside the scope of bar1, if not it will look if there is globalVar in the upper scope (foo's scope), if not it will in the global scope.
console.log(fooVar); // same here
var bar1Var = 7; // belongs to bar1 scope
}
function bar2() {
var globalVar = 9; // belongs to the bar2 scope (shadows the global globalVar but not overriding it)
console.log(globalVar); // will look if there is a globalVar in this scope, if not it will look in one-up scope (foo's scope) .... untill the global scope
console.log(bar1Var); // undefined because bar1Var doesn't belong to this scope, neither to foo's scope nor to the global scope
}
bar1();
bar2();
console.log(globalVar); // prints 5 not 9 because the serach will be in foo's and the global scope in that order
}
foo();
What you need to do is to decalre the variables letterArray and numberArray where they can be access by both sepNsLs and addNumbers (one scope above both of them). Or return the value from sepNsLs and store it in a variable inside addNumbers. Like this:
function sepNsLs() {
// logic here
return numberArray; // return the array to be used inside addNumbers
}
function addNumbers() {
var arr = sepNsLs(); // store the returned value inside arr
for(var i = 0; i < arr.length; ... // work with arr
}

Alert is not displaying as expected.!

I just tried to check the scope variation by using the following code, but the result is coming not in an expected way. Can anyone explain what's going on exactly behind this..?
var a = 10;
+ function () {
a = 5;
var a;
alert("inline " + a); //Expected undefined but it displayed as 5
}();
alert(a); //Expected 5 but it alerted 10
DEMO
var hoisting
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declare
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
The compiler understands your code as
var a;
a = 5;
The position of a var declaration within a function doesn't matter. These are entirely equivalent:
function () {
var a;
a = 5;
}
function () {
a = 5;
var a;
}
when use "var a" you request global value of variable, use "window.a" to display it:
<script>
var a = 10;
+ function () {
a = 5;
var a;
alert("inline " + window.a); //Expected undefined but it displayed as 5
}();
</script>
var a = 10; // Global scope
+ function () {
a = 5; // You are not using Var here .. so it is also a global scope
var a; // Now you are mentioning your a is Var so scope is changed from global to this function
alert("inline " + a); // Printing 5 because you local scope a has value of 5.
}();
alert(a); // Printing 10 because of global scope a has value 10

Is there a way to access a shadowed variable in JavaScript?

var a=1; //first one
function x() {
var a=2; // second
function y() {
var a=3; // third one
}
}
Is there any way that function y() can access the second var a? I know it can access first one via window.a.
As-written?
No.
If you're not dead-set on naming each one a, then you can easily reference it.
The other solution would be to capture the outside variable within another variable, the trick being to not have the same variable name being referenced in the outside scope, from the inside scope.
window.a = 1;
function x() {
var a = 2,
inner_a = a,
y = function () {
var old_a = inner_a,
// a is equal to the closest var assignment ie: inside x()
a = 3;
};
}
or to pass it into the construction of a new function through closure
(immediately-invoking function)
window.a = 1;
function x() {
var a = 2;
var y = (function (old_a) {
return function () { var a = 3; };
// this inner function has access to "old_a", through closure
}(a));
}
This is a pattern that is preferred for several use-cases, when mixing JS with browser-functionality (ie: the DOM and DOM events, loops which assign timers or callbacks, AJAX responses, et cetera).

Categories

Resources