How to init a global variable if it is not present? - javascript

I load the same script in my page many times. I have some trouble on decide which is loaded first/after in my website, due to the async/load functions.
So, I'd like to put a global variable that count, when the script is loaded, the order of them.
So myScript.js will start with :
(function () {
var privateNumberScriptLoaded;
if (numberScriptLoaded === undefined) {
numberScriptLoaded = 0;
}
else {
numberScriptLoaded = numberScriptLoaded + 1;
}
privateNumberScriptLoaded = numberScriptLoaded;
console.log(privateNumberScriptLoaded);
})();
but when I load it with :
<script src="http://www.mywebsite.com/widget/myScript.js?type=normal" type="text/javascript"></script>
<script src="http://www.mywebsite.com/widget/myScript.js?type=rotation" type="text/javascript"></script>
I get (for two times) numberScriptLoaded is not defined.
How can I resolve this trouble? In fact I'll "create" a global variable in my website if it doesnt exist. Than increment it and store in a "private" variable for each script, so I can save the order of the execution for each script.

At present, your script falls prey to The Horror of Implicit Globals. I'd recommend not doing that.
You have three options:
As all global variables end up as properties on window, you could use window explicitly:
if (!window.numberScriptLoaded) {
window.numberScriptLoaded = 1; // 1, not 0
}
else {
++window.numberScriptLoaded;
}
Unlike the code without the window. prefix, that won't throw a ReferenceError, because looking up a property on an object works differently from resolving a freestanding identifier.
Live demo | demo page source | source of script it loads
Always put var numberScriptLoaded; (with no initializer) at global scope in your script, e.g. outside your scoping function:
var numberScriptLoaded; // No initializer (no = 0 or anything)
On the first load, this will create the variable; on subsequent loads, it's a no-op. Then you can do this without a ReferenceError:
if (!numberScriptLoaded) {
numberScriptLoaded = 1; // 1, not 0
}
else {
++numberScriptLoaded;
}
Live demo | demo page source | source of script it loads
Use typeof. If you take the typeof a variable that doesn't exist, you don't get a ReferenceError; you get "undefined". Then you can create it via the window. prefix (so you're not falling prey to The Horror).
if (typeof numberScriptLoaded === "undefined") {
// Assigning to window.numberScriptLoaded creates the global
window.numberScriptLoaded = 1; // 1, not 0
}
else {
++numberScriptLoaded;
}
Live demo | demo page source | source of script it loads

You should use typeof
if (typeof numberScriptLoaded === 'undefined') {

Try
if ( 'undefined' === typeof numberScriptLoaded ) {
numberScriptLoaded = 0;
} else {
numberScriptLoaded = numberScriptLoaded + 1;
}

myGlobalVar = typeof myGlobalVar == "undefined"? "New Value" : myGlobalVar;
myGlobalVar = typeof myGlobalVar == "undefined"? "Totally New Value" : myGlobalVar;
alert(myGlobalVar);
http://jsfiddle.net/8gnuwaah/2/

Global variables are direct attributes of window object. So if you'd like to init global variable from anywhere just type:
window.variableName = "what_ever_you_want"

As a best practice and to prevent this type of errors, all variables should be initialized before being used in your script.
You should put:
var numberScriptLoaded;
Just before your closure and the error won't happen.

If you're going to use the window to store the global, then you can do it in a single line with:
window.numberScriptLoaded = (window.numberScriptLoaded || 0) + 1

Related

var = true won't pass to another function

I've got a contact field on my website, and tests whether the value inserted is good or not. That part works fine. If a value is right, there is a var made with value = true.
I'm also calling a second function, which tests if all the contacts fields have got a true. If so, the send button will be abled, otherwise it keeps disabled. Sadly enough I get an error in my console, which says: Uncaught ReferenceError: nameIsGoed is not defined.
Hope you can help me out! :)
One of the tree functions which are quietly the same
function checkEmptyMessage(field) {
if (field.value != '') {
document.getElementById("message").style.borderColor="#91bc1e";
var messageIsGoed = true;
}
else if (field.value == ''){
document.getElementById("message").style.borderColor="#f15a24";
var messageIsGoed = false;
}}
The function that checks whether the value is true or not, if so: disable get's false.
function checkDisable(){
if ((nameIsGoed == true) && (messageIsGoed == true) && (mailIsGoed == true)){
document.getElementById("submit").disabled=false;
alert("mooizo");
}
else{
alert("er missen nog gegevens");
}
}
You have a scope problem, var messageIsGoed; should be (declared) outside your function, so the value you give it is available to other functions.
var messageIsGoed; // outside the function
function checkEmptyMessage(field) {
if (field.value != '') {
document.getElementById("message").style.borderColor="#91bc1e";
messageIsGoed = true;
}
else if (field.value == ''){
document.getElementById("message").style.borderColor="#f15a24";
messageIsGoed = false;
}}
I added (declared) var messageIsGoed; outside the function and removed the var inside the function so you don't declare it again (which actually makes a new variable only available inside that function).
Read more here about declaring variables: MDN:var
You cant use messageIsGoed outside of function if you declared it using var.
Just declare it outside both functions and use it inside without var so it will be global.
That's a local variable.
It only exists inside the function it's declared in.
You want to make a global variable, which will exist everywhere.
Declare the variable outside the function.

Initializing localStorage variables with Javascript doesn't work when in a function

Okay, so I'm using the following if statements to preset certain variables of an application I'm making:
if(localStorage.s1 == undefined) {
localStorage.s1= 50
}
if(localStorage.s2 == undefined) {
localStorage.s2= 100
}
And that works fine. There's about twelve of these presets, so I've re-factored it by using the following function:
function setterfunc(targetedelement, presetting) {
if(localStorage.targetedelement == undefined) {
localStorage.targetedelement = presetting;
}
}
But when I call it with
setterfunc(foobar, 342)
Google Chrome console just tells me:
Uncaught ReferenceError: foobar is not defined
Any help? The verbose way around of repeating the if statements works perfectly.
Use the bracket notation :
function setterfunc(targetedelement, presetting) {
if(localStorage[targetedelement] == undefined) {
localStorage[targetedelement] = presetting;
}
}
setterfunc('foobar', 342)
or the setItem and getItem accessors :
function setterfunc(targetedelement, presetting) {
if(localStorage.getItem(targetedelement) == undefined) {
localStorage.setItem(targetedelement) = presetting;
}
}
setterfunc('foobar', 342)
Side note : Be careful that localStorage only stores strings. So if you want to handle numbers, you'd better parse what you read from local storage.
The reason for the error is that the string foobar needs to be quoted, otherwise JS is looking for a variable of this name:
slidersetter('foobar', 342);
but your function is named setterfunc, not slidersetter.

Object not defined or null

I wrote a JavaScript file named global.js that has the following contents:
;
var Globals =
{
function getAppRoot() {
if (typeof (jQuery) !== "undefined")
return $("#ApplicationRoot").attr("href");
};
appRoot : getAppRoot();
};
Then in my HTML file (ASP.NET MVC project), I included my JavaScript file like so:
<link rel = "home" id = "ApplicationRoot"
href = "#Url.Content("~/")" />
<script src = "#Url.Content("~/Scripts/jquery-1.8.3.js")"
type="text/javascript"></script>
<script src = "#Url.Content("~/Scripts/global.js")"
type = "text/javascript"></script>
And then, in the HTML file, inside a SCRIPT tag, I write:
$(document).ready(
function() {
alert("Globals.appRoot = " + window.Globals.appRoot);
} );
However, when I run the code, it tells me that Globals is undefined.
UPDATE
Thank you, all. I just noticed that I'd forgotten the equal to sign (assignment operator) for one.
Another important thing that I observe now (which I wasn't fully sure of) is: I am assuming from your comments that an object declaration like so:
var foo = { /* cannot have anything that does not adhere to the bar : gar syntax? */ }
ANOTHER UPDATE
The thing is: if I made appRoot a method by doing so:
var Globals =
{
appRoot : function() { }
};
or like so:
var Globals =
{
appRoot : function getAppRoot() { }
}
The client would have to invoke appRoot with a set of following parenthesis. I would like for appRoot to be a property instead of a method. How do I do that?
FINAL UPDATE
I now have changed my code to read as follows:
// globals.js
// I understand that the starting semi-colon is not
// required. I'd left it in for reasons that it is used
var Globals =
{
appRoot : $("#ApplicationRoot").attr("href");
};
// inside the HTML file in $(document).ready();
if (tyepof(Globals) == "undefined" || Globals == null)
alert("Globals is either undefined or null");
else
alert("Globals.appRoot = " + Globals.appRoot);
I get the alert message Globals is either undefined or null.
ANSWER
Okay, finally. Thanks for all your help. I had another minor syntax error in the object declaration/initialization of the Globals object.
Since appRoot was a member of the object, and I was using the object initializer syntax, I should not have terminated the declaration of appRoot with a semi-colon. Instead, I should either have used a comma or just left it without any terminating character since it was the last (and the only member of Globals).
You need to re-write your globals.js, something like this should work:
var Globals = {
appRoot : function() {
if (typeof (jQuery) !== "undefined") {
return $("#ApplicationRoot").attr("href");
}
}
};
Your global.js should look more like this:
//; << not needed
var Globals = /*equal to missing*/
{
appRoot : function getAppRoot() {
if (typeof (jQuery) !== "undefined")
return $("#ApplicationRoot").attr("href");
}
};

How can I check whether a variable is defined in Node.js?

I am working on a program in node.js which is actually js.
I have a variable :
var query = azure.TableQuery...
looks this line of the code is not executing some times.
my question is :
How can I do a condition like:
if this variable is defined do this.
else do this.
I cannot do in js (query!= null)
I want to see if this variable is defined do some thing. how to do this
if ( typeof query !== 'undefined' && query )
{
//do stuff if query is defined and not null
}
else
{
}
Determine if property is existing (but is not a falsy value):
if (typeof query !== 'undefined' && query !== null){
doStuff();
}
Usually using
if (query){
doStuff();
}
is sufficient. Please note that:
if (!query){
doStuff();
}
doStuff() will execute even if query was an existing variable with falsy value (0, false, undefined or null)
Btw, there's a sexy coffeescript way of doing this:
if object?.property? then doStuff()
which compiles to:
if ((typeof object !== "undefined" && object !== null ? object.property : void 0) != null)
{
doStuff();
}
For me, an expression like
if (typeof query !== 'undefined' && query !== null){
// do stuff
}
is more complicated than I want for how often I want to use it. That is, testing if a variable is defined/null is something I do frequently. I want such a test to be simple. To resolve this, I first tried to define the above code as a function, but node just gives me a syntax error, telling me the parameter to the function call is undefined. Not useful! So, searching about and working on this bit, I found a solution. Not for everyone perhaps. My solution involves using Sweet.js to define a macro. Here's how I did it:
Here's the macro (filename: macro.sjs):
// I had to install sweet using:
// npm install --save-dev
// See: https://www.npmjs.com/package/sweetbuild
// Followed instructions from https://github.com/mozilla/sweet.js/wiki/node-loader
// Initially I just had "($x)" in the macro below. But this failed to match with
// expressions such as "self.x. Adding the :expr qualifier cures things. See
// http://jlongster.com/Writing-Your-First-Sweet.js-Macro
macro isDefined {
rule {
($x:expr)
} => {
(( typeof ($x) === 'undefined' || ($x) === null) ? false : true)
}
}
// Seems the macros have to be exported
// https://github.com/mozilla/sweet.js/wiki/modules
export isDefined;
Here's an example of usage of the macro (in example.sjs):
function Foobar() {
var self = this;
self.x = 10;
console.log(isDefined(y)); // false
console.log(isDefined(self.x)); // true
}
module.exports = Foobar;
And here's the main node file:
var sweet = require('sweet.js');
// load all exported macros in `macros.sjs`
sweet.loadMacro('./macro.sjs');
// example.sjs uses macros that have been defined and exported in `macros.sjs`
var Foobar = require('./example.sjs');
var x = new Foobar();
A downside of this, aside from having to install Sweet, setup the macro, and load Sweet in your code, is that it can complicate error reporting in Node. It adds a second layer of parsing. Haven't worked with this much yet, so shall see how it goes first hand. I like Sweet though and I miss macros so will try to stick with it!
If your variable is not declared nor defined:
if ( typeof query !== 'undefined' ) { ... }
If your variable is declared but undefined. (assuming the case here is that the variable might not be defined but it can be any other falsy value like false or "")
if ( query ) { ... }
If your variable is declared but can be undefined or null:
if ( query != null ) { ... } // undefined == null
For easy tasks I often simply do it like:
var undef;
// Fails on undefined variables
if (query !== undef) {
// variable is defined
} else {
// else do this
}
Or if you simply want to check for a nulled value too..
var undef;
// Fails on undefined variables
// And even fails on null values
if (query != undef) {
// variable is defined and not null
} else {
// else do this
}
It sounds like you're doing property checking on an object! If you want to check a property exists (but can be values such as null or 0 in addition to truthy values), the in operator can make for some nice syntax.
var foo = { bar: 1234, baz: null };
console.log("bar in foo:", "bar" in foo); // true
console.log("baz in foo:", "baz" in foo); // true
console.log("otherProp in foo:", "otherProp" in foo) // false
console.log("__proto__ in foo:", "__proto__" in foo) // true
As you can see, the __proto__ property is going to be thrown here. This is true for all inherited properties. For further reading, I'd recommend the MDN page:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in
You could use double exclamation mark !! to check if something is defined and not null.
!!null returns false.
!!undefined will also return false.
But if you define a variable for example const a = 1, then !!a will return true.
I have seen a lot of options here, but I would say, that in some cases the code will execute not the way expected, or throw an error. If you want a safe way, use try catch:
try {
I_dont_exist
} catch (err) {
console.log('Variable is not defined')
}

how to get the value from a callback function

I am relatively new to javascript and I am facing some difficulty.I have two java script files as I have shown below. I am having trouble getting the value of the variable entry_title inside the getRss function and storing it inside the variables Rss1_title and Rss2_title . Creating a global variable and assigning it to entry_title will make things worse as I will not be able to know from which Rss url the title came from. Is there a easy way to get the value of the callback functions ?
<script type="text/javascript" src="jsRss.js"></script>
<script type="text/javascript" src="notification.js"></script>
My notification.js file
function get_rss1_feeds(){
var Rss1_title = getRss("http://yofreesamples.com/category/free-coupons/feed/?type=rss");
}
function get_rss2_feeds(){
var Rss2_title = getRss("http://yofreesamples.com/category/real-freebies/feed/?type=rss");
}
setTimeout('get_rss1_feeds()',8000);
setTimeout('get_rss2_feeds()',7000);
My jsRss.js file:
function getRss(url){
if(url == null) return false;
google.load("feeds", "1");
// Our callback function, for when a feed is loaded.
function feedLoaded(result) {
if (!result.error) {
var entry = result.feed.entries[0];
var entry_title = entry.title; // need to get this value
}
}
function Load() {
// Create a feed instance that will grab feed.
var feed = new google.feeds.Feed(url);
// Calling load sends the request off. It requires a callback function.
feed.load(feedLoaded);
}
google.setOnLoadCallback(Load);
}
Errors :
When the setTimeout(get_rss1_feeds, 8000); method is called I get a blank screen.
I get a error in my console saying octal literals and octal escape sequences are deprecated and it is pointing to the 6th line in this script.
Is it because I am using google-api for parsing my Rss?
if (window['google'] != undefined && window['google']['loader'] != undefined) {
if (!window['google']['feeds']) {
window['google']['feeds'] = {};
google.feeds.Version = '1.0';
google.feeds.JSHash = '8992c0a2cdf258e5bd0f517c78243cd6';
google.feeds.LoadArgs = 'file\75feeds\46v\0751';
}
google.loader.writeLoadTag("css", google.loader.ServiceBase + "/api/feeds/1.0/8992c0a2cdf258e5bd0f517c78243cd6/default+en.css", false);
google.loader.writeLoadTag("script", google.loader.ServiceBase + "/api/feeds/1.0/8992c0a2cdf258e5bd0f517c78243cd6/default+en.I.js", false);
}
Seeing as it's a different scope, you can either return it in a callback, or provide it in another way such as exporting it to a higher scope that is visible to your desired location. In this case, it's the global scope, so I'd advise against that.
function getRss(url, callback) {
//...
function feedLoaded(result) {
if (!result.error) {
var entry = result.feed.entries[0];
var entry_title = entry.title; // need to get this value
callback && callback(entry_title);
}
}
and call it like so,
function get_rss1_feeds() {
var Rss1_title = getRss("http://yofreesamples.com/category/free-coupons/feed/?type=rss", function(entry_title) {
// This scope has access to entry_title
});
}
As an aside, use your setTimeout like so:
setTimeout(get_rss1_feeds, 8000);
rather than
setTimeout("get_rss1_feeds()", 8000);
as the latter uses eval, whereas the former passes a reference to the function.
Eventhough it will make your code a mess, you can append the variables to the window object.
For example:
function a()
{
window.testStr = "test";
}
function b()
{
alert(window.testStr);
}
Or even create your own object, instead of using window, as such:
var MyRSSReader = {
TitleOne : '',
TitleTwo : ''
}
MyRSSReader.TitleOne = "My title";
Wikipedia has a nice article about global variables, and why they are bad.

Categories