Я считаю функцию именованных параметров в C # весьма полезной в некоторых случаях.
calculateBMI(70, height: 175);
Что я могу использовать, если я хочу это в JavaScript?
Чего я не хочу, так это:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Такой подход я уже использовал. Есть ли другой способ?
Я в порядке, используя любую библиотеку, чтобы сделать это.
javascript
function
optional-parameters
named-parameters
Робин Мабен
источник
источник
Function
может сделать существующий в JavaScript.Function
в Javascript не может изменить основной синтаксис JavascriptcalculateBMI(70, /*height:*/ 175);
, (2) предоставить объектcalculateBMI(70, {height: 175})
или (3) использовать константуconst height = 175; calculateBMI(70, height);
.Ответы:
ES2015 и позже
В ES2015 деструктуризация параметров может использоваться для моделирования именованных параметров. Требуется, чтобы вызывающая сторона передала объект, но вы можете избежать всех проверок внутри функции, если вы также используете параметры по умолчанию:
ES5
Есть способ приблизиться к тому, что вы хотите, но он основан на выводе
Function.prototype.toString
[ES5] , который в некоторой степени зависит от реализации, поэтому он может быть несовместим с браузерами.Идея состоит в том, чтобы проанализировать имена параметров из строкового представления функции, чтобы можно было связать свойства объекта с соответствующим параметром.
Вызов функции может выглядеть так
где
a
иb
являются позиционными аргументами, а последний аргумент является объектом с именованными аргументами.Например:
Который вы бы использовали как:
DEMO
У этого подхода есть некоторые недостатки (вас предупредили!):
undefined
(это отличается от отсутствия значения вообще). Это означает, что вы не можете использовать,arguments.length
чтобы проверить, сколько аргументов было передано.Вместо того, чтобы иметь функцию, создающую оболочку, вы также можете иметь функцию, которая принимает функцию и различные значения в качестве аргументов, такие как
или даже расширить,
Function.prototype
чтобы вы могли сделать:источник
Object.defineProperty
и наборenumerable
дляfalse
). Нужно всегда быть осторожным при расширении нативных объектов. Весь подход выглядит немного хакерским, поэтому я не ожидал бы, что он сработает сейчас и навсегда;)undefined
"нет значения", можно добавить, что именно так работают значения по умолчанию для функций JS, считаяundefined
пропущенное значение.Нет - объектный подход является ответом JavaScript на это. С этим нет проблем, если ваша функция ожидает объект, а не отдельные параметры.
источник
Эта проблема была моей любимой мозолью в течение некоторого времени. Я опытный программист со многими языками под моим поясом. Один из моих любимых языков, которые я имел удовольствие использовать, это Python. Python поддерживает именованные параметры без каких-либо хитростей .... С тех пор, как я начал использовать Python (некоторое время назад), все стало проще. Я считаю, что каждый язык должен поддерживать именованные параметры, но это не так.
Многие люди говорят, что нужно просто использовать трюк «Передать объект», чтобы вы назвали параметры.
И это прекрасно работает, за исключением ..... когда речь идет о большинстве IDE, многие из нас, разработчиков, полагаются на подсказки типа / аргумента в нашей IDE. Я лично использую PHP Storm (наряду с другими средами разработки JetBrains, такими как PyCharm для python и AppCode для Objective C)
И самая большая проблема с использованием трюка «Передача объекта» состоит в том, что когда вы вызываете функцию, IDE дает вам подсказку одного типа, и все ... Как мы должны знать, какие параметры и типы должны входить в объект arg1?
Итак ... трюк "Передача объекта" у меня не работает ... На самом деле он вызывает больше головной боли, когда приходится смотреть на докблок каждой функции, прежде чем я узнаю, какие параметры ожидает функция .... Конечно, это здорово для когда вы поддерживаете существующий код, но это ужасно для написания нового кода.
Что ж, это техника, которую я использую .... Теперь могут быть некоторые проблемы с этим, и некоторые разработчики могут сказать мне, что я делаю это неправильно, и я непредвзято отношусь к этим вещам ... Я всегда готов искать лучшие способы выполнения задачи ... Так что, если есть проблема с этой техникой, тогда комментарии приветствуются.
Таким образом, у меня есть лучшее из обоих миров ... новый код легко написать, так как моя IDE дает мне все правильные подсказки аргументов ... И, поддерживая код позже, я могу сразу увидеть, не только значение, переданное функции, а также имя аргумента. Единственные накладные расходы, которые я вижу, это объявление имен ваших аргументов в качестве локальных переменных, чтобы не допустить загрязнения глобального пространства имен. Конечно, это немного лишняя типизация, но она тривиальна по сравнению со временем, которое требуется для поиска докблоков при написании нового кода или поддержке существующего кода.
источник
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
это лучше, чемmyFunc(arg1='Param1', arg2='Param2');
потому, что у читателя нет шансов обмануть себя, чем происходят какие-либо настоящие именованные спорыЕсли вы хотите прояснить, каков каждый из параметров, а не просто вызывать
почему бы не сделать следующее
конечно, это дополнительная строка кода, но она выигрывает по удобству чтения.
источник
someFunction(height: 115);
но если вы пишете,someFunction(height);
вы фактически устанавливаете ширину.someFunction(width = 70, height = 115);
. Переменные объявляются в верхней части текущей области в генерируемом коде JavaScript.Другой способ - использовать атрибуты подходящего объекта, например, так:
Конечно, для этого выдуманного примера это несколько бессмысленно. Но в тех случаях, когда функция выглядит
это может быть более полезным. Это также может быть объединено с идеей «parameterfy» для создания такого объекта из существующей функции универсальным способом. Это значит, что для каждого параметра будет создан член, который может оценивать версию функции с частичной оценкой.
Эта идея, конечно, связана с Schönfinkeling aka Curry.
источник
Есть другой способ. Если вы передаете объект по ссылке, свойства этого объекта появятся в локальной области действия функции. Я знаю, что это работает для Safari (не проверял другие браузеры), и я не знаю, есть ли у этой функции имя, но приведенный ниже пример иллюстрирует ее использование.
Хотя на практике я не думаю, что это дает какую-то функциональную ценность помимо техники, которую вы уже используете, семантически немного чище. И это все еще требует передачи ссылки на объект или литерала объекта.
источник
Пробуя Node-6.4.0 (process.versions.v8 = '5.0.71.60') и Node Chakracore-v7.0.0-pre8, а затем Chrome-52 (V8 = 5.2.361.49), я заметил, что именованные параметры почти реализован, но этот порядок все еще имеет приоритет. Я не могу найти то, что говорит стандарт ECMA.
Но порядок обязателен !! Это стандартное поведение?
источник
b=10
выражения есть10
, и это то, что передается в функцию.f(bla=10)
также будет работать (он назначает 10 для переменнойbla
и передает значение функции впоследствии).a
иb
переменные в глобальной области видимости как побочный эффект.Вызов функции
f
с именованными параметрами, переданными как объектв основном вызывает его композицию,
f(...g(o))
где я использую синтаксис распространения, иg
представляет собой «привязывающую» карту, соединяющую значения объекта с их позициями параметров.Карта привязки - это точно отсутствующий компонент, который может быть представлен массивом его ключей:
Обратите внимание на три разделенных компонента: функцию, объект с именованными аргументами и привязку. Эта развязка обеспечивает большую гибкость в использовании этой конструкции, где привязка может быть произвольно настроена в определении функции и произвольно расширена во время вызова функции.
Например, вы можете захотеть сократить
height
иwidth
какh
иw
внутри определения вашей функции, чтобы сделать ее короче и чище, в то время как вы все еще хотите назвать ее с полными именами для ясности:Эта гибкость также более полезна для функционального программирования, где функции могут быть произвольно преобразованы с потерянными их первоначальными именами параметров.
источник
Исходя из Python, это меня раздражало. Я написал простую оболочку / Прокси для узла, которая будет принимать как позиционные, так и ключевые объекты.
https://github.com/vinces1979/node-def/blob/master/README.md
источник
f(x, opt)
гдеopt
находится объект. Помогает ли это избежать или создавать ошибки (например, вызванные опечатками и болью в запоминании названий ключевых слов), остается вопросом.kwargs
dict один за другим и, наконец, поднимаете,TypeError
если остаются неизвестные ключи). Вашеf(x, opt)
решение позволяет вf
функции сделать что - то подобное в Python 2, но вам нужно будет обрабатывать все значения по умолчанию самостоятельно.f(x, opt)
это уже работает, хотя я не понимаю, как это помогает ответить на вопрос, где, например, вы хотите сделатьrequest(url)
иrequest({url: url})
то, и другое , что невозможно сделать сurl
помощью параметра только для ключевых слов.Вопреки распространенному мнению, именованные параметры могут быть реализованы в стандартном старом школьном JavaScript (только для логических параметров) с помощью простого, аккуратного соглашения о кодировании, как показано ниже.
Предостережения:
Порядок аргументов должен быть сохранен - но шаблон все еще полезен, так как он делает очевидным, какой фактический аргумент предназначен для какого формального параметра, без необходимости искать в сигнатуре функции или использовать IDE.
Это работает только для логических значений. Однако я уверен, что подобный шаблон может быть разработан для других типов с использованием уникальной семантики приведения типов в JavaScript.
источник
height
по имени независимо от порядка param.