Re: addEvent - The late entry :)
- From: "Richard Cornford" <Richard@xxxxxxxxxxxxxxxxxxx>
- Date: Mon, 21 Jul 2008 22:37:35 +0100
jdalton wrote:
@Richard CornfordIndeed so far so that their only way out is to petition for a
new - bind - method in the new language versions so that faster
native code can rescue their authors from the consequences of
original designs.
As far as I know the Prototype core members have not petition
for a native bind method.
Maybe, but that has not stopped the authors of other similar libraries making such petitions, and citing Prototype.js methods in order to bolster their position.
I believe other developers have seen its worth and have
requested its addition.
I dislike the tone of your comment.
Should I take it that the contempt is coming across?
The authors are perfectly
capable and do not need “rescuing”.
The evidence (past and present) suggests otherwise.
You make some very good points about Prototype’s bind method.
You don't say?
There are been some performance patches submitted that deal<snip>
with bind and other methods:
http://prototype.lighthouseapp.com/attachments/31739/0467-Optimize-bind-bindAsEventListener.patch
That ends up with a method that looks like:-
| bind: function() {
| if (arguments.length < 2 && Object.isUndefined(arguments[0]))
| return this;
| var __method = this, args = $A(arguments), object = args.shift();
| if (args.length) {
| return function() {
| return __method.apply(object, args.concat($A(arguments)));
| }
| }
| return function() {
| return __method.apply(object, arguments);
| }
| },
- which is a bit of a half-arse effort at improving performance, and faulty in terms of the logic it uses. The branch that just returns this is only acted upon if the value of the first argument is undefined, but the apply and call method both use the global object as the - this - value if their first argument is null or undefined. Javascript offers a very simple test that discriminated null and undefined form all other values, so that could be used in place of the comparatively heavyweight and insufficient - Object.isUndefined(arguments[0]) - test.
As the - args - array is only to be used when it has a non-zero length it would be better to only create that array in the branch that uses it. It remains where it is because the - object - variable needs to be initialised for both of the following branches. Except in reality it does not need to be initialised at all. If instead of using a variable, - object - had been declared as a single formal parameter for the method that parameter would have automatically been assigned the same value a arguments[0]. Having done that the - args - array creation can be moved into the branch that uses it, and so not executed at all when only one argument was used with the - bind - method.
Once the - object - parameter is being used it is no longer necessary to - shift - its value out of the front of the array, and that opens up the possibility of using an alternative approach to create the array. Specifically applying the - Array.prototype.slice - to the arguments object, as in - args = Array.prototype.slice.call(arguments, 1); -, where fast native code creates the desired array and skips the first argument in the process.
And finally, using the - concat - method to append an array created from the arguments object is very convoluted and relatively inefficient when the arguments object can be used as the second argument to the - apply - method and the - apply - method could be called on - push -, which will take any number of arguments and append them to an array. That is:- __method.apply(object, args.concat($A(arguments))); - can be replaced with - __method.apply(obj, args.push.apply(args, arguments)); - and should result in superior performance.
The result might resemble:-
Function.prototype.bind = function(obj){
var args, fnc;
if(arguments.length > 1){
fnc = this;
args = Array.prototype.slice.call(arguments, 1);
return (function(){
return fnc.apply(obj, args.push.apply(args, arguments));
});
}else if(obj == null){
return this;
}else{
fnc = this;
return (function(){
return fnc.apply(obj, arguments);
});
}
};
- which has actually become very different form the authors of Prototype.js's best efforts to date. And it has lost all of its internal dependencies on Prototype.js in the process. (Maybe there is a lesson in that.)
Your faith in the authors or Prototype.js is touching, but no justification for it is evident in the code they write. An I bet that when they become aware of some of the possibilities suggested above they will happily take all the credit for any resulting performance gains that would be the consequences of their applying them (and some can be applied all over the place in Prototype.js methods).
Richard.
.
- Follow-Ups:
- Re: addEvent - The late entry :)
- From: Peter Michaux
- Re: addEvent - The late entry :)
- From: Lasse Reichstein Nielsen
- Re: addEvent - The late entry :)
- From: kangax
- Re: addEvent - The late entry :)
- From: Richard Cornford
- Re: addEvent - The late entry :)
- References:
- addEvent - The late entry :)
- From: Aaron Gray
- Re: addEvent - The late entry :)
- From: Richard Cornford
- Re: addEvent - The late entry :)
- From: Peter Michaux
- Re: addEvent - The late entry :)
- From: Richard Cornford
- Re: addEvent - The late entry :)
- From: Peter Michaux
- Re: addEvent - The late entry :)
- From: jdalton
- addEvent - The late entry :)
- Prev by Date: Simple Toggle checkbox function on IMAGE click
- Next by Date: Re: How do I get the value of a text node?
- Previous by thread: Re: addEvent - The late entry :)
- Next by thread: Re: addEvent - The late entry :)
- Index(es):
Relevant Pages
|