Search code examples
javascriptbackbone.jsarguments

Adding value to the arguments object


I'm having problems with adding values to the arguments objekt in a JavaScript method.

I'm trying to add an additional success callback to the Backbone.Model.fetch() method, my model looks like this:

models.Settings = Backbone.Model.extend({
    url: "path/to/settings.json",

    dataLoaded: function() {
        this.set({
            data: new collections.Data( this.get("data") )
        });
    },

    fetch: function() {
        var
            cb;

        if(!arguments.length) arguments[0] = {};

        if(arguments[0].hasOwnProperty('success')) {
            cb = arguments[0].success;
        }

        arguments[0].success = function() {
            this.dataLoaded();
            if(typeof cb === 'function') cb.apply(undefined, arguments);
        }.bind(this);

        models.Settings.__super__.fetch.apply(this, arguments);
    }
});

The code works well as long as a value (any value) is passed to fetch(). The problem occurs when the arguments object is initially empty. I'm able to set arguments[0] and the success value, as I'm supposed to. But the callback is never run.

What am I missing?


Solution

  • The arguments property is an object, not an array, which means that when you set arguments[0] = {};, it then looks like (http://jsfiddle.net/nikoshr/n93wfm8a/)

    {
        0: {}
    }
    

    However, models.Settings.__super__.fetch.apply expects an array (or at least a length property matching the content) and does not get it.

    Solutions

    1. Most hackish, set a length property :

      if(!arguments.length) {
          arguments[0] = {};
          arguments.length = 1;
      }
      

      http://jsfiddle.net/nikoshr/n93wfm8a/1/

    2. Slightly better, initialize arguments with an array

      if(!arguments.length) {
          arguments = [{}];
      }
      

      http://jsfiddle.net/nikoshr/n93wfm8a/2/

    3. Rewrite the whole thing to take advantage of the method's signature model.fetch([options]) and use Function.prototype.call

      fetch: function(opts) {
          var cb;
          opts = opts || {};
      
          if (opts.hasOwnProperty('success')) {
              cb = opts.success;
          }
      
          opts.success = function() {
              this.dataLoaded();
              if(typeof cb === 'function') cb.apply(this, arguments);
          }.bind(this);
      
          Settings.__super__.fetch.call(this, opts);
      }
      

      http://jsfiddle.net/nikoshr/n93wfm8a/4/