1

I add this snippet to each javascript file used in my asp.net web api application to avoid multiple load :

Fullcalendar.js

blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;

blog.isFirstLoad = function (namesp, jsFile) {
    var isFirst = namesp.jsFile.firstLoad === undefined;
    namesp.jsFile.firstLoad = false;
    return isFirst;
};

$(document).ready(function () {
    if (!blog.isFirstLoad(blog.comments, "fullcalendar.js")) {
        return;
    }
});

Sometimes I get a weird exception

Uncaught TypeError: Cannot read property 'firstLoad' of undefined

I need to know :

  1. Why this happens?
  2. How can I fix it?

2 Answers 2

1

A couple of problems there.

First, you shouldn't be loading the file more than once in the first place, so it shouldn't be necessary to go through this business of trying to figure out whether you've loaded it.

But if you want to do that:

The first practical issue is that you're always doing this:

blog = {};

...which means if there's already a blog global, you're wiping out its value and replacing it with an empty object. If you want to use an existing global's value or create a new one, do this:

var blog = blog || {};

That seems odd, but since repeated var declarations are fine (and don't change the variable), that will use an existing one's value, or if there isn't one (or its value is falsey) it will create a new one and initialize it with {}.

Then, the line

namesp.jsFile.firstLoad = false;

...looks for a property called jsFile on namesp and assumes it's not null or undefined. It doesn't look for a property using the jsFile argument's value.

To do that, use brackets notation:

namesp[jsFile].firstLoad = false;

Even then, though, you're assuming it's not null or undefined, but it may well be. You probably just wanted:

namesp[jsFile] = false;

Or possibly:

namesp[jsFile] = namesp[jsFile] ||{};
namesp[jsFile].firstLoad = false;

That said, it seems really odd to use blog.comments to track whether JavaScript files have been loaded. If the file may have already been loaded, just this will do it:

var fullCalendarLoaded;
if (fullCalendarLoaded) {
    // It's already loaded
} else {
    // It isn't, but it is now
    fullCalendarLoaded = true;
    // ...do your init...
}

Or if you have several of these and want to use a single global for it:

var loadedScripts = loadedScripts || {};
if (loadedScripts.fullCalendar) {
    // Already loaded
} else {
    // Not loaded yet
    loadedScripts.fullCalendar = true;
    // ...do init...
}

Or if using the filename is important:

var loadedScripts = loadedScripts || {};
function firstLoad(filename) {
    if (loadedScripts[filename[) {
        return false;
    }
    // Not loaded yet, remember we've loaded it now
    loadedScripts[filename] = true;
    return true;
}

Then:

if (firstLoad("fullcalendar.js")) {
    // First load, do init...
}
Sign up to request clarification or add additional context in comments.

Comments

1

It's fairly straightforward:

On your initial run, you define

blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;

In theory, this means that on some loads, blog is:

var blog = {
  comments: {
    debugMode: false
  }
}

You then pass blog.comments into your function isFirstLoad as the namesp parameter. In that function, you do the evaluation:

namesp.jsFile.firstLoad === undefined;

Well, you never defined the jsFile property of blog.comments. This means it is undefined. Trying to access the property firstLoad of an undefined variable will give you your error

Uncaught TypeError: Cannot read property 'firstLoad' of undefined

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.