📜 ⬆️ ⬇️

JavaScript magic: arguments

arguments are a very specific thing, about which novices and even amateurs know only that this is “like an array, but some kind of wrong”. In fact, it has a number of interesting features. I suggest in the topic to fantasize on TypeHinting, the default arguments and any other.
 (function (foo, bar) { console.log(typeof arguments); // ? arguments[0] = 42; console.log(foo); // ? })(10, 20); 


And also I will show an interesting idea-library.
 function test (foo, bar) { Args(arguments).defaults(100, 100); return [foo, bar]; }; test( ); // 100, 100 test(15 ); // 15, 100 test(21, 42); // 21, 42 



First of all, I would like to note that many of the ideas expressed in the topic are quite controversial. I myself am not sure that I will use them and do not advise the use of newcomers.
')

What are arguments


This is a hash. Normal hash, as var object = {}
 (function () { console.log( typeof arguments, // object Object.getPrototypeOf(arguments) == Object.prototype // true ) })(); 


Making an array of it is simple:
 var array = Array.prototype.slice.call(arguments, 0); //  ,   : var array = [].slice.call(arguments, 0); 


We call the slice method of the Array prototype on behalf of arguments .

What is in the arguments


arguments.length arguments.length - the number of arguments passed to the function.
 var count = function () { console.log(arguments.length); }; count(); // 0 count(first, second); // 2 


Do not forget that each function also has a length property, which indicates how many elements are declared in its header:

 function one (foo) {}; function three (foo, bar, qux) {}; console.log( one.length); // 1 console.log(three.length); // 3 


arguments.callee arguments.callee - reference to the function itself.

 function foo () { console.log(arguments.callee === foo); // true } 


In this way, you can check whether the correct number of elements has been transmitted or not:

 function test (foo, bar, qux) { return arguments.callee.length === arguments.length; } test(1); // false test(1,2,3); // true 


Arguments in arguments


The arguments also contains a list of arguments passed.
 function test (foo, bar) { console.log(foo, bar); // 'a', 'b' console.log(arguments[0], arguments[1]); // 'a', 'b' } test('a', 'b'); 


Now to the interesting. Many do not know that the arguments object actually contains references, not values, and is closely related to the arguments:
 (function (foo) { arguments[0] = 42; console.log(foo); // 42! foo = 20; console.log(arguments[0]); // 20 })(5); 


At the same time, the connection is quite strong:

 function foo (qux) { change(arguments); return qux; }; function change(a) { a[0] = 42; } foo(10); // 42 


What can be obtained from this?


In many programming languages ​​there are “variables by default”. For example, php:
 function ($foo = 30, $bar = 'test') { var_dump($foo); var_dump($bar); } 


In javascript it will look something like this:
 function (foo, bar) { if (typeof foo === 'undefined') foo = 30; if (typeof bar === 'undefined') bar = 'test'; console.log(foo, bar); } 


Knowing the features of arguments you can create a beautiful interface:
 function test(foo, bar) { Args(arguments).defaults(30, 'test'); console.log(foo, bar) } test(); // 30, 'test' 


Using this code:
 function Args (args) { if (this instanceof Args) { this.args = args; } else { //     new,    ,      return new Args(args); } }; Args.prototype = { defaults: function () { var defaults = arguments; for (var i = defaults.length; i--;) { if (typeof args[i] === 'undefined') args[i] = defaults[i]; } return this; } }; 


Similarly, you can do automatic type casting:

 function test(foo) { Args(arguments) .defaults(10) .cast(Number); console.log(foo) } test('0100'); // 100 


Or Type Hinting:

 function test(foo, bar) { Args(arguments).types(Foo, Bar); // code } test(new Foo(), new Bar()); test(1, 2); // Error 


From interesting ideas - the message that all arguments are required:

 function test (foo, bar, qux) { Args(arguments).allRequired(); } test(1,2,3); // success test(1,2); // Error: 3 args required, 2 given 


Conclusion


I designed all these ideas and possibilities (and even more) into the library - Args.js.
I agree that some things (like TypeHinting) do not quite fit the ideology of the language. At the same time, for example, defaults is a very handy thing, IMHO.
So far this is a prototype and, before you use it, be sure that you really need it, and not that you just try to make something like C # out of a beautiful language.
I propose to discuss, criticize the code, find a couple of bugs and commit a few lines of code)

Args.js



Unfortunately, because of the bug in three popular browsers (IE, Fx , Opera), I could not achieve the desired effect , the most delicious things worked only in Chrome (well, at least in node.js will work)). Hope to solve this problem together.

UPD : In the comments, we found out that this is Chrome’s bug, but how pleasant it is! Thank you jamayka

Source: https://habr.com/ru/post/117868/


All Articles