All the JavaScript you write in the JSFiddle “JavaScript” box gets wrapped in an anonymous function and assigned to the window.onload event of an iframe that is shown when you click the “Run” button.
Last week I published this post: Problems Making JSONP Calls in JSFiddle
As I was testing out some code, I noticed that JSONP calls were failing when using JsFiddle.net. I took a look at it and just found the answer. It wasn’t too big a deal, just needed to understand how JsFiddle executes the JavaScript code that you put in the lower-left-hand box (i.e. the “JavaScript” box).
Here is the code I testing, that was failing:
1 2 3 4 5 6 7 8 9 |
var myCallback = function(data){ console.dir(data); }, script = document.createElement('script'); script.src = 'http://examples.kevinchisholm.com/utils/json/jsonp.php?callback=myCallback'; document.getElementsByTagName('head')[0].appendChild(script); |
In this code, I use the “var” keyword to declare “myCallback” as a function expression, just like I was told in JavaScript summer camp back in the 70s. But even when using the “var” keyword, any variable declared in the global scope becomes a property of the window object. Anyhooo, I confidently assumed that my variable “myCallback” (or window.myCallback) would be available to the script that is loaded by the JSONP call. But that code failed and the following message appeared in the console: “myCallback is not defined”. Bummer.
Well, after a few minutes poking around in Google Chrome Web Inspector, I found the issue:
As I had suspected, JsFiddle executes your JavaScript code in an iframe. What I did not realize at first, is that it wraps all of that code in an anonymous function, that is assigned to the window.onload event. So by using the “var” keyword, my “myCallback” variable became private to the anonymous function. Here is the code that is actually executed by JsFiddle when I clicked “run”:
1 2 3 4 5 6 7 8 9 10 11 |
window.onload=function(){ var myCallback = function(data){ console.dir(data); }, script = document.createElement('script'); script.src = 'http://examples.kevinchisholm.com/utils/json/jsonp.php?callback=myCallback'; document.getElementsByTagName('head')[0].appendChild(script); } |
As a result, my “myCallback” variable (i.e. the function expression) is private, and not available to the outside world.
The answer was simple. I just had to force my “myCallback” variable to be global by removing the “var” keyword:
1 2 3 |
myCallback = function(data){ console.dir(data); } |
This forces “myCallback” to be an implied global, which in-fact becomes a property of the window object. It’s the exact same thing as if I had written: “window.myCallback – function()….”
Here is the JsFiddle.net link for the code that fails: http://jsfiddle.net/DQHax/
Here is the JsFiddle.net link for the fixed code: http://jsfiddle.net/DQHax/1/
Same thing, only let’s avoid implied globals, and explicitly attach “myCallback” to the window object: http://jsfiddle.net/DQHax/2/
Again, no big deal. But if you found yourself pulling your hair out and were googling for an answer, hopefully I saved you a few strands of hair.
: – )
Kevin