Correct way of initializing vars on this cases? - javascript

I am aware that most common practice would be to put var a,b; on the top, but I want to extract every possible character (after running on JS Uglify), and it seems they don't delete unnecessary var initializing
I want to know if any of the following will cause problems and which is recommended
Case 1:
if(condition){
var a=-1;
var b="++";
}else{
var a=1;
var b="--";
}
Case 2:
if(condition){
var a=-1;
var b="++";
}else{
a=1;
b="--";
}
Case 3:
if(condition){
a=-1;
b="++";
}else{
var a=1;
var b="--";
}

This is the way it should be:
var a,b;
if(condition)
{
a = -1;
b = "++";
}
else
{
a = 1;
b = "--"
}
Variables should always be declared at the top of the function with the var keyword. Variable scope is at the function level, and not using var makes it a global variable. Declaring it at the top always ensures that you know the scope is for the entire function (and it is anyway), so when another programmer looks at it and doesn't know that scope is at the function level, he/she wont get confused and think the scope is only in the conditional.

It doesn't matter, since JavaScript has function scope, not lexical scope.
You can think of it as every var ...; statement being shunted up to the top of the function they're in. (That's what I do, at least.)
I'd write the code as
var a, b;
if(condition) {
a = -1;
b = "++";
} else {
a = 1;
b = "--";
}

Related

How do you take a variable from a function that takes an input from an html form and use it in another function

here i am taking a input from a drop down form on a html page. And i am putting it in to a var called AM.
var e = document.getElementById("UserTimeAM");
function onChangeAM() {
var AM = e.value;
var text = e.options[e.selectedIndex].text;
console.log(AM, text);
}
e.onchangeAM = onChangeAM;
onChangeAM();
From there a fetch is called to an api and i am using the AM variable in it. But the issue is that when the site is being served it comes back with an error saying AM is not defined.
lowHigh.forEach(d =>{
let wDate = new Date(d.time).getUTCDate();
let AM_Hour = AM;
let PM_Hour = PM;
AM_Hour = ("0" + AM_Hour);
if(wDate == i+1)
{
if(tidedata1.innerHTML == "")
{
tidedata1.innerHTML = `${AM_Hour}: - ${d.value}m`
tidedata1Full.innerHTML = `${AM_Hour}:am - ${d.value}m`
}
else
{
tidedata2.innerHTML = `${PM_Hour}: - ${d.value}m`
tidedata2Full.innerHTML = `${PM_Hour}:pm - ${d.value}m`
}
}
})
I thought using var would mean it was a global so the variable could be passed in to different functions.
You just need to initialize the AM variable in the scope outside of your two functions to make it possible to use it in both
var AM;
var e = document.getElementById("UserTimeAM");
function onChangeAM() {
AM = e.value;
var text = e.options[e.selectedIndex].text;
console.log(AM, text);
}
e.onchangeAM = onChangeAM;
onChangeAM();
lowHigh.forEach(d =>{
let wDate = new Date(d.time).getUTCDate();
let AM_Hour = AM;
let PM_Hour = PM;
AM_Hour = ("0" + AM_Hour);
if(wDate == i+1)
{
if(tidedata1.innerHTML == "")
{
tidedata1.innerHTML = `${AM_Hour}: - ${d.value}m`
tidedata1Full.innerHTML = `${AM_Hour}:am - ${d.value}m`
}
else
{
tidedata2.innerHTML = `${PM_Hour}: - ${d.value}m`
tidedata2Full.innerHTML = `${PM_Hour}:pm - ${d.value}m`
}
}
})
The problem
In order to fully understand the differences between each of the identifiers (let, var, const) we first need to understand the concept of scope.
What is Scope?
Scope determines the accessibility or visibility of variables to JavaScript. There are three types of scope in JavaScript:
Global scope
Function (local) scope
Block scope (new with ES6)
- Global Scope
Variables declared outside a function are in the global scope.
Global variables can be accessed and changed in any other scope.
- Local Scope
Variables defined within a function are in local scope and are not accessible in other functions.
Each function, when invoked, creates a new scope, therefore variables with the same name can be used in different functions.
Reference: JavaScript: Var, Let, or Const? Which One Should you Use?
Example
var first = 123;
if(true) {
var second = 456;
}
function abc(){
var third = 789;
}
abc();
Note that first and second are inside global scope, and third is in function (local) scope, because its declared inside a function
Important note
Variables declared using the var keyword are either globally or functionally scoped, they do not support block-level scope. This means that if a variable is defined in a loop or in an if statement it can be accessed outside the block and accidentally redefined leading to a buggy program. As a general rule, you should avoid using the var keyword.
Example:
function DoSomething(){
if(true){ //Some condition [only example]
var example = 123;
}
console.log({example})
}
DoSomething()
If it had been declared as a let, it would not be visible, and would belong to the ({}) block of the if, example:
function DoSomething(){
if(true){ //Some condition [only example]
let example = 123;
}
console.log({example})
}
DoSomething()
In this example above, i'm using let, with will generate an error, that is a good thing to alert the programmer.
How to solve
Just as #HaimAbeles said, you just need to initialize the AM variable in the scope outside of your two functions to make it possible to use it in both
Example:
var AM;
var e = document.getElementById("UserTimeAM");
function onChangeAM() {
AM = e.value;
var text = e.options[e.selectedIndex].text;
console.log(AM, text);
}
e.onchangeAM = onChangeAM;
onChangeAM();
...

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
}

