JavaScript variable number of arguments to function - javascript

Is there a way to allow "unlimited" vars for a function in JavaScript?
Example:
load(var1, var2, var3, var4, var5, etc...)
load(var1)

Sure, just use the arguments object.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}

In (most) recent browsers, you can accept variable number of arguments with this syntax:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Here's a small example:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
​ 0: "a"
​1: "b"
​2: "c"
​3: "d"
​length: 4
Documentation and more examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters

Another option is to pass in your arguments in a context object.
function load(context)
{
// do whatever with context.name, context.address, etc
}
and use it like this
load({name:'Ken',address:'secret',unused:true})
This has the advantage that you can add as many named arguments as you want, and the function can use them (or not) as it sees fit.

I agree with Ken's answer as being the most dynamic and I like to take it a step further. If it's a function that you call multiple times with different arguments - I use Ken's design but then add default values:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
This way, if you have many parameters but don't necessarily need to set them with each call to the function, you can simply specify the non-defaults. For the extend method, you can use jQuery's extend method ($.extend()), craft your own or use the following:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
This will merge the context object with the defaults and fill in any undefined values in your object with the defaults.

It is preferable to use rest parameter syntax as Ramast pointed out.
function (a, b, ...args) {}
I just want to add some nice property of the ...args argument
It is an array, and not an object like arguments. This allows you to apply functions like map or sort directly.
It does not include all parameters but only the one passed from it on. E.g. function (a, b, ...args) in this case args contains
argument 3 to arguments.length

Yes, just like this :
function load()
{
var var0 = arguments[0];
var var1 = arguments[1];
}
load(1,2);

As mentioned already, you can use the arguments object to retrieve a variable number of function parameters.
If you want to call another function with the same arguments, use apply. You can even add or remove arguments by converting arguments to an array. For example, this function inserts some text before logging to console:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}

Although I generally agree that the named arguments approach is useful and flexible (unless you care about the order, in which case arguments is easiest), I do have concerns about the cost of the mbeasley approach (using defaults and extends). This is an extreme amount of cost to take for pulling default values. First, the defaults are defined inside the function, so they are repopulated on every call. Second, you can easily read out the named values and set the defaults at the same time using ||. There is no need to create and merge yet another new object to get this information.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
This is roughly the same amount of code (maybe slightly more), but should be a fraction of the runtime cost.

While #roufamatic did show use of the arguments keyword and #Ken showed a great example of an object for usage I feel neither truly addressed what is going on in this instance and may confuse future readers or instill a bad practice as not explicitly stating a function/method is intended to take a variable amount of arguments/parameters.
function varyArg () {
return arguments[0] + arguments[1];
}
When another developer is looking through your code is it very easy to assume this function does not take parameters. Especially if that developer is not privy to the arguments keyword. Because of this it is a good idea to follow a style guideline and be consistent. I will be using Google's for all examples.
Let's explicitly state the same function has variable parameters:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Object parameter VS var_args
There may be times when an object is needed as it is the only approved and considered best practice method of an data map. Associative arrays are frowned upon and discouraged.
SIDENOTE: The arguments keyword actually returns back an object using numbers as the key. The prototypal inheritance is also the object family. See end of answer for proper array usage in JS
In this case we can explicitly state this also. Note: this naming convention is not provided by Google but is an example of explicit declaration of a param's type. This is important if you are looking to create a more strict typed pattern in your code.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Which one to choose?
This depends on your function's and program's needs. If for instance you are simply looking to return a value base on an iterative process across all arguments passed then most certainly stick with the arguments keyword. If you need definition to your arguments and mapping of the data then the object method is the way to go. Let's look at two examples and then we're done!
Arguments usage
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
Object usage
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Accessing an array instead of an object ("...args" The rest parameter)
As mentioned up top of the answer the arguments keyword actually returns an object. Because of this any method you want to use for an array will have to be called. An example of this:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
To avoid this use the rest parameter:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5

Use the arguments object when inside the function to have access to all arguments passed in.

Be aware that passing an Object with named properties as Ken suggested adds the cost of allocating and releasing the temporary object to every call. Passing normal arguments by value or reference will generally be the most efficient. For many applications though the performance is not critical but for some it can be.

