tag:blogger.com,1999:blog-34454975.post1792101957291969684..comments2023-06-28T16:58:41.189+02:00Comments on Web Reflection: Function.prototype.bindAndrea Giammarchihttp://www.blogger.com/profile/16277820774810688474noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-34454975.post-33390406697196789852011-09-02T21:45:38.299+02:002011-09-02T21:45:38.299+02:00I've found another part of the problem with Fu...I've found another part of the problem with Function.prototype.bind: http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.htmlAnonymoushttps://www.blogger.com/profile/13411963065308750818noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-61726173863666901062010-02-21T23:33:30.299+01:002010-02-21T23:33:30.299+01:00I agree :DI agree :Djoseanpghttp://joseanpg.netnoreply@blogger.comtag:blogger.com,1999:blog-34454975.post-46701482436105520342010-02-21T22:42:04.117+01:002010-02-21T22:42:04.117+01:00sure, that would be valid.
What do I think?
I th...sure, that would be valid.<br /><br />What do I think?<br /><br />I think I have both the fastest and more stable version here ;)Andrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-85018620445258721172010-02-21T22:38:06.537+01:002010-02-21T22:38:06.537+01:00Undoubtedly the best option is
boundArgs.concat(_...Undoubtedly the best option is<br /><br />boundArgs.concat(_slice.call(arguments))<br /><br />But the following would be valid too<br /><br />_concat.call(boundArgs,_slice.call(arguments))<br /><br />Do you agree?<br /><br />By the way, it seems that <a href="https://prototype.lighthouseapp.com/projects/8886/tickets/215-optimize-bind-bindaseventlistener#ticket-215-12" rel="nofollow">bind_even_newer</a> also suffers the problem of flattening concat.apply, what do you think?joseanpghttp://joseanpg.netnoreply@blogger.comtag:blogger.com,1999:blog-34454975.post-76744512911708805042010-02-21T21:16:07.875+01:002010-02-21T21:16:07.875+01:00call is fine, but it wont recognize arguments as a...call is fine, but it wont recognize arguments as an array, so it won't concatenate arguments as expected ;)Andrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-7981485495422148042010-02-21T20:26:19.510+01:002010-02-21T20:26:19.510+01:00Very good advice:
"...specially because if a...Very good advice:<br /><br /><i>"...specially because if an argument is an array, this will become flat.<br /><br />var a = [[1, 2], 3];<br />var b = [[4, 5], 6];<br />alert(a.concat(b).join("-"));//1,2-3-4,5-6<br />alert(a.concat.apply(a, b).join("-"));// 1,2-3-4-5-6<br /><br />As you can see, that is simply an error, able to make arguments inconsistent"</i><br /><br />Is <a href="https://prototype.lighthouseapp.com/projects/8886/tickets/215-optimize-bind-bindaseventlistener#ticket-215-16" rel="nofollow"><br />bind_researched</a><br />making that mistake?<br /><br />Perhaps could be fixed using <b>call</b> instead of <b>apply</b>:<br /><br />alert(a.concat.call(a, b).join("-"));//1,2-3-4,5-6joseanpghttp://joseanpg.netnoreply@blogger.comtag:blogger.com,1999:blog-34454975.post-10854621178493354142010-02-21T13:59:35.752+01:002010-02-21T13:59:35.752+01:00@joseanpg there are several bind implementation ou...@joseanpg there are several bind implementation out there. My aim is to provide the fastest one avoiding every redundant operation and using all it's possible to speed up both creation and execution.<br /><br />In your example there are several useless steps.<br /><br />isPartial is created and passed via "not", why? That variable is not useful, the if could simply contain: if (1 < arguments.length) ... same case, no need for a variable, netirher a "not" operation.<br /><br />Same is for checks agains integer, 0 is falsy since C language and it's accepted in C as well as boolean.<br />if (0) { falsy }<br />There is no need to strictly compare via === or !== <br />An if/else statement is usually slower than a ternary operation.<br />Specially in JS where we have no bytecode, it means lots of redundant code as well to surround those 2 cases.<br /><br />return arguments.length ? apply : call<br /><br />This is all we need.<br />In Strategy 2 every time there is one or more arguments, we need to lookup for the global Array, and access its prototype.<br /><br />This is both slower and not safe. Global Constructor prototypes should be always cached in advance so that it's easier to access the method we are looking for, and it's safer, since if another library will replace Array, its prototype, or one of its method we trust for our purpose, we could be in troubles.<br />Finally, since concat already accepts an array to concat, there is no need at all to cache concat and use apply, specially because if an argument is an array, this will become flat.<br /><br />var a = [[1, 2], 3];<br />var b = [[4, 5], 6];<br />alert(a.concat(b).join("-"));<br />//1,2-3-4,5-6<br /><br />alert(a.concat.apply(a, b).join("-"));<br />// 1,2-3-4-5-6<br /><br />As you can see, that is simply an error, able to make arguments inconsistent (if I passed an array as first argument, I meant it!)Andrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-13352744205880601172010-02-21T13:05:05.463+01:002010-02-21T13:05:05.463+01:00What do you think about the implementation of Gar...What do you think about the <a href="http://dhtmlkitchen.com/?category=/JavaScript/&date=2008/09/11/&entry=Function-prototype-bind" rel="nofollow"> implementation of Garrett Smith</a>?<br /><><br />Function.prototype.bind = function(context){<br /> var fn = this, <br /> ap, concat, args,<br /> isPartial = arguments.length > 1;<br /> // Strategy 1: just bind, not a partialApply<br /> if(!isPartial) {<br /> return function() {<br /> if(arguments.length !== 0) {<br /> return fn.apply(context, arguments);<br /> } else {<br /> return fn.call(context); // faster in Firefox.<br /> }<br /> };<br /> } else {<br /> // Strategy 2: partialApply<br /> ap = Array.prototype,<br /> args = ap.slice.call(arguments, 1);<br /> concat = ap.concat;<br /> return function() {<br /> return fn.apply(context, <br /> arguments.length === 0 ? args : <br /> concat.apply(args, arguments));<br /> };<br /> }<br />};joseanpgnoreply@blogger.comtag:blogger.com,1999:blog-34454975.post-12847333908628348482010-02-20T20:17:24.524+01:002010-02-20T20:17:24.524+01:00The check !context is poor, if I want to pass the ...<i>The check !context is poor, if I want to pass the current global object I do believe null should be accepted.</i><br /><br />errata, null will result into null, undefined context, so I guess the check should be context == null for ES5.<br /><br />UpdatedAndrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-71509420549789743632010-02-20T20:15:37.640+01:002010-02-20T20:15:37.640+01:00Michael, that is not standard, bind accepts a this...Michael, that is not standard, bind accepts a <i>thisArg</i> plus, optionally, one or more arguments.<br /><br />The check <i>!context</i> is poor, if I want to pass the current global object I do believe null should be accepted.<br /><br />If I want to pass a persistent condition, true or false, I don't see why I should not be able to bind this value.<br /><br />RegardsAndrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-8651593865174721022010-02-20T20:01:50.675+01:002010-02-20T20:01:50.675+01:00Why not use this instead of manipulating the argum...Why not use this instead of manipulating the arguments object?<br /><br />if(!Function.prototype.bind){<br /> Function.prototype.bind = function(context){<br /> if(!context)<br /> return this;<br /> var fun = this;<br /> return function(){<br /> return fun.apply(context, arguments);<br /> };<br /> };<br />}mlhaufehttps://www.blogger.com/profile/07964865381194929027noreply@blogger.com