On Tue, Sep 9, 2008 at 9:47 PM, David-Sarah Hopwood
<[EMAIL PROTECTED]> wrote:
> Mark S. Miller wrote:
>> On Tue, Sep 9, 2008 at 9:21 AM, Mark S. Miller <[EMAIL PROTECTED]> wrote:
>>> I still need to spec Function.prototype.bind in our funny spec language.
>>> Anyone care to contribute a draft?
>
> I have also assumed the existence of a "static" Function.apply which
> takes the function to be applied as an explicit first argument. This
> is necessary because otherwise there is no way to bind 'this' correctly
> given that thisFunc.apply may have been overridden (or at least, I
> don't know of any way to do it).
>
That code cannot be tested it in any implementations that do not have
your Function.apply.
if(!Function.apply) {
...
}
Just for fun...
You'll have to wait a few 10 seconds to see any results. The returned
function is faster when it does bind only (GarrettsBind tests #3 and
#4, no partialApply), or a partialApply called with 0 args
(GarrettsBind test #1).
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type"
content="text/html; charset=iso-8859-1">
<title>BindFunction.html</title>
</head>
<body>
<script type="text/javascript">
/**
* @param {Object} context - the - this - value to be used.
* @param {arguments} [1..n] optional arguments that are
* prepended to returned function's call.
* @return {Function} a function that applies the original
* function with - context - as the thisArg.
*/
var bindFunctions = [
{
name : "GarrettsBind",
fun:function GarrettsBind(context){
var fn = this,
slice = Array.prototype.slice,
args,
isPartial = arguments.length > 1;
if(isPartial)
args = slice.call(arguments, 1);
// Strategy 1: just bind, not a partialApply
if(!isPartial) {
return function() {
if(arguments.length !== 0) {
return fn.apply(context, arguments);
} else {
return fn.call(context); // faster in Firefox.
}
};
} else {
// Strategy 2: partialApply
return function() {
return fn.apply(context,
arguments.length === 0 ? args :
args.concat(slice.call(arguments)));
};
}
}
},
{
name : "MarksBind",
fun : function MarksBind(self, var_args) {
var thisFunc = this;
var slice = Array.prototype.slice;
var leftArgs = slice.call(arguments, 1);
return function(var_args) {
var args = leftArgs.concat(slice.call(arguments, 0));
return thisFunc.apply(self, args);
};
}
}
];
var currBindFunction = 0;
// Mock Data
function x(a,b,c) {
return ((a||0) + (b||0) + (c||0) + this.v);
}
var o = {v: 1000};
var value;
var ITER = 10000;
var d = new Date,
result,
resultsDiv,
currentTest = 0,
results = [bindFunctions[0].name];
function oncomplete() {
if(++currentTest === tests.length) {
if(++currBindFunction === bindFunctions.length) {
resultsDiv = document.getElementById('resultsDiv');
resultsDiv.innerHTML =
results.join('\n---------------------\n');
return;
} else {
var bo = bindFunctions[currBindFunction];
currentTest=0;
results.push('\n', bo.name);
Function.prototype.bind = bo.fun;
}
}
setTimeout(function(){tests[currentTest].run();}, 500);
}
var tests = [
{
run : (function testBindPartialNoArgs() {
d=new Date;
var adder = x.bind(o, 1, 10, 100);
for(var i = 0; i < ITER; i++) {
result = adder();
}
results.push(
new Result("x.bind(o, 1, 10, 100); adder()",
result===1111, new Date-d)
);
oncomplete();
})
},
{
run : (function testBindPartialWithArgs() {
d=new Date;
var adder = x.bind(o, 1);
for(var i = 0; i < ITER; i++) {
result = adder(10, 100);
}
results.push(
new Result("x.bind(o, 1); adder(10, 100)",
result===1111, new Date-d)
);
oncomplete();
})
},
{
run : (function testBindWithArgs() {
d=new Date;
var adder = x.bind(o);
for(var i = 0; i < ITER; i++) {
result = adder(1, 10, 100);
}
results.push(
new Result("x.bind(o); adder(1, 10, 100)",
result===1111, new Date-d)
);
oncomplete();
})
},
{
run : (function testBindNoArgs() {
d=new Date;
var adder = x.bind(o);
for(var i = 0; i < ITER; i++) {
result = adder();
}
results.push(
new Result("x.bind(o); adder()",
result===1000, new Date-d)
);
oncomplete();
})
}
];
Function.prototype.bind = bindFunctions[0].fun;
tests[0].run();
tests
function Result(s, pass, time) {
this.s = s;
this.result = (pass === true ? "PASS" : "FAIL");
this.time = time;
}
Result.prototype.toString = function() {
return this.s +
"\nresult: " + this.result
+ "\ntime: " + this.time;
}
</script>
<pre id="resultsDiv"></pre>
</body>
</html>
(To be able to test in other browsers, Mark's bind was modified so
that it does not use Array.slice, but instead
Array.prototype.slice.call)
Garrett
> --
> David-Sarah Hopwood
_______________________________________________
Es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss