Javascript function argument length

Магия JavaScript: arguments

arguments — очень специфическая штука, о которой новички и даже любители знают только то, что это «вроде массив, но какой-то неправильный». На самом деле, у него есть ряд интересных особенностей. Предлагаю в топике пофантазировать на тему TypeHinting, аргументов по-умолчанию и всякого другого.

А также покажу интересную идею-библиотеку

function test (foo, bar) < Args(arguments).defaults(100, 100); return [foo, bar]; >; test( ); // 100, 100 test(15 ); // 15, 100 test(21, 42); // 21, 42 

В первую очередь хотел бы заметить, что множество идей высказанных в топике являются достаточно спорными. Я сам не уверен, что буду ими пользоваться и не советую пользоваться новичкам.

Что такое arguments

Сделать из него массив просто:

var array = Array.prototype.slice.call(arguments, 0); // или покороче, но менее производительно: var array = [].slice.call(arguments, 0); 

Мы вызываем метод slice прототипа Array от лица arguments .

Что есть в arguments

var count = function () < console.log(arguments.length); >; count(); // 0 count(first, second); // 2 

Не забывайте, что у каждой функции тоже есть свойство length , которое указывает на то, сколько элементов объявлено в её заголовке:

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

arguments.callee — ссылка на саму функцию.

Читайте также:  Python classes super init

Таким образом можно проверить, передано ли правильное количество элементов, или нет:

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

Аргументы в arguments

function test (foo, bar) < console.log(foo, bar); // 'a', 'b' console.log(arguments[0], arguments[1]); // 'a', 'b' >test('a', 'b'); 

Теперь к интересному. Многие не знают, что объект arguments — содержит на самом деле ссылки, а не значения, и тесно связан с аргументами:

При этом связь достаточно крепкая:

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

Что из этого можно получить?

function ($foo = 30, $bar = 'test')

В javascript оно будет выглядеть как-то так:

Зная особенности arguments можно создать красивый интерфейс:

function test(foo, bar) < Args(arguments).defaults(30, 'test'); console.log(foo, bar) >test(); // 30, 'test' 
 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; > >; 

Аналогично можно сделать автоматическое приведение типов:

function test(foo) < Args(arguments) .defaults(10) .cast(Number); console.log(foo) >test('0100'); // 100 
function test(foo, bar) < Args(arguments).types(Foo, Bar); // code >test(new Foo(), new Bar()); test(1, 2); // Error 

Из интересных идей — сообщение, что все аргументы обязательны:

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

Заключение

Все эти идеи и возможности (и даже больше) я оформил в библиотеку — Args.js.
Согласен, что кое-какие вещи (как TypeHinting) не совсем подходят к идеологии языка. В то же время например defaults — очень удобная штука, имхо.
Пока что это прототип и, перед тем как вы будете его использовать — будьте уверены, что оно вам действительно нужно, а не что вы просто стараетесь из прекрасного языка сделать что-то похожее на C#.
Предлагаю обсудить, покритиковать код, найти пару багов и закоммитить несколько строк кода)

Args.js

К сожалению, из-за бага в трёх популярных браузерах(IE, Fx, Opera) я не смог добиться желаемого эффекта, полноценно самое вкусное заработало только в Chrome (ну по крайней мере в node.js работать будет)). Надеюсь, решим эту проблему вместе.

UPD: В комментах выяснили, что таки это бага Хрома, но, зато, какая приятная! Спасибо jamayka

Источник

Function: length

The length data property of a Function instance indicates the number of parameters expected by the function.

Try it

Value

Property attributes of Function: length
Writable no
Enumerable no
Configurable yes

Description

A Function object’s length property indicates how many arguments the function expects, i.e. the number of formal parameters. This number excludes the rest parameter and only includes parameters before the first one with a default value. By contrast, arguments.length is local to a function and provides the number of arguments actually passed to the function.

The Function constructor is itself a Function object. Its length data property has a value of 1 .

Due to historical reasons, Function.prototype is a callable itself. The length property of Function.prototype has a value of 0 .

Examples

Using function length

.log(Function.length); // 1 console.log((() => >).length); // 0 console.log(((a) => >).length); // 1 console.log(((a, b) => >).length); // 2 etc. console.log(((. args) => >).length); // 0, rest parameter is not counted console.log(((a, b = 1, c) => >).length); // 1, only parameters before the first one with // a default value are counted 

Specifications

Browser compatibility

BCD tables only load in the browser

See also

Found a content problem with this page?

This page was last modified on Feb 21, 2023 by MDN contributors.

Your blueprint for a better internet.

Источник

The arguments object

arguments is an array-like object accessible inside functions that contains the values of the arguments passed to that function.

Try it

Description

Note: In modern code, rest parameters should be preferred.

The arguments object is a local variable available within all non-arrow functions. You can refer to a function’s arguments inside that function by using its arguments object. It has entries for each argument the function was called with, with the first entry’s index at 0 .

For example, if a function is passed 3 arguments, you can access them as follows:

[0]; // first argument arguments[1]; // second argument arguments[2]; // third argument 

The arguments object is useful for functions called with more arguments than they are formally declared to accept, called variadic functions, such as Math.min() . This example function accepts any number of string arguments and returns the longest one:

