As I was writing jPaq v2.0, one of the things I wanted in quite a few cases were functions in which the this object could be parameterized without using the theFunction.apply() function or the theFunction.call(). Here is an example of what is often done with native prototypal functions:


// Reference the generic Object's prototypal function:
var toString = Object.prototype.toString;

// Use the toString function on different things:
alert(toString.call(3.14159265));  // [object Number]
alert(toString.call(/regular_expression/g)); // [object RegExp]
alert(toString.call("a string")); // [object String]
alert(toString.call(toString)); // [object Function]

// Reference the Array's prototypal function.
var slice = Array.prototype.slice;

// Use the slice function on different things:
alert(slice.call([0,1,2,3], 2));  // 2,3
alert(slice.call("abcd", 1));  // b,c,d
alert(slice.call((function(){return arguments})(9,8,7), 0));  // 9,8,7

Even though, we now have a reference to the toString() and slice() functions, we’ll always need to use the call() function or apply() function to define this. Personally, I would much prefer something like this:


// Reference the generic Object's prototypal function:
var toString = ({}).toString.getCall();

// Use the toString function on different things:
alert(toString(3.14159265));  // [object Number]
alert(toString(/regular_expression/g)); // [object RegExp]
alert(toString("a string")); // [object String]
alert(toString(toString)); // [object Function]

// Reference the Array's prototypal function.
var slice = [].slice.getCall();

// Use the slice function on different things:
alert(slice([0,1,2,3], 2));  // 2,3
alert(slice("abcd", 1));  // b,c,d
alert(slice((function(){return arguments})(9,8,7), 0));  // 9,8,7

You may be wondering why we don’t just reference the call() function. Believe it or not, the following code doesn’t work:


var slice = Array.prototype.slice.call;
alert(slice([1,2,3], 0));  // error occurs

The reason the above code doesn’t work is because the reference to slice is not kept within the call() function. To prove this, you can see try the following test:


var slice = [].slice.call;
var toString = ({}).toString;
alert(slice === toString);  // true

The reason slice and toString reference the same function is because on the first two lines, I am actually saving a reference to Function.prototype.call(). Unfortunately, the reference to the slice and toString functions are lost at the point of assigning the references to variables. For this reason, we need to define a new function which will allow you to get a function equivalent to the call() function without losing the reference to the original function. That is why I have the following definition for the getCall() function:


Function.prototype.getCall = function() {
    var fn = this;
    return function() {
        return fn.call.apply(fn, arguments);
    };
};

Now, we can reference a function equivalent to the call() function of another function. One of the biggest advantages of using this approach comes when you have to minify your JS code.

Also, if you would like an equivalent getApply() function, you could use the following definition:


Function.prototype.getApply = function() {
    var fn = this;
    return function(context, args) {
        return fn.apply(context, args);
    };
};
Categories: BlogJavaScriptJScript

1 Comment

How do you reference Array.prototype.slice.call()? - Programmers Goodies · July 26, 2011 at 3:55 PM

[…] you the ability to retrieve the call function for any other function. Here is a definition that I posted on my blog for such a function which I called […]

Leave a Reply

Your email address will not be published. Required fields are marked *