Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically set the length of a function

Tags:

javascript

The length property of functions tells how long the 'expected' argument list is:

console.log((function () {}).length);  /* 0 */
console.log((function (a) {}).length); /* 1 */
console.log((function (a, b) {}).length); /* 2 etc. */

However, it is a readonly method:

f = function (a) {};
alert(f.length); // 1
f.length = 3;
alert(f.length); // 1

Is there a way to programmatically set that length? The closest I've come so far is to use the Function constructor:

f = new Function("a,b,c", "/* function body here */");
f.length; // 3

However, using Function is essentially the same as eval and we all know how bad that is. What other options do I have here?

like image 317
nickf Avatar asked Sep 06 '11 08:09

nickf


2 Answers

It turns out the length property on functions is configurable, which means you can use .defineProperty to change the value of length on a function. Example:

function hi() {}
hi.length === 0; // Expected

Object.defineProperty(hi, "length", { value: 5 })
hi.length === 5; // Intriguing

This works in the latest version of Chrome and Firefox, but it does not work in Safari (v9.1.1).

like image 189
Xavi Avatar answered Oct 18 '22 14:10

Xavi


According to the ECMA Script standard, revision 5.1 on page 103, the .length parameter on a Function object is not writable so it is set when the function is declared and not changable (if implemented per spec).

Thus, the only way to create a function with a particular .length upon demand is to either have a bunch of functions lying around of various length (as nickf suggests), create a Function object (as you've already mentioned) or use eval() with a dynamically created string. I don't know what problem yu're actually trying to solve, but I personally find nothing wrong with using eval() if you know the source of the code you're using it with and have a way of either checking it or knowing what it will or won't have in it. In this case, programmatically generating a certain number of parameters in a string before calling eval() on it poses no security risk I'm aware of.

If this is all your own code, you can just create a new property on the function .dynLength that is mutable and set it to whatever you want and have your code use that.

like image 34
jfriend00 Avatar answered Oct 18 '22 13:10

jfriend00