Use array and then you can use how many parameters you need. For example, calculate the average of the number elements of an array:
function fncAverage(sample) {
var lenghtSample = sample.length;
var elementsSum = 0;
for (var i = 0; i < lenghtSample; i++) {
elementsSum = Number(elementsSum) + Number(sample[i]);
}
average = elementsSum / lenghtSample
return (average);
}
console.log(fncAverage([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); // results 5.5
let mySample = [10, 20, 30, 40];
console.log(fncAverage(mySample)); // results 25
//try your own arrays of numbers

Related

array.splice = what does it means?

I would like to understand the meaning of that code fragment. "saveTo" is a array, the programmer assigned a function() to the splice method. I don't understand what does it mean. Is that a override? What is the meaning of the return argument?, and why the function takes no argument while splice requires 2 or more arguments?
saveTo.splice = function() {
if (saveTo.length == 1) {
$("#send").prop("disabled", true);
}
return Array.prototype.splice.apply(this, arguments);
};
Javascript lets you re-assign methods at runtime. In this case, what the programmer was doing is reassigning splice on this specific instance of an array in order to call a jQuery method. Beyond that, it works in exactly the same way as the existing splice as they are calling return Array.prototype.splice.apply(this, arguments); - meaning that this method just passes on whatever arguments are passed to it.
Here's a demo:
var myArray = [1,2,3,4];
console.log("Splice before re-assing: ", myArray.splice(1,1));
// reset it.
myArray = [1,2,3,4];
myArray.splice = function(){
console.log("From inside new splice function");
return Array.prototype.splice.apply(this, arguments);
}
console.log("Splice after re-assiging: ", myArray.splice(1,1));
Whether this is a good thing to do is debatable. It breaks a few principles of programming.
The programmer that wrote this code knew that some other part of the program is calling splice on this array, and he wanted to attach an event to that, in order to update the user interface (hence the call to jQuery).
This is commonly called "Monkey Patching". You can read about it at https://www.audero.it/blog/2016/12/05/monkey-patching-javascript/
This is not a good pratice as it obfuscate what is happening: no programmer would expect that calling a data manipulation function has side-effects somewhere else.
You can run this sample to understand how it works:
const myArray = [];
// Patch push method only for this instance of array.
myArray.push = function() {
// log event
console.log('myArray.push was called with the following arguments', arguments);
// Call the original push function with the provided arguments.
return Array.prototype.push.apply(this, arguments);
}
myArray.push(1);
You can also patch methods for all instances of a given class:
// Patch push method on all arrays
const originalPush = Array.prototype.push;
Array.prototype.push = function() {
// log event
console.log('.push was called with the following arguments', arguments);
// Call the original push function with the provided arguments.
return originalPush.apply(this, arguments);
}
const myArray = [];
myArray.push(1);
As for your question about the arguments, in javascript all functions can access the arguments array-like object that contains the arguments the function was called with, which does not depend on which arguments are specified in the original declaration.
function doSomething(arg1) {
console.log(arguments[2]);
}
doSomething(1, 2, 3); // outputs "3"
Here is the MDN documentation about it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
Note that there is a better way to extend arrays in ES6:
class CustomArray extends Array {
splice(...args) {
if(this.length === 1) {
$("#send").prop("disabled", true);
}
super.splice(...args);
}
}
Now that there are other ways to change the arrays length, .length, .pop, .shift, etc. so those should be overriden as well. However then it is still questionable wether the code calling those methods should not just cause the side effect.
What this does is it adds some checks for specifically saveTo.splice. If you call anyOtherArray.splice, then it'll just be evaluated as per normal. The reason it takes no arguments is because Array.prototype.splice takes arguments, and also the calling context of saveTo, as well as the array-like objects arguments, representing all the arguments passed to saveTo.splice. So it's just adding a little bit of extra code based on a specific condition - other than that, there's no difference to the native splice.
1) Yes, the programmer has overridden splice method, its not recommended
2) return statement is nothing but calls Array.prototype.splice(the original method).
3) Yes, splice requires arguments, but in JS, you may not define them as function params. You get the passed parameters as an array like object arguments inside your functions,
if you look closely, they call Array.prototype.splice with this and arguments object.
Okay, let's dissect this piece by piece.
saveTo.splice = function() {
if (saveTo.length == 1) {
$("#send").prop("disabled", true);
}
return Array.prototype.splice.apply(this, arguments);
};
As we all know that in JavaScript functions are first class objects, so if we have an object let's say saveTo something like this:
const saveTo = {};
Then we can assign a function to one of its properties like :
saveTo.splice = function() {
};
or something like this to:
const saveTo = {
splice: function() {
}
};
With that out of the way, you are just calling the Array#prototype#splice method to create a shallow copy out of the array and passing it an iterable to it.
So in total you have overridden the native Array#prototype#splice to fit your requirement.

Array.of() not working as specified in es6?

