I’m using a script that use jsonP to share cross domain information.
It works well, but I need to put it inside an IIFE.
var domain = "http://example.com/";
var myObj = {
recupData : function(data){
if (data.id) {
console.log(data.id);
}
},
scriptTag : function() {
var siteOrigin = domain+"check?q=myObj.recupData",
script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = siteOrigin;
document.getElementsByTagName('HEAD')[0].appendChild(script);
}
}
myObj.scriptTag();
That works! (I just took a very little part of my global script, just to show you the structure, so if there is any syntax error there, that’s not the point).
But when I put this code in an IIFE, a self invoked function, I get some trouble.
(function(){
var domain = "http://example.com/";
var myObj = {
recupData : function(data){
if (data.id) {
console.log(data.id);
}
},
scriptTag : function() {
var siteOrigin = domain+"check?q=myObj.recupData",
script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = siteOrigin;
document.getElementsByTagName('HEAD')[0].appendChild(script);
}
}
myObj.scriptTag();
})();
I get the error myObj is not defined, the error comes from the scriptTag method and I really don’t understand why I can’t access to this method until I have added an IIFE, it shouldn’t change anything, It just avoids to pollute the global namespace.
I think it’s just a context problem, but I need an explanation.
The motivation for using IIFEs is that your variable names don’t “leak” into the global scope. However, when you’re using JSONP, you are obligated to expose at least one variable to the global scope so the loaded script can call it (or one of its methods). This loaded script is inserted as a separate
scripttag into thehead, in a completely different scope and thus you can only share variables with it through the global scope.For example, imagine that your call to
http://mydomain.com/check?q=myObj.recupDataproduces a response like:This is being loaded inside a separate script tag, as if you’d written:
Clearly, if this call ought to work,
myObjneeds to be in the global scope so you should move its declaration outside of the IIFE, or explicitly register it on thewindowobject:The second option may be more interesting since it will always end up in the global scope, no matter where you place the snippet. If for some reason you end up nesting the first snippet inside another IIFE, you’d need to remember to move the
myObjdeclaration as well, which can be cumbersome.