параметры Параметры функции появляются в двух местах: в месте определения функции и в месте вызова функции. Параметры в этих двух местах различны.
Формальные параметры (формальные параметры).
Параметры, которые появляются в определении функции, можно рассматривать как заполнитель. Они не имеют данных и могут только ждать, пока функция не будет вызвана для получения переданных данных, поэтому они называются формальными параметрами или формальными. параметр для краткости.
Фактические параметры (фактические параметры).
Параметры, передаваемые при вызове функции, содержат реальные данные и будут использоваться кодом внутри функции, поэтому они называются фактическими параметрами или для краткости фактическими параметрами.
Разница и связь между формальными параметрами и фактическими параметрами
1) Переменные формальных параметров будут выделять память только при вызове функции. После завершения вызова память будет немедленно освобождена, поэтому переменные формальных параметров действительны только внутри функции и. нельзя использовать вне функции.
2) Фактическими параметрами могут быть константы, переменные, выражения, функции и т. д. Независимо от типа данных фактических параметров, они должны иметь определенные значения при вызове функций, чтобы передать эти значения формальным параметрам. , поэтому вам следует заранее использовать присваивание, ввод и другие методы, чтобы получить определенное значение для фактических параметров.
3) Фактические параметры и формальные параметры должны строго согласовываться по количеству, типу и порядку, иначе возникнет ошибка «несоответствие типов». Конечно, если автоматическое преобразование типов возможно или выполняется принудительное преобразование типов, фактический тип параметра также может отличаться от формального типа параметра.
4) Передача данных, происходящая при вызове функции, является односторонней, и значение фактического параметра можно передать только формальному параметру, но значение формального параметра нельзя передать фактическому параметру в обратном направлении. Другими словами, после завершения передачи данных фактические параметры и формальные параметры больше не связаны, поэтому во время вызова функции изменения значения формальных параметров не повлияют на фактические параметры.
5) Хотя формальные параметры и фактические параметры могут иметь одно и то же имя, они независимы друг от друга и не влияют друг на друга, поскольку фактические параметры действительны вне функции, а формальные параметры действительны внутри функции.
Функция формальных параметров и фактических параметров заключается в передаче данных. При вызове функции значение фактического параметра будет передано формальному параметру.
позволяет нам передавать данные, и переданные данные влияют на результаты выполнения функции, делая функцию более гибкой и многоразовой.
функция foo(a, b) { console.log([a, b]); } foo(1, 2); //
В этом примере вывода [1, 2] a
и b
являются локальными переменными в функции, и доступ к ним возможен только внутри функции. При вызове функции передаваемые данные будут сопоставляться в соответствии с позицией и присваиваться a
и b
соответственно.
При создании функции параметры, указанные в круглых скобках после function 函数名
называются формальными параметрами , при вызове функции параметры, передаваемые в круглых скобках после имени функции, называются фактическими параметрами . В приведенном выше примере a
и b
являются формальными параметрами, а переданные 1
и 2
— фактическими параметрами.
Поскольку формальные параметры объявлены переменными, их нельзя объявлять повторно с помощью let
и const
.
функция foo(a, b) { let a = 1; // Ошибка, объявлено a const b = 1 // Ошибка, объявлено b}
Все передачи функций в JavaScript передаются по значению, а не по ссылке. Так называемое значение относится к значению, хранящемуся непосредственно в переменной. Если объект передается в качестве параметра, то значение является ссылкой на объект, а не сам объект. На самом деле это процесс неявного присваивания, поэтому при передаче параметров в функцию он эквивалентен присвоению значений одной переменной другой переменной .
Исходное значение:
функция add(num) { вернуть число + 1; } пусть счет = 5; let result = add(count); // Процесс передачи параметров здесь можно рассматривать как num = count; консоль.журнал(счет); // 5 console.log(result); // 6
справочное значение:
function setName(obj) { obj.name = "Сяо Мин"; } пусть человек = {}; setName(person); // Процесс передачи параметров здесь можно рассматривать как obj = person; console.log(person); // {name: "Xiao Ming"}
Функции в JavaScript не определяют ни тип параметров, ни количество переданных параметров. Установка двух формальных параметров при определении функции не означает, что при вызове необходимо передать два параметра. При фактическом вызове, независимо от того, переданы ли один или три параметра, об ошибке не будет сообщено, даже если никакие параметры не будут переданы.
Во всех функциях (не стрелках) существует специальный объект, похожий на массив, с именем arguments
(не экземпляр Array
), который содержит копии всех фактических параметров. Мы можем использовать его для получения значений всех фактических параметров в соответствии с ними. к методу доступа к индексу значения массива, вы также можете получить доступ к его свойству arguments.length
, чтобы определить количество параметров, передаваемых при фактическом вызове функции.
Например:
функция foo(a, b) { console.log(аргументы[0]); console.log(аргументы[1]); console.log(arguments.length); } foo(10, 20); // Выводим последовательно 10, 20, 2.
В приведенном выше примере первый параметр функции foo() — a, а второй параметр — b, который можно получить отдельно через аргументы[. х]. То же значение. Поэтому вы можете даже объявить функцию, не задавая формальных параметров.
функция Фу() { console.log(аргументы[0]); console.log(аргументы[1]); } foo(10, 20); // Вывод 10 и 20 по порядку.
Видно, что формальные параметры функции JavaScript написаны только для удобства. Передача любого количества параметров не приведет к ошибке.
Еще следует отметить, что arguments
можно использовать вместе с формальными параметрами, а значения в объекте arguments
будут синхронизированы с соответствующими формальными параметрами. Например:
функция foo(a) { аргументы[0]++; console.log(а); } foo(10); // Вывод 11; //---------------------------------------- функция foo2(a) { а++; console.log(аргументы[0]); } foo2(10); // Вывод 11
Когда значение аргументов [0] или a изменяется, другое значение также изменяется. Это не означает, что они обращаются к одному и тому же адресу памяти, ведь мы передаем примитивное значение. Они по-прежнему находятся в памяти отдельно, но их значения синхронизируются благодаря внутренним механизмам.
Кроме того, если параметр отсутствует, значение этого формального параметра не будет синхронизировано с соответствующим значением в объекте arguments
. Например, в следующем примере передается только один параметр, поэтому в arguments
имеется только одно фактическое значение параметра. На данный момент, если для аргументов [1] в функции установлено определенное значение, это значение не будет синхронизировано. ко второму формальному параметру, например:
function foo(a,b) { аргументы[1] = 2; console.log(б); } foo(1); // Вывод не определен
В этом примере формальному параметру b не передается фактический параметр, и его значение по умолчанию будет undefined
. Но если:
foo(1, undefined); //
Когда вывод 2 передается вручную в undefined
, в массиве arguments
появится элемент со значением undefined
, который все еще можно синхронизировать со значением b.
В строгом режиме значения и формальные параметры в объекте arguments
больше не будут синхронизироваться. Конечно, если передаются ссылочные значения, они все равно будут влиять друг на друга, но это всего лишь характеристика ссылочных значений. Поэтому лучше всего не полагаться на этот механизм синхронизации при разработке, то есть не использовать формальные параметры и соответствующие им значения в объекте arguments
одновременно.
В стрелочных функциях нет аргументов
. Если функция определена с использованием синтаксиса стрелок, в функции нет объекта аргументов, и доступ к ней возможен только через определенные формальные параметры.
пусть foo = () => { console.log(аргументы[0]); }foo(); // Ошибка, аргументы не определены.
В некоторых случаях доступ к arguments
возможен:
function fn1(){. пусть fn2 = () => { console.log(аргументы[0]); } фн2(); }fn1(5);
Но эти arguments
не принадлежат стрелочной функции, а принадлежат внешней обычной функции. Когда доступ arguments
осуществляется в стрелочной функции, arguments
внешней функции находятся в цепочке области видимости.
Когда функция содержит несколько формальных параметров, вызов функции становится проблемой, потому что вам всегда нужно убедиться, что переданные параметры расположены в правильном положении. Как решить? ограничение порядка передачи параметров?
Поскольку атрибуты объекта неупорядочены, соответствующее значение определяется именем атрибута. Таким образом, вы можете передать объект и использовать его свойства в качестве реальных параметров, поэтому порядок параметров не имеет значения.
функция foo(obj) { console.log(obj.name, obj.sex, obj.age); } foo({ sex: 'Male', age: 18, name: 'Xiao Ming' }); // Сяо Мин - мужчина 18 лет
Если при вызове функции не указаны фактические параметры, используется значение по умолчанию формальных параметров undefined
.
Иногда нам нужно установить определенное значение по умолчанию. До ES6, когда явная установка значения по умолчанию не поддерживалась, мы могли использовать только обходной путь:
functionsayHi(name) {. имя = имя || 'все'; console.log('Привет' + имя + '!'); } SayHi(); // Выводим «Привет всем!»
и определяем, есть ли какое-либо присвоение, проверяя значение параметра. Хотя описанный выше метод прост, его недостаток заключается в том, что если входящий фактический параметр соответствует логическому значению false
, фактический параметр не будет работать. Если вам нужна большая точность, вы можете использовать оператор if
или троичное выражение, чтобы определить, равен ли параметр undefined
. Если да, это означает, что параметр отсутствует:
// оператор if определяет функцию SayHi(name) { если (имя === не определено) { имя = 'все'; } console.log('Привет' + имя + '!'); } //Функция оценки троичного выраженияsayHi(name) { имя = (имя! == неопределенное) ? имя: 'все'; console.log('Привет' + имя + '!'); }
ES6 гораздо удобнее, поскольку поддерживает явный способ установки значений по умолчанию, например так:
functionsayHi(name = 'everyone') { // При определении функции напрямую присваиваем значения формальным параметрам console.log( 'Привет' + имя + '!'); } SayHi(); // Вывод: «Всем привет!» SayHi('Тони'); // Выводим "Привет, Тони!" SayHi(undefined); // Вывод «Всем привет!»
Эти результаты показывают, что он также определяет, отсутствует ли параметр, по тому, равен ли он undefined
.
Значение по умолчанию может быть не только значением, оно также может быть любым допустимым выражением, даже вызовом функции:
functionsayHi(name = 'every'+'one') { console.log('Привет' + имя + '!'); } SayHi(); // Вывод: «Всем привет!» //----------------------------------------- функция Фу() { console.log('Вызов foo'); вернуть «Тони»; } функция SayHi(name = foo()) { console.log('Привет' + имя + '!'); } SayHi(); // Вывод 'вызов foo' // Вывод «Привет, Тони!» SayHi(undefined); // Вывод 'вызов foo' // Вывод «Привет, Тони!» SayHi('John'); // Вывод 'Привет, Джон!'
Вы можете видеть, что значение параметра функции по умолчанию будет оцениваться только тогда, когда функция вызывается, а значение параметра отсутствует или undefined
, и не будет оценивается при определении функции.
Обычно мы устанавливаем значения по умолчанию для параметров, чтобы мы могли соответствующим образом опустить параметры при вызове функции. Здесь следует отметить, что при наличии нескольких параметров, если параметр со значением по умолчанию не помещен в конец, он на самом деле невозможно пропустить.
функция fn(x = 1, y) { console.log([x, y]); } fn(); // вывод[1, не определено] фн(2); //выход[2, не определено] fn(, 2); // Ошибка, синтаксическая ошибка (пустые слоты, такие как массивы, здесь не поддерживаются) fn(undefined, 2); // Вывод [1, 2] (для удобства лучше передать 1!)
В приведенном выше примере значение по умолчанию для формального параметра x кажется бессмысленным. Поэтому параметры со значениями по умолчанию лучше всего ставить в конце:
функция fn(x, y = 2) { console.log([x, y]); } фн(); // вывод [не определено, 2] фн(1); //вывод[1, 2] fn(1, 1) //вывод[1, 1]Проблема с пропуском параметров
Когда для нескольких параметров установлены значения по умолчанию, проблема возникает снова. Вы не можете пропустить предыдущие параметры и передавать только фактические параметры последнему параметру.
функция fn(x, y = 2, z = 3) { console.log([x, y, z]); } fn(1, , 10) // Сообщить об ошибке
Ранее мы знали, что можем избежать ограничения порядка параметров, передавая объекты. Как реализовать значения параметров по умолчанию? Использование операторов ||
, if
или троичных выражений для оценки также является решением, но это кажется немного отсталым. Далее идут два других новых метода в ES6.
Значения параметров по умолчанию используются совместно с Object.assign().
функция fn(obj = {}) { пусть defaultObj = { х: не определено, й: 2, я: 3 } пусть результат = Object.assign(defaultObj, obj); console.log([result.x, result.y, result.z]); } fn() // вывод [не определено, 2, 3] fn({ x: 1, z: 10 }); // Вывод [1, 2, 10];
В приведенном выше примере в функции определен объект defaultObj
, а свойства в нем используются в качестве значений параметров по умолчанию. Затем используется Object.assagin() для объединения входящего объекта и объекта по умолчанию. Свойства в defaultObj будут такими же. Те же атрибуты obj переопределяются. Если в obj есть другие атрибуты, они будут назначены defaultObj. Здесь переменная используется для получения возвращенного объединенного объекта.
В то же время значение по умолчанию формального параметра obj
также установлено в пустой объект, чтобы предотвратить передачу параметров при вызове функции, поскольку это приведет к тому, что второй параметр, полученный Object.assign(), будет undefined
, что приводит к ошибке.
Значения параметров по умолчанию и назначения деструктуризации используются вместе.
При вызове функции сопоставление фактических и формальных параметров на самом деле представляет собой процесс неявного присваивания. Следовательно, передачу параметров также можно деконструировать и назначить:
функция fn({ x, y = 2, z = 3 }) { console.log([x, y, z]); } fn({}); // Вывод [не определено, 2, 3] fn({ x: 1, z: 10 }); // Вывод [1, 2, 10];
В этом примере используется только значение по умолчанию назначения деструктуризации объекта, а значение по умолчанию параметра функции не используется. Если при вызове функции не передаются никакие параметры, также будет сообщено об ошибке, поскольку это приведет к сбою назначения деструктуризации во время инициализации параметра, что эквивалентно выполнению такого кода, как {x, y = 2, z = 3} = undefined
.
Аналогичным образом вы можете использовать синтаксис значений параметров по умолчанию, чтобы установить объект деструктуризации по умолчанию для {x, y = 2, z = 3}
, чтобы функции без передачи параметров могли выполняться плавно:
функция fn({ x, y = 2, z = 3 } = {}) { console.log([x, y, z]); } fn() // вывод [не определено, 2, 3]
Здесь присутствуют двойные значения по умолчанию, что может немного сбить с толку. Поэтому используйте кусок псевдокода, чтобы объяснить описанный выше процесс инициализации параметров :
if(actual options=== {...}) { // if fn({...}); { х, у = 2, z = 3 } = {...}; } else if (фактический параметр === undefined ){ // if fn(); { х, у = 2, z = 3 } = {}; }
Есть одна деталь, которая требует особого внимания к двойным значениям по умолчанию, а именно разница между значением по умолчанию деструктурирующего назначения и значением по умолчанию параметра функции. См. следующий пример:
функция fn ({ x = 1 } = {}, { y } = { y: 2 }){ console.log(х, у); } фн(); // Вывод 1 2 fn({ x: 10 }, { y: 20 }); // Вывод 10 20 fn({},{}); // 1 не определено
В этой функции есть два набора параметров, использующих деструктурирующее присваивание. Кажется, что и x, и y имеют установленные значения по умолчанию. Хотя это две разные формы, результаты явно не одинаковы. Если переданный параметр равен {}
, y не получает значение по умолчанию 2. Почему? В сочетании с предыдущим примером псевдокода:
fn({ x: 10 }, { y: 20 }); // Во время инициализации: { x = 1 } = { x: 10 }, { y } = { y: 20 } fn({},{}); // Во время инициализации: { x = 1 } = {}, { y } = {}
Если переданный параметр равен {}
, параметр функции не отсутствует и undefined
, поэтому значение параметра функции по умолчанию не имеет никакого эффекта. В то же время нет соответствующих значений для x и y в {}
. 1, полученная с помощью x, является значением по умолчанию для деструктурирующего присваивания, а y не имеет значения по умолчанию для деструктурирующего присваивания, поэтому по умолчанию оно равно undefined
.
Область действия и временная мертвая зона значений параметров по умолчанию
Есть еще одна небольшая деталь: как только параметрам будут присвоены значения по умолчанию, они образуют собственную область действия (завернутую в (...)
), поэтому на переменные в теле функции нельзя ссылаться:
функция foo(a = b) { пусть б = 1; } foo(); // Ошибка, b не определен
Но эта область является временной. После инициализации параметров эта область больше не будет существовать.
Он также следует правилам обычных областей:
пусть б = 2; функция foo(a = b) { пусть б = 1; вернуть а; } Фу(); // 2
В приведенном выше примере существует глобальная переменная b, тогда формальный параметр a получит значение глобальной переменной b.
Конечно, если в области формального параметра есть формальный параметр b, он сначала получит текущую область действия:
пусть б = 2; функция foo(b = 3,a = b) { вернуть а; } Фу(); // 3
Установите значения по умолчанию для нескольких параметров, они будут инициализированы по порядку, следуя правилам «временной мертвой зоны», то есть предыдущие параметры не могут ссылаться на более поздние параметры:
функция foo(a = b, b = 2) { вернуть а + б; } foo(); // Ошибка, доступ к b невозможен до инициализации
остальные параметры
ES6 предоставляет синтаксис **оставшиеся параметры (остальные)** ( ...变量名
), который может собирать избыточные фактические параметры функции (то есть фактические параметры, которые не соответствуют формальным параметрам), чтобы не было нужно использовать объект arguments
. Понятно. Если формальный параметр используется с оператором ...
, он станет массивом, и в этот массив будут помещены избыточные фактические параметры.
Основное использование остальных параметров:
функция sum(a, ...values) { for (пусть значение значений) { а += значение; } вернуть а; } сумма(0, 1, 2, 3); // 6);
В приведенном выше примере во время инициализации параметра сначала выполняется сопоставление на основе позиции параметра, 0 присваивается a, а затем оставшиеся параметры 1, 2 и 3 будут помещены в значения массива.
Ниже приведен пример сравнения использования объектов arguments
и остальных параметров для получения параметров:
// Как написать аргументы function sortNumbers() { return Array.prototype.slice.call(arguments).sort(); } // Как записать остальные параметры const sortNumbers = (...numbers) => { вернуть числа.сортировать(); }
Видно, что остальные параметры записаны более лаконично. Хотя arguments
— это объект, подобный массиву, итерируемый объект, в конце концов, это не массив. Он не поддерживает методы массива. Когда мы используем arguments
, если мы хотим вызвать метод массива, мы должны сначала использовать Array.prototype.slice.call
чтобы преобразовать его в массив.
Остальные параметры отличаются от объекта arguments
. Они являются реальными экземплярами Array
и могут легко использовать метод массива. А стрелочные функции также поддерживают остальные параметры.
Кроме того, использование остальных параметров не влияет на функциональность объекта arguments
, оно все равно может отражать параметры, переданные при вызове функции.
Положение остальных параметров
Оставшийся параметр должен быть последним формальным параметром, иначе будет сообщено об ошибке.
// Функция сообщения об ошибках fn1(a, ...rest, b) { console.log([a, b, rest]); } //Правильный способ записи функции fn2(a, b, ...rest) { console.log([a, b, rest]); } fn2(1, 2, 3, 4) // Вывод [1, 2, [3, 4]]
Развернуть синтаксис
Раньше мы знали, как собирать избыточные параметры в массив, но иногда нам нужно сделать обратное, например, передать элементы массива в функцию отдельно вместо передачи массива, например:
функция сумма (... значения) { пусть сумма = 0; for (пусть значение значений) { сумма += значение; } сумма возврата; } пусть arr = [1, 2, 3, 4]; сумма(обр); // "01,2,3,4"
Функция в приведенном выше примере будет аккумулировать все переданные значения. Если мы передадим ее напрямую в массиве, мы не получим желаемый результат.
В примере, если передан массив, значение значений станет [[1, 2, 3, 4]]
, в результате чего в значениях массива будет только один элемент, а тип этого элемента — массив. . Тогда возвращаемое значение функции является результатом сложения значения 0
и массива [1, 2, 3, 4]
. Эти два типа неявно преобразуются в строки, а затем складываются вместе. Это эффект конкатенации.
Чтобы разобрать массив и передать его в функцию, сначала невозможно передать параметры по одному — sum(arr[0], arr[1], arr[2], arr[3]);
не всегда возможно Вы знаете, сколько элементов в массиве, а элементов в массиве может быть много. Передавать вручную неразумно.
Более целесообразно использовать метод apply():
sum.apply(ноль, обр.); // 10;
Но это еще не оптимальное решение, поэтому здесь наступает ключевой момент!
Новый синтаксис **expand (spread)** в ES6 может помочь нам справиться с этой ситуацией. Он также использует синтаксис ...变量名
. Хотя он аналогичен синтаксису остальных параметров, его цель совершенно противоположна. Он может разделить итерируемый объект на последовательность параметров, разделенных запятыми.
Когда функция вызывается, ее применение выглядит следующим образом:
сумма(...обр); // 10 // Эквивалент sum(1,2,3,4);
Его даже можно использовать с обычными значениями по желанию, нет ограничений на переднюю и заднюю позиции, и одновременно можно передавать несколько итерируемых объектов:
сумма(-1, ...обр); // 9 сумма(...обр, 5); // 15; сумма(-1, ...обр, 5 // 14); sum(-1, ...arr, ...[5, 6, 7]); // 27
Оператор расширения ...
для нас эквивалентен завершению операции передачи параметров вручную. Функция знает только, что фактически полученные параметры являются отдельными значениями и не будут иметь других эффектов из-за существования оператора расширения.
Хотя все приведенные выше примеры относятся к массивам, синтаксис расширения может делать больше. Другие итерируемые объекты, такие как строки и литеральные объекты, могут быть расширены. Для получения дополнительной информации см. → Синтаксис расширения.
Формальные параметры — это локальные переменные, объявленные в функции. Фактические параметры, передаваемые функции, будут присвоены формальным параметрам. Передача параметров функции на самом деле является процессом неявного присваивания.
Количество формальных параметров и фактических параметров может быть не равным:
● Формальные параметры, в которых отсутствуют фактические параметры, получат значение по умолчанию, undefined
.
● Дополнительные фактические параметры доступны через объект arguments
, за исключением стрелочных функций.
Вы можете передать объект так, чтобы порядок передачи параметров больше не был важен, и позволить свойствам объекта использоваться в качестве реальных параметров.
Значение параметра по умолчанию ES6 — значение по умолчанию будет получено только в том случае, если значение параметра отсутствует или undefined
при вызове функции.
● Параметры, задающие значения по умолчанию, можно опустить, только если они помещены в последнюю позицию.
● Значение по умолчанию формального параметра не может ссылаться на переменные в теле функции, но может ссылаться на предыдущие формальные параметры и внешние переменные.
● Реализация значений по умолчанию через Object.assign() или деструктурирование присваивания может сделать метод передачи параметров более гибким.
Основное различие между остальными параметрами и arguments
:
● Остальные параметры содержат только те фактические параметры, которые не имеют соответствующих формальных параметров, тогда как объект arguments
содержит все фактические параметры, передаваемые в функцию.
● Остальные параметры являются реальными экземплярами Array
, а arguments
— просто объектами, подобными массивам.
И остальные параметры, и синтаксис расширения используют оператор ...
в сценариях, связанных с функциями:
● Появляется в конце списка функциональных параметров и является оставшимся параметром.
● Встречается при вызове функций, это синтаксис расширения.
Выше приведена статья, в которой подробно объясняются параметры функций JavaScript. Для получения дополнительной информации обратите внимание на другие соответствующие статьи на китайском веб-сайте php!