Задайте параметр по умолчанию по имени при вызове метода в Javascript [duplicate]

Ваш путь к классу нарушен (что является общей проблемой very в мире Java).

В зависимости от того, как вы запускаете свое приложение, вам нужно пересмотреть аргумент в -cp, запись в Class-Path в файле MANIFEST.MF или на вашем диске.

113
задан Bergi 24 July 2015 в 09:45
поделиться

7 ответов

ES2015

В ES2015 параметр деструктурирования параметра может использоваться для имитации именованных параметров. Это потребует, чтобы вызывающий передал объект, но вы можете избежать всех проверок внутри функции, если вы также используете параметры по умолчанию:

myFunction({ param1 : 70, param2 : 175});

function myFunction({param1, param2}={}){
  // ...
}

ES5

Там это способ приблизиться к тому, что вы хотите, но он основан на выходе Function.prototype.toString [ES5] , который зависит от реализации в некоторой степени, поэтому он не может быть совместим с несколькими браузерами .

Идея состоит в том, чтобы проанализировать имена параметров из строкового представления функции, чтобы вы могли ассоциировать свойства объекта с соответствующим параметром.

Затем вызов функции мог выглядят как

func(a, b, {someArg: ..., someOtherArg: ...});

, где a и b являются позиционными аргументами, а последний аргумент - объектом с именованными аргументами.

Например:

var parameterfy = (function() {
    var pattern = /function[^(]*\(([^)]*)\)/;

    return function(func) {
        // fails horribly for parameterless functions ;)
        var args = func.toString().match(pattern)[1].split(/,\s*/);

        return function() {
            var named_params = arguments[arguments.length - 1];
            if (typeof named_params === 'object') {
                var params = [].slice.call(arguments, 0, -1);
                if (params.length < args.length) {
                    for (var i = params.length, l = args.length; i < l; i++) {
                        params.push(named_params[args[i]]);
                    }
                    return func.apply(this, params);
                }
            }
            return func.apply(null, arguments);
        };
    };
}());

Который вы бы использовали как:

var foo = parameterfy(function(a, b, c) {
    console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);     
});

foo(1, 2, 3); // a is 1  | b is 2  | c is 3
foo(1, {b:2, c:3}); // a is 1  | b is 2  | c is 3
foo(1, {c:3}); // a is 1  | b is undefined  | c is 3
foo({a: 1, c:3}); // a is 1  | b is undefined  | c is 3 

DEMO

Есть некоторые недостатки этого подхода (вы были предупреждены!):

  • Если последний аргумент является объектом, он рассматривается как «именованные объекты аргументов»
  • You wil Я всегда получаю столько аргументов, сколько вы определили в функции, но некоторые из них могут иметь значение undefined (это отличается от отсутствия значения вообще). Это означает, что вы не можете использовать arguments.length для проверки того, сколько аргументов было передано.

Вместо функции, создающей оболочку, вы также можете иметь функцию, которая принимает функцию и различные значения в качестве аргументов, например

call(func, a, b, {posArg: ... });

, или даже расширить Function.prototype, чтобы вы могли:

foo.execute(a, b, {posArg: ...});
108
ответ дан Felix Kling 22 August 2018 в 15:04
поделиться
  • 1
    Клятва! Function.prototype .. Я надеялся, что кто-то пойдет в этом направлении. – Robin Maben 3 August 2012 в 15:58
  • 2
    Да ... вот пример для этого: jsfiddle.net/9U328/1 (хотя лучше использовать Object.defineProperty и установить enumerable на false). Всегда нужно быть осторожным при расширении собственных объектов. Весь подход немного взломан, поэтому я не ожидал, что он будет работать сейчас и навсегда;) – Felix Kling 3 August 2012 в 16:03
  • 3
    Отметил. Я приложу его к использованию. Маркировка как ответ! ...На данный момент ;) – Robin Maben 3 August 2012 в 16:43
  • 4
    Very minor nitpick: Я не думаю, что этот подход поймает EcmaScript 6 Функции стрелок . В настоящее время это не вызывает большой озабоченности, но, возможно, стоит упомянуть в разделе о предостережениях вашего ответа. – NobodyMan 9 June 2015 в 23:33
  • 5
    @NobodyMan: Верно. Я написал этот ответ до того, как функции стрелки были чем-то. В ES6 я бы прибегнул к деструкции параметров. – Felix Kling 9 June 2015 в 23:38

