Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing JavaScript function's parameter value using arguments array not working

I am learning JavaScript and am pretty confused about the arguments property array.

I have a function that takes a single argument and returns it. When I pass the parameter and reassign it using arguments[0] = value, it's updating the value.

function a(b) {    arguments[0] = 2;    return b;  }  console.log(a(1)); //returns 2

But when I call the same function with no parameters it returns undefined.

function a(b) {    arguments[0] = 2;    return b;  }  console.log(a()); //returns undefined

But even if I pass undefined, the value will update as well.

function a(b) {    arguments[0] = 2;    return b;  }  console.log(a(undefined)); //returns 2

I thought that if you do not pass a parameter to a JavaScript function, it automatically creates it and assigns the value to undefined and after updating it should reflect the updated value, right?

Also a() and a(undefined) are the same thing, right?

like image 894
A Rogue Otaku Avatar asked Jan 23 '19 08:01

A Rogue Otaku


People also ask

Can we pass a variable number of arguments to a function JavaScript?

When you call a function in JavaScript, you can pass in any number of arguments, regardless of what the function declaration specifies. There is no function parameter limit. In the above function, if we pass any number of arguments, the result is always the same because it will take the first two parameters only.

Which one option will convert the arguments to an array?

Object. values( ) will return the values of an object as an array, and since arguments is an object, it will essentially convert arguments into an array, thus providing you with all of an array's helper functions such as map , forEach , filter , etc.

Can we pass an array as argument to a function in JavaScript?

We can pass the entire array to the function as an argument to simplify the code.


2 Answers

Assigning to arguments indicies will only change the associated argument value (let's call it the n-th argument) if the function was called with at least n arguments. The arguments object's numeric-indexed properties are essentially setters (and getters):

http://es5.github.io/#x10.6

Italics in the below are my comments on how the process relates to the question:

(Let) args (be) the actual arguments passed to the [[Call]] internal method

  1. Let len be the number of elements in args.

  2. Let indx = len - 1.

  3. Repeat while indx >= 0, (so, the below loop will not run when no arguments are passed to the function:)

(assign to the arguments object being created, here called map:)

    1. Add name as an element of the list mappedNames.
    1. Let g be the result of calling the MakeArgGetter abstract operation with arguments name and env.
    1. Let p be the result of calling the MakeArgSetter abstract operation with arguments name and env.
    1. Call the [[DefineOwnProperty]] internal method of map passing ToString(indx), the Property Descriptor {[[Set]]: p, [[Get]]: g, [[Configurable]]: true}, and false as arguments.

So, if the function is invoked with no arguments, there will not be a setter on arguments[0], so reassigning it won't change the parameter at index 0.

The same sort of thing occurs for other indicies as well - if you invoke a function with 1 parameter, but the function accepts two parameters, assigning to arguments[1] will not change the second parameter, because arguments[1] does not have a setter:

function fn(a, b) {   arguments[1] = 'bar';   console.log(b); } fn('foo');

So

a() and a(undefined) are the same thing right?

is not the case, because the second results in an arguments object with a setter and a getter on index 0, while the first doesn't.

Note that this odd interaction between the arguments and the function parameters is only present in sloppy mode. In strict mode, changes to arguments won't have any effect on the value an individual argument identifier contains:

'use strict'; function a(b) {   arguments[0] = 2;   return b; } console.log(a(1)); //returns 1
like image 65
CertainPerformance Avatar answered Oct 07 '22 18:10

CertainPerformance


ECMA 262 9.0 2018 describes this behaviour in 9.4.4 Arguments Exotic Objects with

NOTE 1:

The integer-indexed data properties of an arguments exotic object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function's execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. If the arguments object is an ordinary object, the values of its properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

In short,

  • if in 'sloppy mode', then all arguments are mapped to their named variables, if the length correspond to the given parameter, or

  • if in 'strict mode', then the binding is lost after handing over the arguments.

This is only readable in an older version of ECMA 262 7.0 2016. It describes this behaviour in 9.4.4 Arguments Exotic Objects with

Note 1:

For non-strict functions the integer indexed data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function's execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object's properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

like image 44
Nina Scholz Avatar answered Oct 07 '22 19:10

Nina Scholz