Let say we declare a variable in the global context, like so:
var someVariable = "someValue";
We can always access its value like window['someVariable'] as it is in the global execution context.
But, how can we access it value the same way if it is inside some function and not in the global execution context? For e.g.
function someFunction(someParameter) {
var someVariable = "some value";
// some code
}
I want to do something like someFucntionContext['someParameter'] or someFucntionContext['someVariable'] to access the value of those variables in the execution context of the someFucntion like I just did for the variable declared in the global context.
That's not possible without returning objects or instantiating the function and accessing the property.
Global variables are automatically a property of the window object, provided you use var and not let or const. Such as root level functions being automatically a method of the window object. But functions do not behave like primitive objects. You need to do something like
function Favorites(){
return{
food: "burrito",
color: "gray"
}
}
var fav = Favorites();
var favfood = fav.food; //fav['food']
OR
function Favorites(){
this.food = "burrito";
this.color = "gray";
}
var fav = new Favorites();
var favfood = fav.food; //fav['food']
And like so
var favfood = window.fav.food;
var favcolor = window['fav']['color']
One of the approach could be exposing certain properties of the function itself.
function fn(){
fn.num = 100;
}
//access fn.num
console.log(fn["num"])
You can control which properties you want to expose from the function itself. For example,
function doSomething(num, addStr){
//expose num
doSomething.num = num;
var str = "Hello ";
if(addStr){
str += addStr;
}
//expose str
doSomething.str = str;
}
//set num
doSomething(100);
//access num
console.log(doSomething.num)
console.log(doSomething["num"])
//set num and str
doSomething(200, "Jerry!")
//access str
console.log(doSomething["str"])
Related
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();
...
var myVar = 5;
var example = function() {
var myVar = 10;
// How can I access the global variable 10?
};
If there is a global variable with the same name as a local variable, how can I access the global one?
I am not using es6.
I am running it in jsdb, not a browser or node so I do not have access to objects 'Window' or 'global'
Assuming you can alter the code calling your example() function, you should be able to pass the current scope using Function.prototype.call() and access it using this. For example
'use strict'
var myVar = 5;
var example = function() {
var myVar = 10;
console.info('Local:', myVar)
console.info('Outer:', this.myVar)
};
example.call({ myVar })
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
}
I have a global variable:
var chart;
A function which creates the chart:
function setChart(variableName, chartContainer){
variableName = new CanvasJS.Chart(chartContainer, {**params**});
variableName.render();
};
I call setChart
setChart(chart, "chartContainDiv");
If I call chart.render(); later, it doesn't work.
How can I achieve this? / What am I misunderstanding?
Since you're passing a string into the function, you end up trying to assign this:
setVar("globalVar");
// In setVar...
"globalVar" = 5
which obviously doesn't work. Passing in just the variable name itself will almost work as expected:
setVar(globalVar);
// In setVar...
globalVar = 5
HOWEVER
Because of variable scope, inside the setVar function you have a local variable with the same name as the global one. Doing any assignation here will just set the local variable to 5, where the global variable will remain at whatever value it used to be.
var myVar = 1;
function setVar(globalVar) { globalVar = 5; alert(globalVar); }
setVar(myVar); // alerts 5
alert(myVar); // alerts 1
Interestingly, if you pass the string in then you're able to set it via array-access on the window object:
setVar("globalVar");
// In setVar...
window[variableName] = 5; // window["globalVar"] = 5;
but trying to do that by passing the variable itself in doesn't work...
setVar(globalVar);
// In setVar...
window[globalVar] = 5; // window["5"] = 5 // or whatever globalVar contains
The TLDR version of this is that this is the only way to do this exactly as you're trying to do in the OP (although there are other ways such as Ahmad's answer, where you set a specific variable without passing it):
var myVar = 1;
function setVar(varName) { window[varName] = 5; }
setVar('myVar');
Use the function as a factory that returns a chart object, instead of passing it an empty variable. This uses the exact same concept, by creating an object and then returning that object, but it doesn't use a CanvasJS object for simplicity purposes:
function setChart(chartContainer) {
var variableName = new String(chartContainer);
return variableName.toUpperCase();
};
var chart = setChart("chartContainDiv");
var chart2 = setChart("blahBlah");
console.log(chart.toString()); // "CHARTCONTAINDIV"
console.log(chart2.toString()); // "BLAHBLAH"
http://jsfiddle.net/n8Lg4wqy/3/
first you have to be clear on the scopes of variables and global variables. In you example, there is no line where you set globalVar to 5. You only set a local variable for the function setVar called variableName to 5.
what you should do is:
var globalVar;
function setVar(){
globalVar = 5;
};
now if you want to have a global variable or a set of global variables then you should have them in an object and then have a function that take that variable name and an optional value that you to assign.
var globalVariables = {"globalvar1" : "", "globalvar2" : "", .... };
function setGlobalVar(variableName, Value) {
globalVariables[variableName] = value;
}
setGlobalVar ('globalvar1', 5); // this would do it
I just write a test html file to learn about object in javascript. The code is as follows
in script tag
<script type="text/javascript">
var obj = new ParentFn();
var obj2 = new AnotherParentFn();
var temp;
function initer()
{
temp = obj.Adding();
obj2.caller();
}
function ParentFn()
{
this.a = 10;
this.b = 20;
}
function AnotherParentFn()
{
this.a = 30;
this.b = 50;
}
AnotherParentFn.prototype.caller = function()
{
var self = this;
temp();
}
ParentFn.prototype.Adding = function()
{
var self = this;
document.getElementById("id_div1").innerHTML = " Method Called and Result of a+b is " + (self.a + self.b);
}
</script>
In body i use
<button onclick="initer()"> Click here to test </button>
<div id="id_div1"></div>
Problem is when AnotherParentFn.prototype.caller is called from initer() function temp variable is still undefined. What is wrong with the code??
My task is to assign the function ParentFn.prototype.Adding in a global variable and call the global variable from AnotherParentFn.prototype.caller function. How to achieve it?
You don't need to save it as a global variable. It's already saved in ParentFn.prototype. All you need to do is invoke it with .call and pass in your desired receiver. You can implement AnotherParentFn.prototype.caller like this:
AnotherParentFn.prototype.caller = function()
{
ParentFn.prototype.Adding.call(this);
}
This way you can get rid of temp completely. You also don't need to assign this to a local var self everywhere.
Parentheses are used to execute a function.
When you assign the value to temp, you are calling the function and assigning the result (undefined) to temp. To store a reference to the function in temp, omit the parentheses.
temp = obj.Adding;
By writing temp = obj.Adding(); it stores the return value. not function pointer in temp. Use this
function initer()
{
temp = obj.Adding;
obj2.caller();
}
First of all, the reference to obj.Adding is not assigned properly; it should be this (without parentheses):
function initer()
{
temp = obj.Adding;
obj2.caller();
}
Then, inside AnotherParentFn.prototype.caller itself, you must pass the current object as this explicitly during the invocation by using .call():
AnotherParentFn.prototype.caller = function()
{
temp.call(this);
}