-
Fri 2019.08.16
'Is this a bug, or a feature?'
Aren't all bugs really 'Undocumented Features'?
Hello Windy City @jrh from an Espruino neighbor 100 miles N.W. of you. Waukesha, WI home of Les Paul inventor of the solid body electric guitar. There are at least two of us here in the Midwest. Welcome to the world of Espruino!
Curious about your post, I tested the same on an EspruinoWiFi, and verify the same output.>foo( 100 ) 100 Uncaught ReferenceError: "1" is not defined
But looking under the hood reveals the culprit. I copied your snippet verbatim here for ease of others to copy and follow along as well.function foo(x,y) { for ( var i=0; i < arguments.length; i++ ) { console.log( arguments[i] ); } } foo( 2, 3 ); foo( 100 );
Q: What is the containerarguments
?When we add this line inside the function and run, we get:
console.log( typeof( arguments ) ); >foo( 2, 3 ) object
So we have a container that is an object that we know from experience, massages the values or arguments that are passed to the function parameters.
Now we go one step further and wonder well how many values does this arguments container actually receive?console.log( arguments.length ); foo( 2, 3 ); 2
So now we have our test snippet:function foo(x,y) { console.log( typeof( arguments ) ); console.log( arguments.length ); for ( var i=0; i < arguments.length; i++ ) { console.log( arguments[i] ); } }
Now lets proceed to the actual perceived error:
Uncaught ReferenceError: "1" is not defined
This is informing us that as we are dealing with an object that holds an array of values that when referenced with an 'i' indexer
arguments[i]
we may reveal what value is in each array location. The above error indicates that element 1 doesn't exist.Let's now take a peek at the function call:
foo(100);
And for the BIG SURPRISE!, I actually thought I had the obvious answer, until I did a bit more testing. Had to wrap the function contents in a try/catch to allow processing to continue and give us a bit more detail.function foo(x,y) { console.log( typeof( arguments ) ); console.log( arguments.length ); try { for ( var i=0; i < arguments.length; i++ ) { console.log( arguments[i] ); } } catch(e) { console.log( "ERROR: " + e.message ); } }
Running our test produces the same error.
>foo(100) object 2 100 ERROR: "1" is not defined
and then on to two additional lines for the Coup de Gras:
function foo(x,y) { console.log( typeof( arguments ) ); console.log( arguments.length ); try { console.log( arguments[0] ); console.log( arguments[1] ); // for ( var i=0; i < arguments.length; i++ ) { // console.log( arguments[i] ); // } } catch(e) { console.log( "ERROR: " + e.message ); } }
provides some additional information, but we still need a bit more, however
>foo(100) object 2 100 ERROR: "1" is not defined
Final test is to modify what is passed as the parameter list. We'll change the function definition to have just a single 'x' parameterfoo( x )
function foo(x) { console.log( typeof( arguments ) ); console.log( arguments.length ); try { console.log( arguments[0] ); // console.log( arguments[1] ); for ( var i=0; i < arguments.length; i++ ) { console.log( arguments[i] ); } } catch(e) { console.log( "ERROR: " + e.message ); } }
the result is as expected in our deign requirement expecting one argument be passed
>foo(100) object 1 100 100
If you have been following along, I believe you now have the answer to the question is this a bug?
Further clarity may be gained from the docs: -
Yes it's a bug.
arguments.length
is set to the number of arguments if the number of provided arguments is higher (and/or equal) to the number specified arguments in the function definition. But it is not set to the number of arguments if the number of provided arguments is smaller.As workaround define the function without arguments,
arguments.length
will be always correct.function foo(x,y) { console.log("arguments.length=" + arguments.length); //console.log("x=" + x); //console.log("y=" + y); //for ( var i=0; i < arguments.length; i++ ) { // console.log("typeof(arguments["+ i + "])=" + typeof(arguments[i])); // console.log("arguments["+ i + "]=" + arguments[i]); //} } function bar() { console.log("arguments.length=" + arguments.length); } foo(); foo(1); foo(1,2); foo(1,2,3); bar(); bar(1); bar(1,2); bar(1,2,3);
I was testing espruino on the Linux command line (while waiting for my boards to be shipped) and ran across this error. Is this a bug, or a feature?
The source was cloned from github and compiled on Ubuntu 16.04.6 LTS. I got the same error on an OS X build as well. It was built with the following commands:
I saw this post Functions with unknown amount of args. but I didn't get the same results.