Tuesday, March 30, 2010

Modify argument value before calling sc_super()

I have overridden a function "testFn" in a subclass which does something extra and then calls the parent class function. But I want to change one of the argument values before calling the parent class function. The standard javascript approach would be something like this:


testFn: function(arg1, arg2) {
  // ... do something
  var myarg2 = "new arg value";
  // use the following instead of sc_super() to that you can pass custom arguments
  arguments.callee.base.call(this, arg1, myarg2);
}


But javascript also supports some special handling of the "arguments" object, that gives us a cleaner implementation as below:


testFn: function(arg1, arg2) {
  // ... do something
  arg2 = "new arg value";

  sc_super();
}


To understand what's going on, you first need to understand that when doing "sc-build", all occurrences of the "sc_super()" is replaced with the following line (verbatim):


arguments.callee.base.apply(this, arguments);


So, the "arguments" object (provided by javascript) is passed to the parent function (stored by sproutcore in arguments.callee.base) asis.

In our second code snippet, although we just reassign the value of "arg2", the same value change automatically reflects in the "arguments" object (as if arg2 is a reference variable to the corresponding value in the "arguments" object). So any functions called from here one to which we pass the "arguments" object will have the new value of arg2.

But, the "arguments" object in the function which originally called "testFn" does not get this changed value. So, this also means that when you call a function, a copy of the "arguments" is passed instead of the original "arguments" object.

To try this out in any browser, paste the following snippet in the javascript console of any browser:


fnsub = function(x,y) {
  console.log("sub says: " + x + ", " + y);
};

fn = function(x, y) {
  console.log(arguments[0] + ", " + arguments[1]);
  y = "universe";
  fnsub.apply(this, arguments);
  console.log(arguments[0] + ", " + arguments[1]);
};

fn("hi", "world");


You will see an output similar to:


hi, world
sub says: hi, universe
hi, universe

So, although you changed the value of "y", it internally changed the value of "arguments[1]"

2 comments:

  1. Cool blog! You should link to it here https://wiki.sproutcore.com/External-Blogs

    ReplyDelete
  2. Thanks. I did not know about this page. Linked my blog there now.

    ReplyDelete