Есть другой способ. Если вы передаете объект по ссылке, свойства этого объекта будут отображаться в локальной области функции. Я знаю, что это работает для Safari (не проверял другие браузеры), и я не знаю, имеет ли эта функция имя, но приведенный ниже пример иллюстрирует его использование.

Хотя на практике я не думаю что это предлагает любую функциональную ценность за пределами техники, которую вы уже используете, это немного чище семантически. И по-прежнему требуется передать ссылку на объект или литерал объекта.

function sum({ a:a, b:b}) {
    console.log(a+'+'+b);
    if(a==undefined) a=0;
    if(b==undefined) b=0;
    return (a+b);
}

// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));

// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));
3
ответ дан Allen Ellison 22 August 2018 в 15:04
поделиться

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

someFunction(70, 115);

, то почему бы не сделать следующий

var width = 70, height = 115;
someFunction(width, height);

уверен, это дополнительная строка кода, но она выигрывает на удобочитаемости.

15
ответ дан dav_i 22 August 2018 в 15:04
поделиться
  • 1
    +1 для соблюдения принципа KISS, плюс также помогает при отладке. Тем не менее, я думаю, что каждый var должен быть в отдельной строке, хотя и с небольшим ударом производительности ( http://stackoverflow.com/questions/9672635/javascript-var-statement-and-performance ). – clairestreb 19 June 2014 в 15:55
  • 2
    Речь идет не только о дополнительной строке кода, но и о порядке аргументов и сделать их необязательными. Поэтому вы можете написать это с помощью названных параметров: someFunction(height: 115);, но если вы напишете someFunction(height);, вы фактически устанавливаете ширину. – Francisco Presencia 30 April 2015 в 06:51

Trying Node-6.4.0 (process.versions.v8 = '5.0.71.60') и Node Chakracore-v7.0.0-pre8, а затем Chrome-52 (V8 = 5.2.361.49), я заметил, что named параметры реализованы почти , но этот порядок все еще имеет приоритет. Я не могу найти то, что говорит стандарт ECMA.

>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }

> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17

Но требуется заказ! Является ли это стандартным поведением?

> f(b=10)
a=10 + b=2 = 12
2
ответ дан jgran 22 August 2018 в 15:04
поделиться
  • 1
    Это не то, что вы думаете. Результатом выражения b=10 является 10, и это то, что передается функции. f(bla=10) также будет работать (он назначает 10 переменной bla и после этого передает значение функции). – Matthias Kestenholz 17 November 2016 в 14:24

Этот вопрос был моим любимым человеком в течение некоторого времени. Я опытный программист со многими языками под моим поясом. Один из моих любимых языков, которым я имел удовольствие использовать Python. Python поддерживает именованные параметры без каких-либо обманщиков .... Поскольку я начал использовать Python (некоторое время назад), все стало проще. Я считаю, что каждый язык должен поддерживать именованные параметры, но это не так.

Многие люди говорят, что просто используют трюк «Пропустить объект», чтобы вы назвали параметры.

/**
 * My Function
 *
 * @param {Object} arg1 Named arguments
 */
function myFunc(arg1) { }

myFunc({ param1 : 70, param2 : 175});

И это отлично работает, за исключением того, что ..... когда дело доходит до большинства IDE, многие из нас разработчики полагаются на подсказки типа / аргумента в нашей среде IDE. Я лично использую PHP Storm (наряду с другими IDE JetBrains, такими как PyCharm для python и AppCode для Objective C)

И самая большая проблема с использованием трюка «Передача объекта» заключается в том, что когда вы вызываете функцию, IDE дает вам однотипный намек и все ... Как мы должны знать, какие параметры и типы должны входить в объект arg1?

I have no idea what parameters should go in arg1 [/g0]

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

Ну, это тот метод, который я использую ... Теперь могут быть некоторые проблемы с ним, и некоторые разработчики могут скажите мне, что я делаю это неправильно, и у меня есть открытый ум, когда дело доходит до этих вещей ... Я всегда готов смотреть на лучшие способы решения задачи ... Итак, если есть проблема с этой техникой , то комментарии приветствуются.

/**
 * My Function
 *
 * @param {string} arg1 Argument 1
 * @param {string} arg2 Argument 2
 */
function myFunc(arg1, arg2) { }

var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');

