MStodd MStodd - 1 year ago 42
Javascript Question

Why must I access a global variable through window?

I have some JS in a file, and some JS on a page.

If I try to access my function via NucleusPreview, it can't be found

If I access it via window.NucleusPreview, it is found

Why is that? Am I doing something wrong, or do I need to be explicit when accessing objects in window scope when in another function?

Update: I was creating NucleusPreview inside the onReady, but moved it so I think the window scope was a red herring. The problem is that when calling it in onReady, gave it time to load the file, but when I moved it out I started calling it too early.

The JS in the the file is basically:

var NucleusPreview;

(function ($) {
NucleusPreview = function NucleusPreview(source) {
//ctor stuff
};

NucleusPreview.prototype.AdjustCaption = function AddCaption() {
//caption stuff
};
})(jQuery);


My JS on the page:

$('.nucleus-preview').each(function eachNucleusPreview(index, element) {
var jElement = $(element),
vidId = jElement.data('video-id'),
np = new NucleusPreview($(element)); //Uncaught RefError: NucleusPreview is not defined

_wq.push({
id: vidId,
onReady: function (video) {
np.AdjustCaption();
}
});
});

Answer Source

As long as the first bit of code you provided is executed first and none of the code is executed prior to the DOM being loaded (you can put all of this code in a document.ready() callback to ensure that is the case), you should be able to. Run this code snippet and wait a moment, you will see that it works without qualifying window.

In the example below, I've placed all the code in a document.ready() callback (although that is not required for the code to run) to ensure that you don't try to access $('.nucleus-preview') before the DOM is ready.

Additionally, doing this will keep NucleusPreview out of the global scope in the first place, which is always a good idea.

// Always make sure the DOM is fully loaded prior to scanning for DOM elements. 
// This can be done by placing all of your code in a "document.ready()` callback
// function as I'm doing here or by placing the code at the end of the HTML document,
// just before the close of the body (</body>).
$(function(){

  // Now NucleusPreview is scoped to this function, which keeps it out of the
  // global scope and that's always good, so you don't pollute the window.
  var NucleusPreview;

  (function ($) {
    NucleusPreview = function NucleusPreview(source) {
        //ctor stuff
    };

    NucleusPreview.prototype.AdjustCaption = function AddCaption() {
        //caption stuff
    };
  })(jQuery);


  var _wq = [];  // Added to allow code to execute

  $('.nucleus-preview').each(function eachNucleusPreview(index, element) {
    var jElement = $(element),
        vidId = jElement.data('video-id'),
        np = new NucleusPreview($(element)); // <-- Works just fine!

    _wq.push({
        id: vidId,
        onReady: function (video) {
            np.AdjustCaption();
        }
    });
  });
});

console.log($('.nucleus-preview'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nucleus-preview"></div>
<div class="nucleus-preview"></div>
<div class="nucleus-preview"></div>

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download