Local variable not accessible inside callback - javascript - javascript

I have this code snippet.
var mapping = {};
_.each(labels,function(i,label){
debugger;
});
but mapping variable is not accessible inside the function.
I have a similar code somewhere else
var labels = {};
_.each(arrOfFields, function(element,index){
labels[prefix+element.fcnbb] = element.UI.label;
});
and labels is accessible here and i am able to use it.
Please explain me why does this happen ??

The problem here that mapping variable isn't declare within the function code block.
In debug mode if you used a callback function like in here you need to declare it within the function, so debugger will save it as his local variable.
so:
var mapping = {};
_.each(labels,function(i,label){
console.log(mapping); // here
debugger;
});
Just write variable name even in console.log() function, the debug will know his local variables, and then you will have an access to the variable itself.

Related

Running a javascript function in global scope

In order to be GDPR compliant I wrapped all affiliate scripts on our webshop inside functions and add them to a job queue.
After the user accepts our privacy policy I run all queued jobs. I want to run them in global scope so all declared variables are accessible in global scope because some affiliate scripts are depending on global variables (I know that's ugly ;) ).
I know, I could rewrite all the javascript code and declare the varibales in global scope and wrap the rest of the code inside a function.
But then I would need to edit a lot of external modules (we are running a magento webshop and use external modules for including the affiliate scripts)
my current approach:
var jobQueue = [];
var add = function (fn) {
jobQueue.push(fn);
console.log("function pushed to queue");
};
var execute = function () {
while ((curJob = jobQueue.pop()) !== undefined) {
curJob();
console.log("executed job");
}
};
my problem is that some external scripts are depending on the variables declared inside my jobs. Is there any possibility to run the functions like the code was run globally?
I already found something like this but I could not make it work:
Javascript eval on global scope?
(this does not work with functions)
eval.call(window, x, y, z)
I found a possible solution but it is ugly:
I save the body of the function (How to get function body text in JavaScript?) to a string and evaluate it in window scope
var execute = function () {
while ((curJob = jobQueue.pop()) !== undefined) {
var entire = curJob .toString();
var body = entire.slice(entire.indexOf("{") + 1, entire.lastIndexOf("}"));
eval.call(window, body);
console.log("executed job");
}
};
Variables in Javascript have 'function scope', meaning that if you declare a variable inside a function, it won't be accessible from outside that function.
But when a variable doesn't exist inside a function, Javascript will look for that variable outside that function until it reaches the global object.
So variables declared in the global object are visible everywhere.
You can assign variables to the global scope just by declaring them in the global scope.
var pushing = "function pushed to queue";
var executed = "executed job";
var jobTitle = "... programing ...";
var jobQueue = [];
var add = function (fn) {
jobQueue.push(fn);
console.log( pushing );
};
var execute = function () {
while ((curJob = jobQueue.pop()) !== undefined) {
curJob();
console.log( executed );
}
};
// Lets add a Job
add( function(){ console.log( jobTitle ); } );
execute();
JS Bin
As you can see, the job added has access to the variable jobTitle that is declared in the global scope.
Hope it helps

Retrieving JS variable [duplicate]

This question already has answers here:
What is the scope of variables in JavaScript?
(27 answers)
Closed 8 years ago.
$('#lobSelect').change(function () {
var selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
});
console.log(selectedLob); //not available here
In the code above i'm using the variable selectedLob to store the value selected from dropdown.
how can i retrieve that value from outside the function?
Also say this function is stored in a file1.js - how can i access this variable from file2.js in a different folder.
Thanks
When you declare a variable, you make it local to the scope of the function it is declared within.
Declare it outside the function:
var selectedLob;
And don't re-declare it inside:
$('#lobSelect').change(function () {
selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
});
It will still be undefined here:
console.log(selectedLob); //not available here
because it doesn't get a value assigned to it until the change event fires, but it will be accessible in the wider scope after that event has happened.
You can use global variable for your task, but this will lead to polluting the global namespace.
The good practise is to use application namespace instead of global namespace
Your file1.js
// your app namespace
var app = app || {};
// on document ready wrapper
$(function () {
$('#lobSelect').change(function () {
// initialize your variable at app namespace
app.selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
});
});
Your file2.js
// use the same app namespace or create it
// if not exist yet (in case when file2.js was loaded before file1.js)
var app = app || {};
$(function () {
// app.selectedLob is available here
});
var selectedLob is local to $('#lobSelect').change(function () { function not accessible outside
Solution
var selectedLob =''; //declare variable outside so it accessible
$('#lobSelect').change(function () {
//assign value here
selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
});
console.log(selectedLob);
//it doesn't get the value as it runs before the change event fires so you get undefined value
Read What is the scope of variables in JavaScript?
you can also set a global variable inside a function using the following method
window["variableName"] = "some value";
then access it anywhere. for example:
console.log(window["variableName"]);
You can use jQuery.data function to store in $('#lobSelect')
$('#lobSelect').data("yourKey", yourVariable)
And retrieve like this:
var someVariable = $('#lobSelect').data("yourKey")
Or declare the variable outside the function as suggested if you want to use it right after (data will store for a longer time):
var selectedLob;
$('#lobSelect').change(function () {
selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
});
console.log(selectedLob);
//accessible here,
//maybe not elsewhere in your code (depending on your code structure)
First problem you have here is the fact that you are using selectedLob variable outside of the scope it is defined in, so you have to move its declaration one level up so it can be used outside of the function as well (or even better you should restructure your code so this kind becomes unnecessary).
Second problem you have is you declare selectedLob variable inside change event handler and expect it to be defined immediately. To fix this (if you are using JQuery here) you can call your change handler function right after you declare it to initially kick start your variable initialization.
So in summary something like this:
var selectedLob =''; //declare variable outside change handler so it accessible
$('#lobSelect').change(function () {
//assign value here
selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
}).change(); // This will call your change event handler and hopefully init selectedLob
// Now selectedLob should be have value of selected option (if your DOM was ready...)
console.log(selectedLob);
And at the end I would have to say that you should really try to avoid things like this, try to restructure your JS code in a way that you maybe initialize all things you need in one place after DOM is ready and then to start up your app with some kind of init function passing all it needs or similar. Writing code like this will soon lead into one big pile of mess :)
Use global variable
var selectedLob; // use as a global variable to access outside of the function
$('#lobSelect').change(function () {
selectedLob = $('#mainWrapper').find('select[name="lob-select"] option:selected').val();
console.log(selectedLob); //prints to the console
});
if(selectedLob!=undefined){
console.log(selectedLob); //available here
}

How can I "save" variables client side so I can use it during some other java script event?

This is a .html page.
Kendo Auto Complete has a SELECT functionality:
select: function(e)
{
valid = true;
if (e.item == null)
{
return;
}
var DataItem = this.dataItem(e.item.index());
nameId = DataItem.NameId;
personId = DataItem.PersonId;
}
Basically what the above does is captures some variable values for me.
This is working fine.
The issue is, I want to use the variables nameId and personId in some other function and event later.
What would be the correct way to "save" these variables?
These variables will be used as parameters on a POST request later.
Store locally on client side:
localStorage.setItem("nameId",nameId);
localStorage.setItem("personId",personId);
Retrieve their values:
nameId=localStorage.getItem("nameId");
personId=localStorage.getItem("personId");
you can use global variables (although this method should only be done as a last resort)
otherwise, javascript is going to assume the scope of your variables to last only the length of the function. If you want the scope to extend beyond the function, then declare them outside the function like so:
var date_item = null
function doSomething(){
date_item = b
}
function doSomethingElse(){
alert(data_item)
}
to use a global variable, just dont use the prefix "var" in front of your variable declaration
var date_item = null // local
date_item = null // global

Access a javascript variable from a function inside a variable

Hello i have the following issue i am not quite sure how to search for it:
function(){
var sites;
var controller = {
list: function(){
sites = "some value";
}
}
}
So the question is how to access the sites variable from the top defined as
var sites
EDIT:
Here is a more complete part. i am Using marionette.js. i don't want to define the variable attached to the Module (code below) variable but keep it private to the Module, hope that makes sense. Here is the code that works:
Admin.module("Site", function(Module, App, Backbone, Marionette, $, _ ) {
Module.sites = null;
Module.Controller = {
list: function (id) {
Module.sites = App.request("site:entities");
}
};
});
and i would like instead of
Module.sites=null;
to do
var sites;
That sort of thing does make a difference right? Because in the first case i would be defining an accessible variable from outside where as the second case it would be a private one. i am a bit new to javascript so please try to make it simple.
if you are looking for global access, just declare the variable outside the function first, make your changes to the variable inside the function, then you can get the value whenever you need it.
I have found some info on this: sadly what i am trying to do doesn't seem possible.
Can I access a private variable of a Marionette module in a second definition of that module?
So i guess i have to do _variable to make developers know its private.
Disclaimer: I have no experience using Marionette, however, what you're describing sounds very doable.
One of the most powerful (in my opinion) features of JavaScript is closures. What this means is that any function declared from within another function has access to the variables declared in the outer function.
For example:
var func;
function foo() {
var answer = 42;
func = function () {
// I have access to variable answer from in here.
return answer++;
};
}
// By calling foo(), I will assign the function func that has access "answer"
foo();
// Now I can call the func() function and it has access to the "answer"
// variable even though it was in a scope that doesn't exist anymore.
// Outputs:
// 42
// 43
console.log(func());
console.log(func());
What this means is that if you declare var sites from within your module definition function as you described, you should have access to it from within any of your inner anonymous functions. The only exception is if Marionette is re-writing your functions (by using the Function function and toString()), which seems unlikely but possible.
Your original example should would as described, my suspicion is that there is something else going wrong with the code that is unrelated to your scope.

JS λ-functions & "upper context" variables

Say I have some context where variables are set and a λ-function is called which uses them directly:
function outerContext(){
...
var data = ...; // some data the script uses
...
someObject.method = function(){
data; // the variable is used here
};
...
}
I know that the dynamically created function has a snapshot of the context it was created in, so data variable is accessible there.
What are the dangers I may face with such an approach when I use this dynamically created method? Should I always give this data as an argument or is it ok?
The inner function does not have access to a "snapshot", it has full access to the data variable.
function outer() {
var data = 1;
...
someObject.method = function () {
data = 42;
};
someObject.method();
// data == 42
}
(The real explanation being that when using data in the inner function, Javascript will try to figure out which scope data is in. It will traverse up the scope chain to find the place where the variable was created, and that's the variable that will be used.)
There's no "danger", this is one of the core competencies of Javascript. It's like an object method modifying an object's properties. Of course you need to take care what you want to do, do you really want to modify the variable or do you just want to use it locally?
For the "snapshot", you need to use a closure:
function outer() {
var data = 1;
...
someObject.method = (function (data) {
return function () {
data = 42;
}
})(data);
someObject.method();
// data == 1
}
I can't really think of any "dangers" besides the possibility of causing a circular reference and thus a memory leak in case of DOM objects or such.
It works much like a private variable in a class.

Categories

Resources