Классический (не js) подход к перегрузке:
function myFunc(){
//code
}
function myFunc(overloaded){
//other code
}
Javascript не позволяет определять более одной функции с одним и тем же именем. Таким образом, появляются такие вещи:
function myFunc(options){
if(options["overloaded"]){
//code
}
}
Есть ли лучший способ обхода перегрузки функций в javascript, кроме передачи объекта с перегрузками в нем?
Передача перегрузок может быстро привести к тому, что функция станет слишком многословной, потому что каждая возможная перегрузка потребует условного оператора. Использование функций для выполнения //code
внутренней части этих условных операторов может вызвать сложные ситуации с областями действия.
javascript
Трэвис Дж.
источник
источник
Ответы:
Есть несколько аспектов перегрузки аргументов в Javascript:
Переменные аргументы - вы можете передавать разные наборы аргументов (как по типу, так и по количеству), и функция будет вести себя в соответствии с переданными ей аргументами.
Аргументы по умолчанию - вы можете определить значение по умолчанию для аргумента, если оно не передано.
Именованные аргументы - порядок аргументов становится неактуальным, и вы просто называете аргументы, которые хотите передать функции.
Ниже приводится раздел по каждой из этих категорий обработки аргументов.
Переменные аргументы
Поскольку в javascript нет проверки типа аргументов или необходимого количества аргументов, вы можете иметь только одну реализацию,
myFunc()
которая может адаптироваться к тому, какие аргументы были переданы ему, путем проверки типа, наличия или количества аргументов.jQuery делает это постоянно. Вы можете сделать некоторые из аргументов необязательными или вы можете выполнить ветвление в своей функции в зависимости от того, какие аргументы ей переданы.
При реализации этих типов перегрузок вы можете использовать несколько различных методов:
undefined
.arguments.length
.arguments
псевдо-массив для доступа к любому заданному аргументу с помощьюarguments[i]
.Вот некоторые примеры:
Давайте посмотрим на
obj.data()
метод jQuery . Он поддерживает четыре различных формы использования:Каждый запускает различное поведение, и без использования этой динамической формы перегрузки потребовалось бы четыре отдельные функции.
Вот как можно различить все эти варианты на английском языке, а затем я объединю их все в коде:
Если первый аргумент, переданный в,
.data()
является строкой, а второй аргумент - этоundefined
, то вызывающий должен использовать эту форму.Если второй аргумент не является неопределенным, установите значение определенного ключа.
Если аргументы не переданы, вернуть все ключи / значения в возвращаемом объекте.
Если тип первого аргумента - простой объект, установите все ключи / значения из этого объекта.
Вот как вы могли бы объединить все это в один набор логики javascript:
Ключ к этой технике - убедиться, что все формы аргументов, которые вы хотите принять, однозначно идентифицируемы, и никогда не возникает путаницы в том, какую форму использует вызывающий. Как правило, это требует соответствующего упорядочивания аргументов и обеспечения достаточной уникальности типа и положения аргументов, чтобы вы всегда могли определить, какая форма используется.
Например, если у вас есть функция, которая принимает три строковых аргумента:
Вы можете легко сделать третий аргумент необязательным, и вы можете легко обнаружить это условие, но вы не можете сделать только второй аргумент необязательным, потому что вы не можете сказать, какой из них вызывающий имеет намерение передать, потому что нет способа определить, является ли второй аргумент Аргумент должен быть вторым аргументом, или второй аргумент был опущен, поэтому то, что находится в месте второго аргумента, на самом деле является третьим аргументом:
Поскольку все три аргумента относятся к одному типу, вы не можете отличить разные аргументы, поэтому не знаете, что имел в виду вызывающий. При таком стиле вызова только третий аргумент может быть необязательным. Если вы хотите опустить второй аргумент, его необходимо передать как
null
(или какое-либо другое обнаруживаемое значение), и ваш код обнаружит это:Вот пример необязательных аргументов jQuery. оба аргумента являются необязательными и принимают значения по умолчанию, если не переданы:
Вот пример jQuery, где аргумент может отсутствовать или один из трех разных типов, что дает вам четыре разных перегрузки:
Именованные аргументы
Другие языки (например, Python) позволяют передавать именованные аргументы как средство передачи только некоторых аргументов и сделать аргументы независимыми от порядка, в котором они передаются. Javascript не поддерживает напрямую функцию именованных аргументов. Вместо него обычно используется шаблон проектирования, который передает карту свойств / значений. Это можно сделать, передав объект со свойствами и значениями, или в ES6 и выше вы можете передать сам объект Map.
Вот простой пример ES5:
jQuery
$.ajax()
принимает форму использования, в которой вы просто передаете ему один параметр, который является обычным объектом Javascript со свойствами и значениями. Какие свойства вы ему передаете, определяют, какие аргументы / параметры передаются в вызов ajax. Некоторые могут потребоваться, многие - по желанию. Поскольку они являются свойствами объекта, особого порядка нет. Фактически, этому объекту можно передать более 30 различных свойств, требуется только одно (URL-адрес).Вот пример:
$.ajax()
Затем внутри реализации он может просто запросить, какие свойства были переданы входящему объекту, и использовать их в качестве именованных аргументов. Это можно сделать либо с помощью,for (prop in obj)
либо путем передачи всех свойств в массив с помощьюObject.keys(obj)
и затем повторения этого массива.Этот метод очень часто используется в Javascript, когда есть большое количество аргументов и / или многие аргументы являются необязательными. Примечание: это накладывает бремя на реализующую функцию, чтобы убедиться, что присутствует минимальный допустимый набор аргументов, и дать вызывающей стороне некоторую обратную связь отладки, которая отсутствует, если передано недостаточное количество аргументов (возможно, путем выдачи исключения с полезным сообщением об ошибке) .
В среде ES6 можно использовать деструктурирование для создания свойств / значений по умолчанию для переданного выше объекта. Более подробно это обсуждается в этой справочной статье .
Вот один пример из той статьи:
Это создает свойства и значения по умолчанию для
start
,end
иstep
свойства на объект передается вselectEntries()
функцию.Значения по умолчанию для аргументов функции
В ES6 Javascript добавляет встроенную языковую поддержку для значений аргументов по умолчанию.
Например:
Дальнейшее описание способов использования здесь, в MDN .
источник
resetProgressBar: function(display_errors, lockout = false)
.Перегрузка функции в JavaScript может выполняться разными способами. Все они включают одну главную функцию, которая либо выполняет все процессы, либо делегирует подфункции / процессы.
Один из наиболее распространенных простых методов включает простой переключатель:
Более элегантным методом было бы использование массива (или объекта, если вы не делаете перегрузки для каждого количества аргументов):
Этот предыдущий пример не очень элегантен, любой может изменить
fooArr
, и он потерпит неудачу, если кто-то передаст более двух аргументовfoo
, поэтому лучшей формой было бы использовать шаблон модуля и несколько проверок:Конечно, ваши перегрузки могут захотеть использовать динамическое количество параметров, поэтому вы можете использовать объект для
fns
коллекции.Мое личное предпочтение, как правило, заключается в том
switch
, что это делает основную функцию больше. Типичным примером того, где я бы использовал эту технику, был бы метод доступа / мутатора:источник
Строго говоря, вы не можете выполнять перегрузку методов. Не так, как это поддерживается в
java
илиc#
.Проблема в том, что JavaScript изначально НЕ поддерживает перегрузку методов. Итак, если он видит / анализирует две или более функций с одинаковыми именами, он просто учитывает последнюю определенную функцию и перезаписывает предыдущие.
Один из способов, который, на мой взгляд, подходит для большинства случаев, следующий:
Допустим, у вас есть метод
Вместо метода перегрузки, который невозможен в javascript, вы можете определить новый метод
а затем измените 1-ю функцию следующим образом -
Если у вас много таких перегруженных методов, рассмотрите возможность использования
switch
не толькоif-else
операторов.( подробнее ) PS: Выше ссылка ведет на мой личный блог, в котором есть дополнительная информация по этому поводу.
источник
Я использую немного другой подход к перегрузке, основанный на количестве аргументов. Однако я считаю, что подход Джона Фосетта тоже хорош. Вот пример кода, основанного на пояснениях Джона Ресига (автора jQuery).
юзабилити:
источник
В javascript вы можете реализовать функцию только один раз и вызвать функцию без параметров.
myFunc()
Затем вы проверяете, является ли параметр undefined.источник
Я попытался разработать элегантное решение этой проблемы, описанной здесь . А демо можно найти здесь . Использование выглядит так:
Методы, используемые для этого:
источник
https://github.com/jrf0110/leFunc
источник
Нет проблем с перегрузкой в JS, pb как сохранить чистый код при перегрузке функции?
Вы можете использовать форвард, чтобы получить чистый код, основываясь на двух вещах:
Тип аргументов (при вызове функции)
источник
Проверь это:
http://www.codeproject.com/Articles/688869/Overloading-JavaScript-Functions
В основном в своем классе вы нумеруете свои функции, которые хотите перегрузить, а затем одним вызовом функции вы быстро и легко добавляете перегрузку функций.
источник
Поскольку в JavaScript нет параметров перегрузки функций , можно использовать вместо него. Если есть один или два обязательных аргумента, лучше хранить их отдельно от объекта параметров. Вот пример того, как использовать объект параметров и заполненные значения для значения по умолчанию в случае, если значение не было передано в объекте параметров.
}
вот пример того, как использовать объект параметров
источник
Для этого вам нужно создать функцию, которая добавляет функцию к объекту, а затем она будет выполняться в зависимости от количества аргументов, которые вы отправляете функции:
источник
Мне нравится добавлять подфункции в родительскую функцию, чтобы получить возможность различать группы аргументов для одной и той же функциональности.
источник
То, что вы пытаетесь достичь, лучше всего делать с помощью переменной локальных аргументов функции .
Вы можете найти лучшее объяснение того, как это работает, здесь .
источник