In JavaScript, any function can be called with an arbitrary number of arguments.
For example:
In some languages, the programmer can create two functions with the same name, but a different set of arguments, and when called, the interpreter chooses the necessary one:
This is called "function polymorphism" or "function overloading." There is nothing like this in JavaScript.
There can be only one function named log
, which is called with any arguments. And already inside she can look, with what is caused and to work in different ways.
In the example above, the second log
declaration will simply override the first.
Access to "superfluous" arguments
How to get argument values that are not in the parameter list?
They are accessed through the “pseudo-array” of arguments.
It contains a list of arguments by number: arguments[0]
, arguments[1]
..., as well as the length
property.
For example, we list all the arguments:
All parameters are in arguments
, even if they are listed. The code above would also work if the function is declared sayHi(a,b,c)
.
In the old JavaScript standard, the pseudo-array of arguments
and parameter variables refer to the same values.
As a result, changing the arguments
affects the parameters and vice versa.
For example:
On the contrary:
In the modern edition of the standard, this behavior is changed. Arguments are separated from local variables:
If you do not use strict mode, then so that the variables do not change “unexpectedly”, it is recommended that you never change the arguments
.
A common mistake for newbies is trying to apply Array
methods to arguments
. It's impossible:
The fact is that arguments
is not an Array
.
In reality, this is an ordinary object, just the keys are numeric and there is length
. At this similarity ends. He does not have any special methods, and he also does not support array methods.
However, no one bothers to make an ordinary array of arguments
:
Example of use: copy(dst, src1,...)
Sometimes there is a task - to copy properties from one or several others into an existing object.
Let's write for this function copy
. It will work with any number of arguments, thanks to the use of arguments
.
Syntax:
- copy (dst, src1, src2 ...)
- Copies properties from
src1, src2,...
objects into a dst
object. Returns the resulting object.
Using:
- To add properties to the
user
object: Using copy
allows you to reduce the code that would be required to manually copy the properties: The user
object is written only once, and the overall meaning of the code is clearer. - To create a copy of the
user
object: var userClone = copy({}, user); |
Such a “clone” of an object can be useful where we want to change its properties, while not touching the original user
object. In our implementation, we will copy only the properties of the first level, that is, the nested objects are not processed. However, it can be expanded.
We now turn to the implementation.
The first argument to copy
always there, so we specify it in the definition. And we will get the rest from arguments
, like this:
2 | for ( var i=1; i<arguments.length; i++) { |
3 | var obj = arguments[i]; |
4 | for ( var key in obj) { |
If desired, this copying can be implemented recursively.
arguments.callee
and arguments.callee.caller
The arguments
object not only stores the list of arguments, but also provides access to a number of interesting properties. They are absent in the modern JavaScript standard, but they are often found in the old code.
arguments.callee
The arguments.callee
property contains a reference to the function that is currently being executed.
This property is deprecated. The current specification recommends using named functional expressions (NFE).
Browsers can more efficiently optimize code if arguments.callee
not used.
However, the arguments.callee
property is often more convenient, since the function with it can be renamed as you like and you don’t have to change anything inside. In addition, NFE does not work correctly in IE <9.
For example:
Why do you need to do some callee
property if you can just use f
? To understand this, consider a slightly different example.
JavaScript has a built-in function setTimeout(func, ms)
, which calls func
in ms
milliseconds, for example:
The function that setTimeout
calls is declared as Function Expression
, without a name.
And what if you want to call yourself again from the function itself? By the name of something you can not apply. For such cases, the arguments.callee
invented, which guarantees that the function is addressed to itself from the inside.
That is, the recursive call will look like this:
Arguments can be passed to arguments.callee()
in the same way as a normal function.
An example with factorial:
2 | var factorial = function (n) { |
3 | return n==1 ? 1 : n* arguments.callee(n-1) ; n==1 ? 1 : n* arguments.callee(n-1) ; |
The
factorial
function does not use its name inside, so recursive calls will go correctly, even if the function has "moved" to another variable.
The recommended alternative to arguments.callee
are named functional expressions.
arguments.callee.caller
The arguments.callee.caller
property stores a reference to the function that called this .
This property is deprecated, similar to arguments.callee
.
There is also a similar arguments.caller
property (without callee
). It is not cross browser, do not use it. The arguments.callee.caller
property is supported everywhere.
For example:
In practice, this property is used very rarely, for example, to obtain information about the stack (the current chain of nested calls) for the purpose of error logging. But in modern browsers there are other ways to do this.
Why is callee
and caller
out of date?
In the modern standard, these properties are declared obsolete and are not recommended to be used. Although de facto, they are used at least because IE to version 9 does not support Named Function Expression as it should.
The reason for abandoning these properties is simple - the interpreter can optimize JavaScript more efficiently. Moreover, for arguments.callee
there is a replacement - NFE.
Importance: 5
You can find the number of actually passed arguments by the value of arguments.length
:
[Open task in new window]
Comments
To leave a comment
Scripting client side JavaScript, jqvery, BackBone
Terms: Scripting client side JavaScript, jqvery, BackBone