1

I've been trying to refine an answer for a question here on SO but I've come across a wierd issue and I am hoping someone could help me understand the cause. What I am attempting to do is disable the use of AJAX operations from within a "protected" function by overriding them with locally-scoped variables. This needs to work with libraries such as jQuery, so I tried implementing logic to recreate the $ variable but for some reason I can't override the global scope with a local version like I can with the others, and meanwhile is producing some very unexpected (and interesting) behaviour.

This is the code that I'm using:

var testFunction = (function(){
    // Global to local/lexical:
    var XMLHttpRequest = undefined;
    var eval = undefined;
    var setTimeout = undefined;
    var setInterval = undefined;
    var Function = undefined;
    var window = undefined;
    // Can't set directly to var $?
    var $new = (function($old){ if($old) {
        var newjq = function(s, c) {
            // Reroute main function
            return $old(s, c);
            };
        var jQueryBlacklist = {
            // Initialize blacklist
            "ajax": true,
            "post": true,
            "get": true,
            "getJSON": true,
            "getScript": true
            };
        for(i in $old) // Reconstruct Object
         if($old.hasOwnProperty(i)
         && !jQueryBlacklist[i])
          newjq[i] = $old[i];
        return newjq;
        } }($));
    // Line below completely breaks script?:
    var $ = $new;
    if(!$new) alert("$new is undefined");
    // Real testFunction() below:
    return function() {
        // AJAX-forbidden code
        if(!$) alert("$ is undefined");
        else alert("jQuery is working");
        // alert($.ajax);
        // $.ajax should be undefined
        }
    }());
testFunction();
// alert($.ajax);
// should be defined

You can click here to see the fiddle.

I'm simply interested in any feedback about this, as to me it seems like a bug. I would love to know the reason(s) for this behaviour. Thanks in advance!

1 Answer 1

2

Your var $ is being hoisted (the declaration is moved to the top of function), shadowing the global $ to be undefined (when it gets passed into the self executing function) until its actual assignment in var $ = new$.

The easiest solution is to pass jquery into your module.

var testFunction = (function ($) {
    // Global to local/lexical:
    var XMLHttpRequest = undefined;
    var eval = undefined;
    var setTimeout = undefined;
    var setInterval = undefined;
    var Function = undefined;
    var window = undefined;
    // Can't set directly to var $?
    var $new = (function ($old) {
        if ($old) {
            var newjq = function (s, c) {
                // Reroute main function
                return $old(s, c);
            };
            var jQueryBlacklist = {
                // Initialize blacklist
                "ajax": true,
                    "post": true,
                    "get": true,
                    "getJSON": true,
                    "getScript": true
            };
            for (i in $old) // Reconstruct Object
            if ($old.hasOwnProperty(i) && !jQueryBlacklist[i]) newjq[i] = $old[i];
            return newjq;
        }
    }($));
    // Line below only affects the object reference passed in to this module
    // Doesn't affect jQuery outside of this function:
    $ = $new;
    if (!$new) alert("$new is undefined");
    // Real testFunction() below:
    return function () {
        // AJAX-forbidden code
        if (!$) alert("$ is undefined");
        else alert("jQuery is working");
        // alert($.ajax);
        // $.ajax should be undefined
    }
}(jQuery));
testFunction();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Sign up to request clarification or add additional context in comments.

4 Comments

The whole point of that part of the script is to override $ within the local scope, so renaming will not solve the problem. What causes $ to be hoisted to the top? Is there any way I can prevent that from happening?
Also, I can't omit the "var" declaration as that would overwrite the global variable. I just want to override it. Is there another solution you could think of maybe? I'm all out of ideas at the moment. Lol
@JonathanGray Hoisting is just how JavaScript works. You can pass a reference to jQuery into your function. See the updated answer
Ahh, I completely forgot about passing the variable as a parameter as an alternative to "var" declarations. Very nice workaround :)

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.