title: Safely defining variables for public callback functions in javascript
body: <p>I am working with the YouTube iFrame API to embed a number of videos on a page. Documentation here: <a href="https://developers.google.com/youtube/iframe_api_reference#Requirements" rel="nofollow">https://developers.google.com/youtube/iframe_api_reference#Requirements</a></p>
  
  <p>In summary, you load the API asynchronously using the following snippet:</p>
  
  <pre><code> var tag = document.createElement('script');
   tag.src = "http://www.youtube.com/player_api";
   var firstScriptTag = document.getElementsByTagName('script')[0];
   firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  </code></pre>
  
  <p>Once loaded, the API fires the predefined callback function <code>onYouTubePlayerAPIReady</code>.</p>
  
  <p>For additional context: I am defining a library file for this in Google Closure. I am providing a namespace: <code>goog.provide('yt.video');</code></p>
  
  <p>I then use <code>goog.exportSymbol</code> so that the API can find the function. That all works fine.</p>
  
  <p>My challenge is that I would like to pass 2 variables to the callback function. Is there any way to do this without defining these 2 variables in the context of the <code>window</code> object?</p>
  
  <pre><code>goog.provide('yt.video');
  
  goog.require('goog.dom');
  
  yt.video = function(videos, locales) {
    this.videos = videos;
    this.captionLocales = locales;
  
    this.init();
  };
  
  yt.video.prototype.init = function() {
    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/player_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  };
  
  /*
   * Callback function fired when YT API is ready
   * This is exported using goog.exportSymbol in another file and
   * is being fired by the API properly.
   */
   yt.video.prototype.onPlayerReady = function(videos, locales) {
      window.console.log('this :' + this); //logs window
      window.console.log('this.videos : ' + this.videos); //logs undefined
      /*
       * Video settings from Django variable
       */
      for(i=0; i&lt;this.videos.length; i++) {
        var playerEvents = {};
        var embedVars = {};
  
        var el = this.videos[i].el;
        var playerVid = this.videos[i].vid;
        var playerWidth = this.videos[i].width;
        var playerHeight = this.videos[i].height;
        var captionLocales = this.videos[i].locales;
        if(this.videos[i].playerVars)
          var embedVars = this.videos[i].playerVars;
        }
        if(this.videos[i].events) {
          var playerEvents = this.videos[i].events;
        }
  
        /*
         * Show captions by default
         */
        if(goog.array.indexOf(captionLocales, 'es') &gt;= 0) {
          embedVars.cc_load_policy = 1;
        };
  
        new YT.Player(el, {
          height: playerHeight,
          width: playerWidth,
          videoId: playerVid,
          events: playerEvents,
          playerVars: embedVars
      });
   };
  </code></pre>
  
  <p>};</p>
  
  <p>To intialize this, I am currently using the following within a self-executing anonymous function:</p>
  
  <pre><code>  var videos = [
      {"vid": "video_id", "el": "player-1", "width": 640, "height": 390, "locales": ["es", "fr"], "events": {"onStateChange": stateChanged}}, 
      {"vid": "video_id", "el": "player-2", "locales": ["es", "fr"], "width": 640, "height": 390}
    ];
  
    var locales = ['es'];
  
    var videoTemplate = new yt.video(videos, locales);
  </code></pre>