According to documentation here, Array.of() is an alternative to new Array() that lets you create an array literal at run-time even if it's only got one element (a case where new Array() breaks down). I like that, and have replaced most new() calls on my custom Array subclass with .of(), but since converting I am now finding errors when I try certain things.
The link claims that .of() is equivalent to this:
Array.of = function() { return Array.prototype.slice.call(arguments); }
To check if that's true, I wrote this test to compare the real of() with that polyfill:
Array.of_polyfill = function( ...args ) // Fake of().
{
console.log( args );
return Array.prototype.slice.call( args );
}
class A extends Array // So we can peek inside what the real of() is doing.
{
constructor( ...args ) // Using of() on an "A" calls this constructor.
{
console.log( args );
return Array.prototype.slice.call( args );
}
}
var a1 = A.of ( 5,6,7,8 );
var a2 = A.of_polyfill( 5,6,7,8 );
Both a1 and a2 ultimately contain the correct value [5,6,7,8], but internally working with the two lines is inconsistent, as shown in the console log:
[4]
(4) [5, 6, 7, 8]
From the first line there, calling .of() did not result in the whole literal being in scope, but just [4], as if internally it's calling the A constructor to preallocate four slots, which is not something the polyfill mentions it does.
I care about the internal behavior because one of the main suggested uses of of() is custom Array subclasses like my A above, to allow me to specify array literals of my new type. To that end my A constructor should be able to do manual stuff with the literal (the arguments that were passed in) but it just can't access it due to the above. Is there some other way that gives me access?
Is that suggested polyfill for of() accurate or am I misunderstanding some aspect of JavaScript and constructors?
Minor point... Array.of lets you create an Array, not an "Array literal". The "literal" refers to the syntax that lets you describe and create an array with its initializing data if any, like var a = [1, 2, 3].
Ultimately, the docs make no claim of complete equivalence of the polyfill. MDN is a wiki, so if the polyfill can be improved, then anyone is welcome to contribute changes. Keep in mind though that it will be expected to work in ES5 and lower, so approaching the full subclassing behavior will be much more work.
So we are mixing multiple things in the question. You are using spread operators where you shouldn't, and there seems to be a misunderstanding about what native code is. Array.of is a static function; creating a constructor doesn't mimic its' behaviour. You can however override the static method and use the spread operator. In this case, it would be
class B extends Array {
static of(...args) {
return args;
}
}
Or using arguments
class A extends Array {
static of() {
return Array.prototype.slice.call(arguments);
}
}
Or just
class A extends Array {
static of() {
return Array.from(arguments);
}
}
Again, your "polyfill" does too much. By using the spread operator, you'll already get an array. This would suffice:
Array.of_polyfill = function (...args) {
return args;
};
Below you'll get three times the same array:
Array.of_polyfill = function (...args) {
return args;
};
class A extends Array {
static of() {
return Array.prototype.slice.call(arguments);
}
}
class B extends Array {
static of(...args) {
return args;
}
}
var a1 = A.of(5, 6, 7, 8);
var a2 = A.of_polyfill(5, 6, 7, 8);
var b = B.of(5,6,7,8);
console.log(a1);
console.log(a2);
console.log(b);
Here's the function declaration in ecmascript6:
/**
#param {...null} items
#static
#return {Array}
*/
Array.of = function(items) {};
You're assuming that your constructor function is called with the arguments that you pass to A.of. That's wrong.
Let's take a look at the specification of Array.of:
Let len be the actual number of arguments passed to this function.
Let items be the List of arguments passed to this function.
Let C be the this value.
If IsConstructor(C) is true, then
a. Let A be ? Construct(C, « len »).
Else,
a. Let A be ? ArrayCreate(len).
[...]
In our case, "C" is A, the class that you defined, which is a constructor. A new instance of A is created, the constructor is called with "len", the number of arguments that we passed to Array.of.
Normally, the constructor would be Array, so Array(len) would be called. Here, A(4) is called. Thus, ...args is [4].
After that, the algorithm will fill the newly constructed array with the correct values.
That means that the results of Array.of and Array.prototype.slice.call are equivalent, but not the way they work internally.
after some tests, it seems that the actual implementation of Array.of() is something like this:
Array.of = function() {
//check wether `this` is a constructor, otherwise fall back to the `Array` constructor
//maybe there's a better way to determine wether `this` is a constructor _before_ calling it.
var constructor = typeof this === "function" && "prototype" in this? this: Array,
result = new constructor(arguments.length);
for(var i=0; i<arguments.length; ++i)
//FF and Chrome use defineProperty()
Object.defineProperty(result, i, {
value: arguments[i],
writable: true,
enumerable: true,
configurable: true
})
//Edge simply assigns the values
//result[i] = arguments[i];
//didn't test IE, Opera, Safari or any mobile browser
//and again, setting the length after the items have been defined
result.length = arguments.length;
return result;
}
Why just "something" - didn't you read the spec?
No, this was driven/deduced by the actual behaviour in the browser. And only "something like", because I might have missed something.
Especially the part with determining wether this is an actual constructor is something I'm not entirely satisfied with. It may produce a false match (and then throw) if you take an arrow function and manually add a property named prototype; but that kind of hacks should be pretty rare.
"After some tests" - what did you test?
how the function behaves in different environments,
attached to functions, to consturctor functions, to functions that ain't constructors, to general objects,
wether there's a difference between attaching it to some Object, or calling it with Function#call,
wether and what arguments are passed to the functions constuctor.
how it behaves if constructor and constructor.prototype.constructor are not the same,
wether it needs Array in the prototype-chain (to fall back to the Array-constructor),
Basically how it determines the constructor function to initialize the returned object
what happens if I predefine the indices and the length-proeprty (it throws an error if the property ain't configurable:true, but only in FF and Chrome)

Understanding Function.prototype.apply method in chain constructor

I don't know how to ask this question. i think it would be better understandable using example:(this example i have taken from MDN)
Function.prototype.construct = function (aArgs) {
var oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};
function MyConstructor() {
for (var nProp = 0; nProp < arguments.length; nProp++) {
this['property' + nProp] = arguments[nProp];
}
}
var myArray = [4, 'Hello world!', false];
i can create object using two way:
var obj1=new MyConstructor(4,'Hello world!', false);
var myInstance = MyConstructor.construct(myArray);
what is the difference between creating object using these two way ? why we use apply method to create object in chain constructor and what is advantage of creating object using 2nd way ?
what is the difference between creating object using these two way ?
Fundamentally, the difference is whether you give the arguments as discrete arguments (#1) or as an array (#2). Also, the first way is standard, normal JavaScript; the second requires that you extend the Function prototype.
why we use apply method to create object in chain constructor
So that the arguments are passed to the constructor function as though they'd been provided as discrete arguments.
This is fairly complex code, so a simpler example of what Function#apply does is probably useful. Let's take a boring function:
function foo(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
}
Now, let's call that with discrete arguments:
foo(1, 2, 3);
...which gives us
1
2
3
Now, let's use apply (ignore the null for now):
var a = [1, 2, 3];
foo.apply(null, a);
We get the same result:
1
2
3
Function#apply accepts the value to use as this as the first argument, and the arguments for the call as an array (or array-like object) in the second argument, and calls the function with that this value and arguments.
and what is advantage of creating object using 2nd way ?
Just that you can use an array for the arguments, rather than listing them individually.

Accessing parameters when the function expects none Javascript

I am writing a Javascript function to count the number of instances of an element in an unsorted array. It has a method signature like this
Array.prototype.numberOfOccurrences = function() {
}
Here is an example of expected behavior
var arr = [4, 0, 4];
Test.assertEquals(arr.numberOfOccurrences(4), 2);
My problem is that I don't know how to access the elements in the array. The function doesn't take any parameters so how do I reference the array being passed in?
Note: The instructions aren't very descriptive for this kata on code wars and adding a parameter to the function returns some error unexpected token.
Inside the function you are creating into the Array.prototype you can access all the prototype functions through the "this" keyword.
Meaning you can access the array items using numeric properties like this[0] or this[1] to a access the first and second item respectively.
You can also call functions which allows you to iterate over each item on the array, such as: forEach, filter, etc.
Please refer this page to see everything you can do with the array prototype:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype
Lastly don't forget that the JavaScript implementation varies on each browser, so a function that works on Chrome, might not work on InternetExplorer, always confirm on caniuse.com If the function you are used has the same implementation on your targets browsers.
Cheers.
Whether you should extend javascript base objects aside, this is your friend:
Array.prototype.numberOfOccurrences = function(valueToFind) {
return this.filter(function(item) {
return item === valueToFind;
}).length;
}
var a = [1,2,3,3,3,3];
console.log(a.numberOfOccurrences(3)); //4
As noted above, if you're not able to change the function signature for whatever reason you can specify it as follows:
Array.prototype.numberOfOccurrences = function() {
var valueToFind = arguments[0];
...
}
I would recommend adding the parameter to the function for clarities sake. Seems counter intuitive for a function like numberOfOccurences to not take in a parameter - numberOfOccurences of what?
Fiddle: http://jsfiddle.net/KyleMuir/g82b3f98/
You might try using the locally available variable 'arguments' inside of the function. So for example, your code might look like thsi:
Array.prototype.numberOfOccurrences = function() {
var args = arguments || {};
var testArray, testCheck;
if (args[0] && Array.isArray(args[0]) {
// do something with the array that was the first argument, like:
testArray = args[0];
testCheck = testArray.indexOf(args[1]);
return testCheck;
} else {
// do what you want to do if the function doesn't receive any arguments or the first argument
// received isn't an array.
}
}
'arguments' is always available to you inside a declared function.

Is it not possible to set arguments that have not been provided, using arguments property

I was testing things. And discovered that i could not set arguments if i have not provided it.
Using arguments[1] etc.
Example:
function abc (a,b) {
arguments[1] = 'new value';
console.log(b);
}
abc('a');
It won't work.
I know i could set value like if (b=='undefined') b='default'; but why i can't like this. In other words this behavior is unexpected, isn't it?
On the other hand, if you do provide argument it will get changed!
calling function like this will output new value
abc('a','b');
is there a solution, if you wanted to set value using arguments[2] and pass argument when calling function.
after more testing it seems: b doesnt get connected with arguments[1] if not called.
My understanding is argument is dynamic whose length is set by number of arguments / parameters provided to the function.
In first case, you have provided only one parameter so size of argument is 1 and hence argument[1] should be out of bound, while in second case, you have argument of length 2 so you can change either parameter value by using its index.
After posting a terribly wrong answer, I took a look at the ECMA Spec and here is in code, what JavaScript does when the arguments object will be created:
function abc () {
var names = ["a", "b"]; //as normally provided in the function declaration: function (a, b)
var a, b;
var args = {};
var mappedNames = [];
args.length = arguments.length;
var index = args.length - 1;
//this is the crucial part. This loop adds properties to the arguments object
//and creates getter and setter functions to bind the arguments properties to the local variables
//BUT: the loop only runs for the arguments that are actually passed.
while (index >= 0) {
var val = arguments[index];
if (index < names.length) {
var name = names[index];
if (mappedNames.indexOf(name) === -1) {
mappedNames.push(name);
var g = MakeArgGetter(name);
var p = MakeArgSetter(name);
Object.defineProperty(args, index.toString(), {get : g, set : p, configurable : true});
}
}
args[index.toString()] = val;
index--;
}
function MakeArgGetter(name) {
return function zz(){
return eval(name);
};
}
function MakeArgSetter(name) {
return function tt(value) {
eval(name + " = value;");
};
}
console.log(args[0]); //ab
args[0] = "hello";
args[1] = "hello";
console.log(a); //hello
console.log(b); //undefined
}
abc('ab');
Note, that there is some more going on in the Spec and I simplyfied it here and there, but this is essentially what is happening.
What are you trying to achieve by this?
If you want to have "dynamic arguments" like abc('a) and abc('a', 'b') are both valid, but the first will set the missing argument to a default value, you either have to check for the arguments length and/or for all arguments values.
Suppose the following: abc('a', null) is given, what then? - depends on logic, can be good but can also be bad.
Given this, checking the argument vector isn't smarter but more cryptic and having something like if (b=='undefined') b='default' much straighter and better to understand.
TL;DR: Not possible per ECMA spec since arguments is binded to only formal parameters that match the provided arguments. Its recommended to only reference arguments and not alter it.
Examples: http://jsfiddle.net/MattLo/73WfA/2/
About Arguments
The non-strict arguments object is a bidirectional and mapped object to FormalParameterList, which is a list generated based on the number of provided arguments that map to defined parameters in the target function defintion/expression.
When control enters an execution context for function code, an arguments object is created unless (as specified in 10.5) the identifier arguments occurs as an Identifier in the function’s FormalParameterList or occurs as the Identifier of a VariableDeclaration or FunctionDeclaration contained in the function code. ECMA 5.1 spec (as of 03/26/2014)
arguments to variables / variables to arguments
Argument-to-variable mappings exist only internally when the method is invoked. Mappings are immutable and are created when a target function is invoked, per instance. The update bindings between the two is also disabled when the use strict flag is available within the scope of the function. arguments becomes strictly a reference and no longer a way to update parameters.
For non-strict mode functions the array index (defined in 15.4) named 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. ECMA 5.1 spec (as of 03/26/2014)
What about length?
arguments.length can be an indicator initially to determine how many formal parameters were met but it's unsafe since arguments can be changed without length ever updating automatically. length doesn't update because it's not a real array and therefore doesn't adhere to the Array spec.

Categories

Resources