Reputation: 2609
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!
Upvotes: 1
Views: 106
Reputation: 92274
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>
Upvotes: 2