Improved Function#methodize
Reported by Juriy Zaytsev | July 12th, 2008 @ 07:13 AM
Continuing with Function.prototype.* optimizations, here's a "smarter" Function#methodize.
There are 34 Element methods in prototype.js that accept no arguments (more than a half of all) - Element.show, Element.hide, Element.visible, etc.
When extending DOM Elements, all these methods are "methodized" by one pattern - the one that accounts for extra arguments. Array.prototype.concat and $A are the usual party poopers when it comes to performance. By returning a "simpler" function when methodizing a parameter-less method, we can boost the speed of the entire library.
Function.prototype.methodize = function(noArgs) {
if __method = this;
return this._methodized = (noArgs === true)
? function() { return __method.call(null, this) }
: function() { return __method.apply(null, [this].concat($A(arguments))) };
}
Comments and changes to this ticket
-
Juriy Zaytsev July 12th, 2008 @ 07:23 AM
- → State changed from new to enhancement
Some numbers from FF2. I'm sure IE yields even better increase.
Function.prototype.methodize2 = function(noArgs) { var __method = this; return this._methodized = (noArgs === true) ? function() { return __method.call(null, this) } : function() { return __method.apply(null, [this].concat($A(arguments))) }; } document.body.show1 = Element.Methods.show.methodize(); document.body.show2 = Element.Methods.show.methodize2(true); console.time('old'); for(var i=0; i<1000; i++) document.body.show1(); console.timeEnd('old'); console.time('new'); for(var i=0; i<1000; i++) document.body.show2(); console.timeEnd('new'); // old: 57ms // new: 30ms -
Juriy Zaytsev July 20th, 2008 @ 01:17 AM
Attaching an alternative (better) patch which improves methodize, wrap and curry with using a safer technique. Speed improvements are as usual 30%+
-
John-David Dalton July 23rd, 2008 @ 03:48 PM
- → Assigned user changed from Juriy Zaytsev to Andrew Dupont
- → Milestone changed from to 1.6.0.3
-
-
Mark Caudill August 30th, 2008 @ 10:19 PM
For curry, isn't that pointless because !arguments.length returns this anyway?
if (!arguments.length) return this; var __method = this, args = $A(arguments); return function() { - return __method.apply(this, args.concat($A(arguments))); + return arguments.length + ? __method.apply(this, args.concat($A(arguments))) + : __method.apply(this, args); -
Juriy Zaytsev August 31st, 2008 @ 04:51 PM
@Mark
Those are two different
arguments: )First line in
curryensures that when no arguments are passed intocurry, the function is returned as it is:function foo(){}; foo.curry(); // => returns `foo` functionThe forking of returned function, on the other hand, is to skip unnecessary concatenation when no arguments are passed into a function returned by
curry:function foo(a,b){ return [a, b] }; var curried = foo.curry('bar'); // no arguments were given, no need to concat, returns ['bar', undefined] curried(); // arguments were given, concat them with curried ones, returns ['bar', 'baz'] curried('baz'); -
Tobie Langel October 1st, 2008 @ 01:53 PM
- → Milestone cleared.
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
The Prototype JavaScript library.