Set a global variables and use them in function (javascript)

I am new to programming and I am stuck. Here is my code:
function Subtraction() {
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
var c = (parseFloat(a) - parseFloat(b)).toFixed(5);
alert(c);
}
This works fine to me, but I have many functions that waits for onclick event to be executed. And every function have the same a and b variables. How can I get them in global scope so I don't need to wait them over and over again? I tried to put them outside of the function, but what event can trigger their declaration? There is what I tried:
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
parseFloat(a).toFixed(5);
parseFloat(b).toFixed(5);
function Subtraction() {
var c = a - b;
alert(c);
}
I see two options at least:
One is to declare them after window has loaded.
Other is to pass the elements as function parameters:
1
var a,b;
window.onload = function(){
a = document.getElementById('inputA').value;
b = document.getElementById('inputB').value;
}
2
element.onclick = function(){
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
Subtraction(a, b);
};
Btw, capital letters is used for Classes, if its a normal function better to use small "s".
You can try to declare the vars in a different javascript source file or put them in an upper block the environment of the variables holds through the entire execution from the moment you declare them so if you do this:
<script src="declare_vars.js"></script>
<script src="use_vars.js"></script>
In declare_vars.js you can try doing:
var a;
var b;
and in the other scripts use them as you want and give them the values you need, they will always be available.
The value of an input is a primitive (specifically a string) and is therefore passed by value. This means that if you do this:
var oldvalue = document.getElementById('someinput').value;
document.getElementById('someinput').value = "derp";
alert(oldvalue); // it has not changed
What you can do, if you want, is cache the result of getElementById:
var inputA = document.getElementById('inputA');
var inputB = document.getElementById('inputB');
// in your function {
var c = parseFloat(inputA.value)-parseFloat(inputB.value);
// }
This works because the result of getElementById is the input element itself. You then retrieve the desired property of this element (.value) at the specific time you need it.
That said, avoid global variables. Put variables in a scope if you want, but don't make them global.
Disclaimer: this solution makes no attempt to avoid using global variables. The usage of global variables may introduce all sorts of problems, though for an application as simple as the one described by the OP the potential pitfalls are limited.
You can add the initialization in the change event handler of each input to make sure it is always up to date:
HTML
a<input id="inputA"/>
b<input id="inputB"/>
<button id="sum">sum</button>
JAVASCRIPT
var a,b;
document.getElementById('inputA').addEventListener('change',function(evt){
a = +evt.target.value;
});
document.getElementById('inputB').addEventListener('change',function(evt){
b = +evt.target.value;
});
document.getElementById('sum').addEventListener('click', function(evt){
console.log('Sum is ' + (a+b));
});
DEMO: http://jsbin.com/EZECEraR/2/edit

