2010-06-30 4 views
47

У меня есть типичный яваскрипт функция с некоторыми параметрамиJavaScript необязательных аргументов в функции

my_function = function(content, options) { action } 

, если я вызываю функцию как таковые:

my_function (options) 

аргумента «опцию» передаются как «содержание»

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

ответ

81

Вы должны решить, какие параметр, который вы хотите обработать одним аргументом. Вы не можете рассматривать его как оба, content и options.

Я вижу две возможности:

  1. Либо изменить порядок ваших аргументов, т.е. function(options, content)
  2. Проверьте options определяется:

    function(content, options) { 
        if(typeof options === "undefined") { 
         options = content; 
         content = null; 
        } 
        //action 
    } 
    

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

+1

undefined - глобальное свойство с постоянным значением, поэтому вам не нужно его цитировать. В устаревших браузерах вы можете случайно установить его на произвольное значение, но это не относится к современным браузерам. – andreszs

+5

@Andrew: 'typeof' всегда возвращает строку. Кроме того, 'if (options === undefined)' также будет работать. Но, как вы сказали, в старых браузерах можно переопределить 'undefined', поэтому все еще преобладающая практика (я думаю) заключается не в том, чтобы напрямую использовать' undefined' (если вы не указали где-то явно). –

+1

не сравнивать строки с '===', это не тот же объект, если у вас одинаковый контент. – inetphantom

14

Как это:

my_function (null, options) // for options only 
my_function (content) // for content only 
my_function (content, options) // for both 
0

вы получите ООН принял значение в качестве аргумента, не определено. Но в вашем случае вам нужно передать хотя бы нулевое значение в первом аргументе.

Или вы должны изменить определение метода как

my_function = function(options, content) { action } 
21
my_function = function(hash) { /* use hash.options and hash.content */ }; 

, а затем вызвать:

my_function ({ options: options }); 
my_function ({ options: options, content: content }); 
+0

что такое хэш на самом деле? – BlueBird

+0

Почему вы называете это «хэш»? –

+0

@Muneer: Это просто пример. – Sarfraz

3

Или вы также можете различать, какой тип контента у вас есть. Параметры используются в качестве объекта содержания используется, чтобы быть строкой, так что можно сказать:

if (typeof content === "object") { 
    options = content; 
    content = null; 
} 

Или, если вы запутались с переименованием, вы можете использовать массив аргументов, которые могут быть более простым:

if (arguments.length === 1) { 
    options = arguments[0]; 
    content = null; 
} 
+1

Я предпочитаю этот вариант: 'var optional_arg = arguments.length> = 1? arguments [0]: «значение по умолчанию»; ' –

1

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

function my_func(op, cb) { 
    var options = (typeof arguments[0] !== "function")? arguments[0] : {}, 
     callback = (typeof arguments[0] !== "function")? arguments[1] : arguments[0]; 

    console.log(options); 
    console.log(callback); 
} 

Если вы называете это, не проходя аргумент опции, то по умолчанию будет пустой объект:

my_func(function() {}); 
=> options: {} 
=> callback: function() {} 

Если вы вызываете его с аргументом опции вы получите весь ваш Params:

my_func({param1: 'param1', param2: 'param2'}, function() {}); 
=> options: {param1: "param1", param2: "param2"} 
=> callback: function() {} 

Это может, очевидно, быть переделано для работы с большим количеством аргументов, чем два, но получить еще более кооперативы nfusing. Если вы можете просто использовать объект в качестве своего первого аргумента, вы можете передать неограниченное количество аргументов с помощью этого объекта. Если вам абсолютно необходимы дополнительные аргументы (например, my_func (arg1, arg2, arg3, ..., arg10, fn)), я бы предложил использовать библиотеку, такую ​​как ArgueJS. Я лично его не использовал, но выглядит многообещающе.

+0

большое спасибо ... Именно это я и ищу. У меня есть 6 параметров в моей функции. некоторые параметры имеют значения по умолчанию. Но некоторые параметры должны задаваться в вызове функции. Я думаю, что этот ответ хорошо подходит для моего дела. Еще раз спасибо ... :) –

-1

Вы также можете поставить галочку в акции, как: options = !options ? content : options , который устанавливает параметры для первого аргумента, если не второй не был принят, и затем вы просто установить содержание в нуль (или игнорировать его, однако вы хотите проверить что)

2

Есть 2 способа сделать это.

1)

function something(options) { 
    var timeToLive = options.timeToLive || 200; // default to 200 if not set 
    ... 
} 

2)

function something(timeToDie /*, timeToLive*/) { 
    var timeToLive = arguments[1] || 200; // default to 200 if not set 
    .. 
} 

В 1) options является объектом JS с тем, что когда-либо атрибуты необходимы. Это проще поддерживать и расширять.

В 2) сигнатура функции понятна для чтения и понимания того, что может быть предоставлен второй аргумент. Я видел этот стиль, используемый в коде Mozilla и документации.

1

Я создал простую библиотеку для обработки необязательных аргументов с функциями JavaScript, см. https://github.com/ovatto/argShim. Библиотека разработана с учетом Node.js, но ее следует легко портировать для работы, например. браузеры.

Пример:

var argShim = require('argShim'); 
var defaultOptions = { 
    myOption: 123 
}; 

var my_function = argShim([ 
    {optional:'String'}, 
    {optional:'Object',default:defaultOptions} 
    ], function(content, options) { 
    console.log("content:", content, "options:", options); 
    }); 

my_function(); 
my_function('str'); 
my_function({myOption:42}); 
my_function('str', {myOption:42}); 

Выход:

content: undefined options: { myOption: 123 } 
content: str options: { myOption: 123 } 
content: undefined options: { myOption: 42 } 
content: str options: { myOption: 42 } 

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

+0

Это очень многословно, плюс он использует слово «default», которое уже является ключевым словом в JS. Не рекомендовал бы. –

+0

Уверен, что он может быть немного подробным, но он предоставляет некоторые дополнительные функции поверх простой проверки наличия аргументов. И писать одинаковые функции в каждой функции будет еще более подробным. Кроме того, в то время как некоторым не нравится, зарезервированные ключевые слова могут свободно использоваться как имена свойств в ES5. Однако вся библиотека была довольно поспешно написана, чтобы ваш (и мой) пробег мог меняться :) – ovatto

1

Просто, чтобы выгнать давно мертвую лошадь, потому что мне пришлось реализовать необязательный аргумент в середине двух или более необходимых аргументов. Используйте массив arguments и используйте последний один как необязательный необязательный аргумент.

my_function() { 
    var options = arguments[argument.length - 1]; 
    var content = arguments.length > 1 ? arguments[0] : null; 
} 
1

В ES6 есть хорошие параметры чтения по умолчанию. on the MDN website here.
В ES6 теперь вы можете сделать следующее:

secondDefaultValue = 'indirectSecondDefaultValue'; 

function MyObject(param1 = 'firstDefaultValue', param2 = secondDefaultValue){ 
    this.first = param1; 
    this.second = param2; 
} 

Вы можете использовать это также следующим образом:

var object = new MyObject(undefined, options); 

который установит значение по умолчанию 'firstDefaultValue' для первого param1 и ваш options для второго param2.

Here a demonstration in a fiddle

0

С ES6:

function test(a, b = 3) { 
    console.log(a, ' ', b); 
} 

test(1);  // Output: 1 3 
test(1, 2); // Output: 1 2 
Смежные вопросы