Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery / JavaScript Function Scope / Hoisting

I have two files containing JavaScript and jQuery functions. They are referenced on the page in this order:

<script src="js/kiosk-functions.js"></script>
<script src="js/kiosk-main-socket-handler.js"></script>

In kiosk-functions.js I had originally done this -

$(function() {
    // some JavaScript functions
    function isJSON(str) {
        try {
            JSON.parse(str);
            return true;
        } catch (e) {
            return false;
        }
     }
     // some jQuery code follows...
});

Then, in kiosk-main.js I had this -

$(function() {
    var socket = io();
    socket.on('message', function (data) {

        if(isJSON(data)) {
            // do stuff
        }
    });
    // other JavaScript and jQuery code
});

This resulted in the following error -

Uncaught ReferenceError: isJSON is not defined

Once I moved the isJSON() function out of the document ready handler in kiosk-functions.js then all was well, but left me puzzled. I read a number of the answers here on SO trying to understand what was going on, being under the impression that the function would be hoisted and available globally. I didn't find anything that demonstrated this example.

I'm sure that I am missing something simple here. Does the document ready handler (a function) keep the isJSON() function from being hoisted? Or is it a simple scope issue?

like image 270
Jay Blanchard Avatar asked Jul 05 '26 14:07

Jay Blanchard


1 Answers

Your problem is not hoisting, but the scope of the function.

Basically in kiosk-functions.js you define a callback to document.ready and inside that callback you define the function isJSON(). The function is just known within that scope.

In the second file kiosk-main.js you try to use isJSON() as if it was defined either in that callback's scope or in the global scope. Both is not the case, hence the error.

In order to solve this, you could add some global namespace myNamespace and attach your function there:

$(function() {
    // some JavaScript functions
    function isJSON(str) {
        try {
            JSON.parse(str);
            return true;
        } catch (e) {
            return false;
        }
     }

  // init namespace
  window.myNamespace = window.myNamespace || {};

  // attach function
  window.myNamespace.isJSON = isJSON;
});

Then in the other file you can reference that global namespace to call your function:

$(function() {
    var socket = io();
    socket.on('message', function (data) {

        if(myNamespace.isJSON(data)) {
            // do stuff
        }
    });
    // other JavaScript and jQuery code
});

Edit

As mentioned by @Alnitak in the comments: In the browser the global object is window. Changed code accordingly.

like image 103
Sirko Avatar answered Jul 08 '26 04:07

Sirko