function longestString()  let longest = ""; for (let i = 0; i  arguments.length; i++)  if (arguments[i].length > longest.length)  longest = arguments[i]; > > return longest; > 

You can use arguments.length to count how many arguments the function was called with. If you instead want to count how many parameters a function is declared to accept, inspect that function’s length property.

Assigning to indices

Each argument index can also be set or reassigned:

Non-strict functions that only has simple parameters (that is, no rest, default, or destructured parameters) will sync the new value of parameters with the arguments object, and vice versa:

function func(a)  arguments[0] = 99; // updating arguments[0] also updates a console.log(a); > func(10); // 99 function func2(a)  a = 99; // updating a also updates arguments[0] console.log(arguments[0]); > func2(10); // 99 

Non-strict functions that are passed rest, default, or destructured parameters will not sync new values assigned to parameters in the function body with the arguments object. Instead, the arguments object in non-strict functions with complex parameters will always reflect the values passed to the function when the function was called.

function funcWithDefault(a = 55)  arguments[0] = 99; // updating arguments[0] does not also update a console.log(a); > funcWithDefault(10); // 10 function funcWithDefault2(a = 55)  a = 99; // updating a does not also update arguments[0] console.log(arguments[0]); > funcWithDefault2(10); // 10 // An untracked default parameter function funcWithDefault3(a = 55)  console.log(arguments[0]); console.log(arguments.length); > funcWithDefault3(); // undefined; 0 

This is the same behavior exhibited by all strict-mode functions, regardless of the type of parameters they are passed. That is, assigning new values to parameters in the body of the function never affects the arguments object, nor will assigning new values to the arguments indices affect the value of parameters, even when the function only has simple parameters.

Note: You cannot write a «use strict»; directive in the body of a function definition that accepts rest, default, or destructured parameters. Doing so will throw a syntax error.

arguments is an array-like object

arguments is an array-like object, which means that arguments has a length property and properties indexed from zero, but it doesn’t have Array ‘s built-in methods like forEach() or map() . However, it can be converted to a real Array , using one of slice() , Array.from() , or spread syntax.

const args = Array.prototype.slice.call(arguments); // or const args = Array.from(arguments); // or const args = [. arguments]; 

For common use cases, using it as an array-like object is sufficient, since it both is iterable and has length and number indices. For example, Function.prototype.apply() accepts array-like objects.

function midpoint()  return ( (Math.min.apply(null, arguments) + Math.max.apply(null, arguments)) / 2 ); > console.log(midpoint(3, 1, 4, 1, 5)); // 3 

Properties

Reference to the currently executing function that the arguments belong to. Forbidden in strict mode.

The number of arguments that were passed to the function.

Returns a new Array iterator object that contains the values for each index in arguments .

Examples

Defining a function that concatenates several strings

This example defines a function that concatenates several strings. The function’s only formal argument is a string containing the characters that separate the items to concatenate.

function myConcat(separator)  const args = Array.prototype.slice.call(arguments, 1); return args.join(separator); > 

You can pass as many arguments as you like to this function. It returns a string list using each argument in the list:

myConcat(", ", "red", "orange", "blue"); // "red, orange, blue" myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // "elephant; giraffe; lion; cheetah" myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley"); // "sage. basil. oregano. pepper. parsley" 

Defining a function that creates HTML lists

This example defines a function that creates a string containing HTML for a list. The only formal argument for the function is a string that is «u» if the list is to be unordered (bulleted), or «o» if the list is to be ordered (numbered). The function is defined as follows:

You can pass any number of arguments to this function, and it adds each argument as a list item to a list of the type indicated. For example:

Using typeof with arguments

The typeof operator returns ‘object’ when used with arguments

.log(typeof arguments); // 'object' 

The type of individual arguments can be determined by indexing arguments :

.log(typeof arguments[0]); // returns the type of the first argument 

Specifications

Browser compatibility

BCD tables only load in the browser

See also

Found a content problem with this page?

This page was last modified on Apr 5, 2023 by MDN contributors.

Your blueprint for a better internet.

MDN

Support

Our communities

Developers

Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.

Источник

arguments.length

The arguments.length data property contains the number of arguments passed to the function.

Value

Property attributes of arguments.length
Writable yes
Enumerable no
Configurable yes

Description

The arguments.length property provides the number of arguments actually passed to a function. This can be more or less than the defined parameter’s count (see Function.prototype.length ). For example, for the function below:

function func1(a, b, c)  console.log(arguments.length); > 

func1.length returns 3 , because func1 declares three formal parameters. However, func1(1, 2, 3, 4, 5) logs 5 , because func1 was called with five arguments. Similarly, func1(1) logs 1 , because func1 was called with one argument.

Examples

Using arguments.length

In this example, we define a function that can add two or more numbers together.

function adder(base /*, num1, …, numN */)  base = Number(base); for (let i = 1; i  arguments.length; i++)  base += Number(arguments[i]); > return base; > 

Specifications

Browser compatibility

BCD tables only load in the browser

See also

Found a content problem with this page?

This page was last modified on Apr 5, 2023 by MDN contributors.

Your blueprint for a better internet.

MDN

Support

Our communities

Developers

Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.

Источник

Оцените статью