Таким образом, у меня есть лучшее из обоих миров ... новый код легко писать, так как моя IDE дает мне все правильные подсказки аргументов ... И, пока поддерживая код позже, я могу сразу увидеть не только значение, переданное функции, но и имя аргумента. Единственный недостаток, который я вижу, - объявлять ваши имена аргументов как локальные переменные, чтобы не загрязнять глобальное пространство имен. Конечно, это немного лишний набор, но тривиальный по сравнению с временем, требуемым для поиска докблоков при написании нового кода или сохранении существующего кода.

Now, I have all the parameters and types when creating new code [/g1]

16
ответ дан Ray Perea 22 August 2018 в 15:04
поделиться
  • 1
    Единственное, что связано с этой техникой, это тот факт, что вы не можете изменить порядок параметров ... Я лично хорошо это понимаю. – Ray Perea 10 July 2014 в 21:11
  • 2
    Похоже, что это просто просит неприятностей, когда приходит какой-то будущий сопровождающий, и думает, что они могут изменить порядок аргумента (но, очевидно, не могут). – Andrew Medico 10 July 2014 в 21:19
  • 3
    @AndrewMedico Я согласен ... похоже, вы можете просто изменить порядок аргументов, как в Python. Единственное, что я могу сказать об этом, это выяснить, как быстро, когда изменение порядка аргументов нарушает работу программы. – Ray Perea 10 July 2014 в 21:27
  • 4
    Я утверждаю, что myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2'); лучше, чем myFunc(arg1='Param1', arg2='Param2');, потому что у него нет шансов обмануть читателя, чем происходят какие-либо фактические именованные аргументы – Eric 21 September 2016 в 09:24
  • 5
    @Eric. Я не думал об использовании комментариев в вызове функции ... Это здорово ... Единственное, что с этим методом заключается в том, что с комментариями у меня нет автоматического завершения, поэтому мне нужно будет вывести каждый аргумент имя вручную ... Но, опять же, мне все равно придется это делать, когда я определяю вары в первую очередь ..... Спасибо за ваше понимание. – Ray Perea 21 September 2016 в 16:53

Нет - объектный подход - это ответ JavaScript на это. Нет проблем с этим, если ваша функция ожидает объект, а не отдельные параметры.

55
ответ дан Robin Maben 22 August 2018 в 15:04
поделиться
  • 1
    Объяснение путинского голосования : @Utkanos это скорее комментарий, чем ответ. – Robin Maben 3 August 2012 в 16:41
  • 2
    @RobertMaben - Ответ на заданный вопрос заключается в том, что нет никакого способа собирать объявленные vars или функции, не зная, что они живут в определенном пространстве имен. Просто потому, что ответ короткий, он не отрицает его пригодность в качестве ответа - не согласны ли вы? Есть гораздо более короткие ответы там, по линии «нет, нет возможности». Короткие они могут быть, но они также являются ответом на вопрос. – Utkanos 3 August 2012 в 17:31
  • 3
    В настоящее время существует es6: 2ality.com/2011/11/keyword-parameters.html – slacktracer 12 January 2016 в 19:32
  • 4
    Это, безусловно, справедливый ответ - «Именованные параметры» - это языковая функция. Объектный подход является следующим лучшим в отсутствие такой функции. – fatuhoku 19 January 2016 в 19:07

Другой способ - использовать атрибуты подходящего объекта, например. например:

function plus(a,b) { return a+b; };

Plus = { a: function(x) { return { b: function(y) { return plus(x,y) }}}, 
         b: function(y) { return { a: function(x) { return plus(x,y) }}}};

sum = Plus.a(3).b(5);

Конечно, для этого составленного примера это несколько бессмысленно. Но в тех случаях, когда функция выглядит как

do_something(some_connection_handle, some_context_parameter, some_value)

, она может оказаться более полезной. Это также можно сочетать с идеей «parameterfy», чтобы создать такой объект из существующей функции в общем виде. То есть для каждого параметра он создавал бы элемент, который может оценивать частичную оценочную версию функции.

Эта идея, конечно, связана с Schönfinkeling aka Currying.

4
ответ дан Udo Klein 22 August 2018 в 15:04
поделиться
  • 1
    Это аккуратная идея, и она становится еще лучше, если вы объедините ее с аргументами интроспекции. К сожалению, он не работает с дополнительными аргументами – Eric 21 September 2016 в 09:26
Другие вопросы по тегам:

Похожие вопросы: