Performance penalty for undefined arguments - javascript

I quite often have optional arguments in functions, but some testing is showing a huge performance hit for them in firefox and safari (70-95%). Strangely, if I pass in the literal value undefined then there is no penalty. What could be happening here? I wouldn't have thought that it was a scope chain issue as they are inherently local to the function. Am I to start passing undefined into every optional argument?
jsPerf: http://jsperf.com/function-undefined-args/2

For a function like this:
function threeArgs(x, y, z) {
return x + y + z;
}
that's called like this:
threeArgs(1, 2, 3);
the optimizer is free to make the choice to generate no code at all. It's fairly easy for it to determine that there are no side effects, because the function simply references its parameter values and returns the result of a simple expression. Since the return value is ignored, there's no reason for the runtime to do anything at all.
Beyond that, if the code were:
something += threeArgs(1, 2, 3);
the optimizer might decide to generate code roughly equivalent to:
something += 6;
Why? Because the call was made with numeric constants, and it can safely fold those at code generation time. It might be conservative on that, because numbers are weird, but here they're all integers so it could well do this. Even if it didn't, it could safely inline the function:
something += 1 + 2 + 3;
When there's a parameter missing, however, it may be that the optimizers bail out and generate a real function call. For such a simple function, the overhead of the function call could easily account for a large difference in performance.
By using variables instead of constants in a test, and by actually using the return value of the function, you can "confuse" the optimizer and keep it from skipping the call or pre-computing the result, but you can't keep it from inlining. I still think that your result is interesting for that reason: it exposes the fact that (as of today anyway) those optimizers are sensitive to the way that functions are invoked.

I think what could explain the performance difference is the way arguments are passed to a function object: via the arguments object. When not passing any arguments, JS will start by scanning the arguments object for any of the given arguments, when those are undefined, The arguments prototype chain will be scanned, all the way up to Object.prototype. If those all lack the desired property, JS will return undefined. Whereas, passing undefined explicitly, sets it as a property directly on the arguments object:
function foo(arg)
{
console.log(arguments.hasOwnProperty('0'));
}
foo();//false'
foo('bar');//true
foo(undefined);//true
I gather that's the reason why passing undefined explicitly tends to be faster.

Related

passing single argument into a function that requires multiple arguments in javascript

I'm trying to read through some source code on the internet, and I'm getting confused because the author defined a function as:
var _0x80a1 = function (x, a) {...}
But then only calls it using statements like this:
_0x80a1("0x0")
How does that work?
JavaScript parameters are optional you don't need to pass them. So you can do something like this:
function multiply(a, b) {
if(typeof b === 'undefined') {
b = 10;
}
return a * b;
}
console.log(multiply(5));
// expected output: 50
In newer versions of JS you can also do default parameters like this:
function multiply(a, b = 10) {
return a * b;
}
console.log(multiply(5));
// expected output: 50
No function "requires" an argument in JavaScript. It's not a strongly typed language.
I might be typing out of my own butt, but I think function's arguments are syntactic sugar in JS. You can always pass any amount of arguments, regardless of the function's "signature", because the only thing that identifies a function in JS, is its name (and the object on which it is called). That is why, the arguments object exists.
So, as others pointed it out, the second, third, or any other argument that wasn't given will simply be undefined.
An answer on this subject with examples
In ,JavaScript function parameters are optional.If your'e not making use of 'a' inside your function then JS compiler don't care about that.If your'e making use of 'a' inside your function then you will encounter some error like "a is undefined".
function (x,a=10){
}
You can set default parameters like this.Now even if your'r passing one parameter to your function it will run without any errors
I was curious so tried to understand this a bit so I could try to answer.
The variable _8x80a1 is a literal bit definition (https://www.hexadecimaldictionary.com/hexadecimal/0x80A1/) representing e.g. 32929 in decimal.
I'm guessing JS internally numbers all functions when its run. This leaves an entire integer (32766) 'vanilla' functions that can be compiled before using a literal as a function name might cause a conflict.
So the 'x' in the function def. looks like it's passing a string, but it might be just calling 'Function #0' in the _8x80a1 var/function. This would make sense if the function contains multiplpe 'sub functions', as then the 'a' variable can be an object collection (e.g. parameters), that can be passed to the sub-function.
Roughtly, I think .. Not used JS for a whilst and just thought I'd try to help answer! ;-) Essentially a compact way to make a toolkit you can copy between projects, and know your references will all work as expected to your tools, without disrupting e.g. jQuery or other scripts. (Wouldn't be surprised if this is how JS is minified actually ;)).
Chris

Why don't we get error if we pass 3 arguments to a function which is declared with 2 parameters in JavaScript [duplicate]

This question already has answers here:
What happens if I call a function with more arguments than it is defined to accept?
(5 answers)
Closed 3 years ago.
I know its silly to ask this question but still, I want to know why don't javascript throw an error if we declare a function with only 1 parameter and pass multiple arguments.
function checkIt(a){
return a;
}
checkIt(6,5);
and the answer we got is 6.
It's just how JS is implemented-- you can have less or more arguments without any errors.
If you have less, you get undefined for where you didn't enter any arguments.
If you have more, it's simply put into the arguments array. Usually, if you want to accept a misc. number of arguments, you'll use the (...) operator in parameters to let people know that it's a function that accepts an unknown number of arguments. Also, the good thing about the (...) operator is that it only grabs arguments that aren't known, as opposed to the arguments variable which just grabs everything.
Interesting question.
JavaScript is a "Loosely Typed" Language.
In programming, we call a language "loosely typed" when you don't have to explicitly specify types of variables and objects.
JavaScript is loosely typed. You don't have to tell that a string is a string, nor you can require a function to accept an integer as its parameter.
This gives JavaScript a lot of flexibility. Flexibility lets you move faster, change things quickly, iterate at a faster velocity.
One of the features of loosely typed language is that they auto initialize and typecast variables as required. Hence, when the JS interpreter reads the arguments and sees that one of the argument is missing, it automatically initializes it as undefined and continues with the further programming flow.
This is a concept which almost applicable to all loosely typed languages.
Thanks.
One reason is that it's not necessarily possible to determine how many arguments a function should accept, just from reading it. For example, what if your checkIt checked arguments[1] somewhere? (But that's not something for the interpreter to scan for on function invocation)
function checkIt(a) {
console.log(arguments[1]);
return a;
}
checkIt(6, 5);
Or, the same thing with argument rest syntax:
function checkIt(...args) {
console.log(args[1]);
return args[0];
}
checkIt(6, 5);
The argument index to find could even be dynamic:
function checkIt(argIndex, ...args) {
console.log(args[argIndex]);
}
checkIt(1, 5, 6, 7);
Passing more arguments than stated in the parameter list may well be a code smell, but just like missing semicolons and unnecessary semicolons, there's no explicit reason for it to throw an error, so it doesn't.

What are the harmful effects of manipulating an object passed in as a parameter? [duplicate]

Eclipse has an option to warn on assignment to a method's parameter (inside the method), as in:
public void doFoo(int a){
if (a<0){
a=0; // this will generate a warning
}
// do stuff
}
Normally I try to activate (and heed) almost all available compiler warnings, but in this case I'm not really sure whether it's worth it.
I see legitimate cases for changing a parameter in a method (e.g.: Allowing a parameter to be "unset" (e.g. null) and automatically substituting a default value), but few situations where it would cause problems, except that it might be a bit confusing to reassign a parameter in the middle of the method.
Do you use such warnings? Why / why not?
Note:
Avoiding this warning is of course equivalent to making the method parameter final (only then it's a compiler error :-)). So this question Why should I use the keyword "final" on a method parameter in Java? might be related.
The confusing-part is the reason for the warning. If you reassign a parameter a new value in the method (probably conditional), then it is not clear, what a is. That's why it is seen as good style, to leave method-params unchanged.
For me, as long as you do it early and clearly, it's fine. As you say, doing it buried deep in four conditionals half-way into a 30-line function is less than ideal.
You also obviously have to be careful when doing this with object references, since calling methods on the object you were given may change its state and communicate information back to the caller, but of course if you've subbed in your own placeholder, that information is not communicated.
The flip side is that declaring a new variable and assigning the argument (or a default if argument needs defaulting) to it may well be clearer, and will almost certainly not be less efficient -- any decent compiler (whether the primary compiler or a JIT) will optimize it out when feasible.
Assigning a method parameter is not something most people expect to happen in most methods. Since we read the code with the assumption that parameter values are fixed, an assignment is usually considered poor practice, if only by convention and the principle of least astonishment.
There are always alternatives to assigning method parameters: usually a local temporary copy is just fine. But generally, if you find you need to control the logic of your function through parameter reassignment, it could benefit from refactoring into smaller methods.
Reassigning to the method parameter variable is usually a mistake if the parameter is a reference type.
Consider the following code:
MyObject myObject = new myObject();
myObject.Foo = "foo";
doFoo(myObject);
// what's the value of myObject.Foo here?
public void doFoo(MyObject myFoo){
myFoo = new MyObject("Bar");
}
Many people will expect that at after the call to doFoo, myObject.Foo will equal "Bar". Of course, it won't - because Java is not pass by reference, but pass by reference value - that is to say, a copy of the reference is passed to the method. Reassigning to that copy only has an effect in the local scope, and not at the callsite. This is one of the most commonly misunderstood concepts.
Different compiler warnings can be appropriate for different situations. Sure, some are applicable to most or all situations, but this does not seem to be one of them.
I would think of this particular warning as the compiler giving you the option to be warned about a method parameter being reassigned when you need it, rather than a rule that method parameters should not be reassigned. Your example constitutes a perfectly valid case for it.
I sometimes use it in situations like these:
void countdown(int n)
{
for (; n > 0; n--) {
// do something
}
}
to avoid introducing a variable i in the for loop. Typically I only use these kind of 'tricks' in very short functions.
Personally I very much dislike 'correcting' parameters inside a function this way. I prefer to catch these by asserts and make sure that the contract is right.
I usually don't need to assign new values to method parameters.
As to best-practices - the warning also avoids confusion when facing code like:
public void foo() {
int a = 1;
bar(a);
System.out.println(a);
}
public void bar(int a) {
a++;
}
You shoud write code with no side effect : every method shoud be a function that doesn't change . Otherwise it's a command and it can be dangerous.
See definitions for command and function on the DDD website :
Function :
An operation that computes and returns a result without observable side effects.
Command : An operation that effects some change to the system (for
example, setting a variable). An
operation that intentionally creates a
side effect.

Amount of passed parameters to functions in JavaScript

JavaScript is a revelation to me. I thought it would be like another sort of classical languages like C#, Java, etc. But it didn't. "Dynamic world" is tough and unpredictable. I was astonished when I read that functions can receive as many parameters as you desire. Without any error! I don't like it at all. I want more "staticness", I want some sort of compile-time errors!
My question is: am I need to worry about that? Is it a good practice to throw an exception if a quantity of passed parameters are more than a particular function expects?
function foo(one, two, three)
{
// Is it good?
if(arguments.length > arguments.callee.length)
throw new Error("Wrong quantity of arguments in " + arguments.callee.name + "()");
/* Stuff */
}
foo(1, 2, 3, 4); // -> Error
foo(1, 2, 3); // -> OK
Should I be concerned about it at all?
Thanks in advance!
You probably should not be concerned. There is no blanket rule on how to handle errors like this. It depends entirely upon the type of error and the type of situation. In some cases, where it's a serious programming error and there is no way to proceed (like insufficient arguments to perform the desired function), it may make sense to throw an exception or return an error from the function. But, in other cases, an extra argument can just be safely ignored and you can continue on your merry way as if that argument was never passed.
As you get used to javascript, you will come to understand that many function arguments can be optional and a single function may be correctly called with zero, one, two or three or even N arguments and the code in the function can adapt appropriately. This actually allows you to do things that are not as easy to do in more "static" languages. It is even possible to adapt to the type of the arguments and do something appropriately based on the type of the argument. While this may sound like heresy to someone that only has experience in hard-typed languages, it can actually be extremely useful.
As you maintain a body of code over time, you will also come to find that it's nice to be able to add an argument to the definition of a function, add code to that function that defaults it to a reasonable value if it isn't passed and NOT have to change any of the prior code that was using that function, yet a few new places that need that new argument can start using it immediately. Rather then grepping through the entire codebase to fix up every caller of that function, you can just make one change in one file and immediately start using a new argument to the function without changing all the other callers. This is enormously useful.
So, in more direct answer to your question, an extra argument passed to a function is never a serious error in javascript. Your code could just ignore it and proceed. If you want to alert the developer who wrote that code that an unexpected argument was passed, you can notify them somehow (perhaps some warning text on the debug console) in the "debug" version of your function/library, but I see no reason why you should stop execution in the "production" version of your function/library when you can proceed without any harm.
You don't need to worry about this. If you pass too many arguments, the function will just ignore it. You should only throw an error if there are too few arguments. In that case, the function might not be able to run.
While I agree that the number of arguments aren't important (and won't cause a problem so long as you type-check the arguments you're getting before you use them), since an unused, uncalled, argument won't do anything, if you're particularly concerned you could just create a subset of the passed-arguments and access that object internally:
function test(arg1, arg2, arg3) {
var slice = Array.prototype.slice,
subset = slice.call(arguments, 0, 3); // depending on how many arguments you want
}
Of course this means that you've now got to recover the parameters from the args object, and since surplus arguments seem to be perfectly safe this seems pointless. But it is still an option.
Albeit unnecessary.

Dynamic vs Static Compiler (JavaScript)

I'm currently writing a JavaScript compiler in ANTLR+Java.
I've read questions here on Stack Overflow on how to proceed with the execution - and the answer is always that it would be way too hard to do a static compilation (without JIT-information) of a dynamic language - but why is that exactly? There are of course the obvious "type resolving" problem and in JavaScript maybe a problem with the eval function - but are there other reasons? (because they don't seem too hard to overcome pure statically (no JITS))
I'm excluding JIT-based compilation because I figure it would be too hard for me to implement.
I have some experience in writing static compilers with a byte-code execution.
UPDATE:
All your answers are really helpfull understanding the problem.
To clarify does this mean that JavaScript is harder to implement than other dynamic languages?
And does this also means that im better of using a Tree-based interpreter than e.g. Byte-code (if we forget about the property that JS always is shipped in raw source code - hence adding extra time for generating and IR and afterwards execute it)? - or should they be about equally easy / hard to do?
(Im new to SOF; dont know if this is the preferred way to update a question?)
There are lots of ways this conversation could go. Here's one direction. In javascript, nearly everything is an object and properties or methods can be added to any object at run-time. As such, you don't know at compile time what methods or properties will or won't be attached to an object. As such, everything has to be looked up at run-time.
For example:
var myObj = {};
function configureObject() {
if (something in the environment) {
myObj.myfunc = function () {alert("Hi");}
} else {
myObj.myfunc = function () {document.write("Hello");}
}
}
Now, sometime later in the code you call myObj.myfunc(); It is not known at compile time what myfunc is or whether it's even an attribute of myObj. It has to be a run-time lookup.
In another example, take this line of code:
var c = a + b;
What his means depends entirely upon the types of a and b and those types are not known at compile time.
If a and b are both numbers, then this is an addition statement and c will be a number.
If either a or b is a string, then the other will be coerced to a string and c will be a string.
You can't precompile this kind of logic into native code. The execution environment has to record that this is a request for the addition operator between these two operands and it has to (at runtime) examine the types of the two operands and decide what to do.
The challenge with writing a static JavaScript compiler is that it is in general undecidably hard to determine what objects are being referenced at any program point or what functions are being called. I could use the fact that JavaScript is dynamic to decide which function to call based on the output of some Turing machine. For example:
var functionName = RunTuringMachineAndReportOutputOnTape(myTM, myInput);
eval(functionName + "();");
At this point, unless you have advance knowledge about what myTM and myInput are, it is provably impossible to decide what function will be invoked by the call to eval, since it's undecidable to determine what is on a Turing machine's tape if it halts (you can reduce the halting problem to this problem). Consequently, no matter how clever you are, and no matter how good of a static analyzer you build, you will never be able to correctly statically resolve all function calls. You can't even bound the set of functions that might be called here, since the Turing machine's output might define some function that is then executed by the above code.
What you can do is compile code that, whenever a function is called, includes extra logic to resolve the call, and possibly uses techniques like inline caching to speed things up. Additionally, in some cases you might be able to prove that a certain function is being called (or that one of a small number of functions will be called) and can then hardcode in those calls. You could also compile multiple versions of a piece of code, one for each common type (object, numeric, etc.), then emit code to jump to the appropriate compiled trace based on the dynamic type.
V8 does that. See Compile JavaScript to Native Code with V8
With EcmaScript 3 and 5 non-strict there are a number of wrinkles around scopes which you don't run into in other dynamic languages. You might think that it is easy to do compiler optimizations on local variables, but there are edge cases in the language when it is not, even ignoring eval's scope introspection.
Consider
function f(o, x, y) {
with (o) { return x + y + z; }
}
when called with
o = {};
o = { z: 3 };
o = { x: 1, z: 2 };
Object.prototype.z = 3, o = {};
and according to EcmaScript 3,
x = (function () { return toString(); })()
should produce quite a different result from
x = toString();
because EcmaScript 3 defines an activation record as an object with a prototype chain.

Categories

Resources