Javascript: Change value of variable inside conditional inside function

I'm trying to reuse a complicated function, and it would work perfectly if I could change the value of a local variable that's inside a conditional inside that function.
To boil it down:
var func = complicated_function() {
// lots of code
if (something) {
var localvar = 35;
}
// lots of code
}
I need localvar to be some other number.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Update: The answer is yes! See my response below.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Nope.
No, but it is possible to assign it conditionally so that the function signature (basically, the required input and output) does not change. Add a parameter and have it default to its current value:
var func = complicated_function(myLocalVar) {
// lots of code
if (something) {
// if myLocalVar has not been set, use 35.
// if it has been set, use that value
var localvar = (myLocalVar === undefined)?35:myLocalVar;
}
// lots of code
}
No.
Without changing the complicated function there is no way, in javascript you can manipilate this by using call and apply. You can override functions in the complicated function or add new if this is an option (but they won't be able to access the local variable localvar).
this is more for fun my real answer is still no.
If you are feeling crazy :)
var complicatedFunction = function() {
var i = 10;
var internalStuff = function() {
console.log(i); // 10 or 12?
};
return internalStuff();
};
var complicatedFunction;
eval("complicatedFunction = " + complicatedFunction.toString().replace(/i = 10/, 'i = 12'));
complicatedFunction(); //# => 12
If the function uses this.localvar:
var func = function() {
alert(this.localvar)
if (true) {
var localvar = 35;
}
// lots of code
alert(this.localvar)
}
var obj = {localvar: 10};
func.call(obj); // alerts 10 twice
If not, then you can't change it without changing the function.
In javascript variables are "pushed" to the top of their function. Variables in javascript have function scope, not "curly brace" scope like C, C++, Java, and C#.
This is the same code with you (the developer) manually pushing it to the top:
var func = complicated_function() {
var localvar = 0;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
}
Does declaring the variable "up" one function help you out? At least the declaration is isolated.
function whatever() {
var localvar = 0;
var func = function() {
var something = true;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
};
func();
alert(localvar);
}
whatever();
Here is the jsFiddle: http://jsfiddle.net/Gjjqx/
See Crockford:
http://javascript.crockford.com/code.html
JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.
I asked this question about three weeks ago and within a half hour got five answers that all basically told me it wasn't possible.
But I'm pleased to announce that the answer is YES, it can be done!
Here's how:
var newfunc = func.toString().replace('35', '42');
eval('newfunc = ' + newfunc);
newfunc();
Of course, it uses eval, which probably means that it's evil, or at least very inadvisable, but in this particular case, it works.

Variable declaration warning in VS2008

The following code in VS2008 gives me a "variable is already defined" warning:
if (someVar) {
var a = 1;
}
else {
var a = 2;
}
The warning is given on the second var a = .... To cure this warning I have done:
var a;
if (someVar) {
a = 1;
}
else {
a = 2;
}
But is this the correct way to do it?
Thanks,
AJ
Yes, that is the correct way to do it. There is no block scope in javascript; there is only function scope and global scope.
you could also give each "block" functional scope using anonymous functions, although it's not very practical in this case:
if (someVar) {
(function () {
var a = 1;
})();
}
else {
(function () {
var a = 2;
})();
}
As a side note, this is also why for (var i = 0; ...) is discouraged in favor of var i; for (i = 0; ...), to avoid 2 consecutive loops in the same function both trying to declare the variable i
It depends on how you're using those variables afterwards.
If they relate to the same object, then it's the correct way.
If they relate to different objects, then I'd rename the variables, as this would prevent maintenance issues in the future.
Either way is perfectly valid and fine (both examples ensure that the variable is declared with the var keyword), but generally it's best practice to declare your vars at the top of the current code block, as in your second example.

Categories

Resources