Declaring JavaScript Variables Efficiently - javascript

I'm trying to optimize a small web application's use of JavaScript variables. I have about five functions that each produce an Ajax call, and repeatedly make use of a query string. Should I declare the query variable inside of each function, or will it increase efficiency to declare it globally? A very simple example of what I'm talking about is:
Local Declaration
<script type="text/javascript">
function queryOne() {
var queryString = "query arguments";
}
function queryTwo() {
var queryString = "query arguments";
}
</script>
Global Declaration
<script type="text/javascript">
var queryString;
function queryOne() {
queryString = "query arguments";
}
function queryTwo() {
queryString = "query arguments";
}
</script>
Is there are notable efficiency benefit to using the global declaration scheme?

Should be declared locally, as any global declaration will take extra time to look for the variable in the local scope and then the global scope, making the global declaration actually slower. Plus a variable declaration might not require a search for the variable name, it can simply just attempt to create a new variable.
Also, if code were added in the future, declaring the variable globally could cause it to be overwritten by other code or conflict.
Actually you might save a little time with a module level variable, if the query string is only assigned to once. However, if you are reassigning the query variable each time the function is called, then you definitely save time making the query variable local to each function.

You could enclose it for neatness;
var MyApp = {
queryString: null,
queryOne: function() {
print( this.queryString );
},
queryTwo: function() {
print( this.queryString );
}
}
.
MyApp.queryString = "foo=boob";
.
a = MyApp.queryOne(123);
b = MyApp.queryTwo(456);

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

Use JavaScript global variable which is in a function outside function. Keeping in mind that function is assigned to a variable

How to use the global variable topic outside the function which is assigned to global variable tell.
<html>
<head>
<script>
alert(topic);
tell = function(){
topic = "something";
};
</script>
</head>
<body>
</body>
</html>
Eventually I want to use the value of topic_splitted anywhere outside the function.
client.onMessageArrived = function (message) {
topic_splitted = message.destinationName.split("/");
console.log("Topic Splitted: " + topic_splitted);
console.log("Message Topic: " + message.destinationName);
console.log("Message Arrived: " + message.payloadString);
if (message.destinationName == "in_progress"){
if (message.payloadString == "false") {
stepCode();
}
}
var new_data = JSON.parse(message.payloadString);
$.extend(true, data, data, new_data);
};
It is not a good idea to use undeclared variables, such as topic in the tell function of the first post example.
If you assign a value to an undeclared variable, JavaScript creates a global variable for you unless the code is running in strict mode. In strict mode it takes the safer approach of throwing an error that the variable has not been defined.
Where to declare common variables?
If the variable needs to be accessed by code executed at global level when the page loads, it needs to be declared at global level. This is not regarded as desirable and should be avoided if possible.
The alternative is to declare the variable inside a function which might be immediately invoked (an IIFE) or is executed in response to window load or document ready events.. Variables declared within such functions can be accessed by code within the outer function and all functions nested within it.
So if topic_splitted is defined outside all the functions which use it, preferable within a common outer function, there should be no problem.
It looks like you are not actually running the function "tell". Try this:
<html>
<head>
<script>
var topic;
var tell = function(){
topic = "something";
};
tell()
alert(topic);
</script>
</head>
<body>
</body>
</html>

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.

Javascript: append script with an object, and create a local instance

Let me expose my question:
I have a main script, let's say that it creates an instance of a "game" object, which, depending on the actions of the user, loads one of many javascript files, let's call them "levels" :D These files contains different objects, for example, "level1.js" which contains the object for level1, then "level2.js", etc.
Each time a level script is loaded, for example level1.js, the instance of "game" creates an instance of the object level1 and stores it in a local variable.
The only way I've found to do it, is to write, at the end of all the "level" scripts, a global variable, which has always the same name, and that points to the definition of the current level. Then in game, when any level script is loaded, I use this global variable to create the instance of the current level. I would like to know if there is a way to do it without using a global variable.
Here is a simplified example:
In game.js:
function Game() {
var levelCurrent = null;
var scriptCour = document.createElement("script");
scriptCur.type = "text/javascript";
scriptCur.onload = function() {
levelCurrent = new level();
}
}
And in each "level" script (level1.js, level2.js):
function level1() {
//definition of the level
//...
}
level = level1;
Or, similarly:
level = function() {
//definition of the level
//...
}
I don't know if I explained well enough my question, but if anyone has an answer... Thank you! Note that the instance of game is created using a self-executing function, and is therefore a local variable, like:
(function() {
var game = new Game();
})();
Thank you!
Instead of assigning the new level to a global variable, you should call a global function with the level information, e.g.
window.addLevel(function level1() {
//definition of the level
//...
});
Why is your Game instance a local variable, can't it be accessed? I guess it's a singleton (only one instance), so it would be perfectly valid to have it as a global variable. It then would be a good namespace for the addLevel function (window.game.addLevel()).
You could have the main game code expose a single global function, like "startNewLevel" or something, and then instead of declaring a global variable you'd just have the new level pass itself to that function.

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