-
-
Save jed/1400363 to your computer and use it in GitHub Desktop.
// usage: newOperator(constructor, [arg1, arg2, ...]) | |
// example: newOperator(Date, [1995, 11, 24]) | |
// => should be identical to new Date(1995, 11, 24) | |
function newOperator(constructor, args) { | |
var i = args.length + 1 | |
, params = [] | |
, fn | |
while (i--) params[i] = "$" + i | |
params.push("return new $0(" + params.slice(1) + ")") | |
fn = Function.apply(null, params) | |
params = params.concat.apply(constructor, args) | |
return fn.apply(null, params) | |
} |
good point, fixed it.
a non-golfed version:
function newOperator(ctor, args) {
var length, fn
args || (args = [])
length = args.length + 1
fn = newOperator[length]
fn || (fn = newOperator[length] = Function(
"ctor", "args", "i",
"return new ctor(" +
Array(length).join(",args[i++]").slice(1) +
")"
))
return fn(ctor, args, 0)
}
jed, no need to b=b||[] ... just b||[] because if length is zero Array(1).join("whatever") will be an empty string (join works with at least length 2 between 0 and 1) so the b, even if undefined, will be untouched ;-)
function d(
a, // constructor function
b, // arguments
c // placeholder for length
){
return( // return the result of
d[c=b?-~b.length:1] || ( // the cached function or
d[c] = Function( // a new function that takes
"a,b,c", // a constructor, arguments, and an index
"return new a(" + // and returns a new instance of the constructor
Array(c) // with
.join(",b[c++]") // the inline arguments
.slice(1) + // (sliced to remove leading comma)
")"
)
)
)(a,b,0) // called with the constructor and arguments
}
in that case, why define the array at all if args
has no length? can we use this?
var length = args ? args.length + 1 : 0
[EDIT] so something like this:
function newOperator(ctor, args) {
var length = args ? -~args.length : 0
, fn = newOperator[length]
fn || (fn = newOperator[length] = Function(
"ctor", "args", "i",
"return new ctor(" +
Array(length).join(", args[i++]").slice(1) +
")"
))
return fn(ctor, args, 0)
}
the minus tilde does not give us much more than +1, 2 readable chars with no necessary int cast.
I agree the creation of an empty Array per each call without arguments is way too redundant and also bigger than this solution:
d[c=b?b.length+1:1]
I have edited and as result 2 chars less and faster "no arguments" execution ;-)
doesn't leaving out the number cast mean that the length property could be used to inject code? i'm thinking where args
is {length: "throw 'neener neener'"}
.
well, the initial trick does not solve a thing here ... if you want to screw up functions that would work even with native arrays methods ...
uh .. wait, I know what you mean ... so yes, minus tilde then, updated :D
you changed function name, if it's d of course it's smaller ... I would still leave the (a||[]).length to make newOperator(Array) possible, as example