IT story

여러 인수와 옵션 개체

hot-time 2020. 6. 14. 09:52
반응형

여러 인수와 옵션 개체


여러 인수로 JavaScript 함수를 만들 때 항상이 선택에 직면합니다. 인수 목록 전달과 옵션 개체 전달.

예를 들어 nodeList를 배열에 매핑하는 함수를 작성 중입니다.

function map(nodeList, callback, thisObject, fromIndex, toIndex){
    ...
}

대신 이것을 사용할 수 있습니다 :

function map(options){
    ...
}

여기서 options는 객체입니다.

options={
    nodeList:...,
    callback:...,
    thisObject:...,
    fromIndex:...,
    toIndex:...
}

어느 것이 권장되는 방법입니까? 한 대를 사용하는시기에 대한 지침이 있습니까?

[업데이트] 옵션 객체에 찬성하여 합의가있는 것 같습니다. 따라서 의견을 추가하고 싶습니다. 필자의 경우 인수 목록을 사용하려는 유혹을받는 한 가지 이유는 JavaScript와 일치하는 동작을 갖는 것이 었습니다 내장 된 array.map 메소드.


다른 많은 것들과 마찬가지로, 나는 options object긴 매개 변수 목록을 전달하는 대신 함수에 전달하는 것을 선호 하지만 실제로는 정확한 컨텍스트에 달려 있습니다.

리트머스 테스트로 코드 가독성을 사용합니다.

예를 들어,이 함수 호출이 있으면 :

checkStringLength(inputStr, 10);

코드를 읽을 수 있고 개별 매개 변수를 전달하는 것이 좋습니다.

반면에 다음과 같은 호출 기능이 있습니다.

initiateTransferProtocol("http", false, 150, 90, null, true, 18);

조사하지 않으면 완전히 읽을 수 없습니다. 반면에이 코드는 다음과 같이 잘 읽습니다.

initiateTransferProtocol({
  "protocol": "http",
  "sync":      false,
  "delayBetweenRetries": 150,
  "randomVarianceBetweenRetries": 90,
  "retryCallback": null,
  "log": true,
  "maxRetries": 18
 });

그것은 과학보다는 예술에 가깝지만 규칙의 이름을 정해야한다면 :

다음과 같은 경우 옵션 매개 변수를 사용하십시오.

  • 네 개 이상의 매개 변수가 있습니다
  • 모든 매개 변수는 선택 사항입니다
  • 어떤 매개 변수가 필요한지 알아 내기 위해 함수를 찾아야했습니다.
  • 누군가가 "ARRRRRG!"

여러 인수는 주로 필수 매개 변수에 대한 것입니다. 그들에게는 아무런 문제가 없습니다.

선택적 매개 변수가 있으면 복잡해집니다. 그들 중 하나가 다른 것에 의존하여 특정 순서를 갖도록 (예를 들어 네 번째 것은 세 번째 것을 필요로하는 경우), 여전히 여러 개의 인수를 사용해야합니다. 거의 모든 기본 EcmaScript 및 DOM 메소드가 이와 같이 작동합니다. openXMLHTTPrequests 방법 이 좋은 예입니다. 마지막 3 개의 인수는 선택 사항입니다. 규칙은 "사용자가없는 암호 없음"과 같습니다 ( MDN 문서 참조 ).

옵션 객체는 두 가지 경우에 유용합니다.

  • 혼동 될 수있는 매개 변수가 너무 많습니다. "이름 지정"이 도움이되며 순서에 대해 걱정할 필요가 없습니다 (특히 변경 될 수있는 경우).
  • 선택적 매개 변수가 있습니다. 객체는 매우 융통성이 있으며, 순서가 없으면 필요한 것만 전달하고 다른 것 (또는 undefineds) 은 전달하지 않습니다 .

귀하의 경우을 추천 map(nodeList, callback, options)합니다. nodelist그리고 callback다른 세 개의 인수는 가끔 와서 적절한 기본값을 가지고해야합니다.

또 다른 예는 JSON.stringify입니다. 함수 space를 전달하지 않고 매개 변수 를 사용하고 싶을 수도 있습니다 . replacer그런 다음 호출해야합니다 …, null, 4). 인수 오브젝트는 2 개의 매개 변수에만 실제로 적합하지는 않지만 더 좋을 수 있습니다.


'객체로서의 옵션'접근법을 사용하는 것이 가장 좋습니다. 속성 순서에 대해 걱정할 필요가 없으며 데이터가 전달 될 때 더 많은 유연성이 있습니다 (예 : 선택적 매개 변수).

Creating an object also means the options could be easily used on multiple functions:

options={
    nodeList:...,
    callback:...,
    thisObject:...,
    fromIndex:...,
    toIndex:...
}

function1(options){
    alert(options.nodeList);
}

function2(options){
    alert(options.fromIndex);
}

I think if you're instantiating something or calling a method of an object, you want to use an options object. If it's a function that operates on just one or two parameters and returns a value, an argument list is preferable.

In some cases, it's good to use both. If your function has one or two required parameters and a bunch of optional ones, make the first two parameters required and the third an optional options hash.

In your example, I'd do map(nodeList, callback, options). Nodelist and callback are required, it's fairly easy to tell what's happening just by reading a call to it, and it's like existing map functions. Any other options can be passed as an optional third parameter.


Your comment on the question:

in my example the last three are optional.

So why not do this? (Note: This is fairly raw Javascript. Normally I'd use a default hash and update it with the options passed in by using Object.extend or JQuery.extend or similar..)

function map(nodeList, callback, options) {
   options = options || {};
   var thisObject = options.thisObject || {};
   var fromIndex = options.fromIndex || 0;
   var toIndex = options.toIndex || 0;
}

So, now since it's now much more obvious what's optional and what's not, all of these are valid uses of the function:

map(nodeList, callback);
map(nodeList, callback, {});
map(nodeList, callback, null);
map(nodeList, callback, {
   thisObject: {some: 'object'},
});
map(nodeList, callback, {
   toIndex: 100,
});
map(nodeList, callback, {
   thisObject: {some: 'object'},
   fromIndex: 0,
   toIndex: 100,
});

It depends.

Based on my observation on those popular libraries design, here are the scenarios we should use option object:

  • The parameter list is long (>4).
  • Some or all parameters are optional and they don’t rely on a certain order.
  • The parameter list might grow in future API update.
  • The API will be called from other code and the API name is not clear enough to tell the parameters’ meaning. So it might need strong parameter name for readability.

And scenarios to use parameter list:

  • Parameter list is short (<= 4).
  • Most of or all of the parameters are required.
  • Optional parameters are in a certain order. (i.e.: $.get )
  • Easy to tell the parameters meaning by API name.

Object is more preferable, because if you pass an object its easy to extend number of properties in that objects and you don't have to watch for order in which your arguments has been passed.


I may be a little late to the party with this response, but I was searching for other developers' opinions on this very topic and came across this thread.

I very much disagree with most of the responders, and side with the 'multiple arguments' approach. My main argument being that it discourages other anti-patterns like "mutating and returning the param object", or "passing the same param object on to other functions". I've worked in codebases which have extensively abused this anti-pattern, and debugging code which does this quickly becomes impossible. I think this is a very Javascript-specific rule of thumb, since Javascript is not strongly typed and allows for such arbitrarily structured objects.

My personal opinion is that developers should be explicit when calling functions, avoid passing around redundant data and avoid modify-by-reference. It's not that this patterns precludes writing concise, correct code. I just feel it makes it much easier for your project to fall into bad development practices.

Consider the following terrible code:

function main() {
    const x = foo({
        param1: "something",
        param2: "something else",
        param3: "more variables"
    });

    return x;
}

function foo(params) {
    params.param1 = "Something new";
    bar(params);
    return params;
}


function bar(params) {
    params.param2 = "Something else entirely";
    const y = baz(params);
    return params.param2;
}

function baz(params) {
    params.params3 = "Changed my mind";
    return params;
}

Not only does this kind of require more explicit documentation to specify intent, but it also leaves room for vague errors. What if a developer modifies param1 in bar()? How long do you think it would take looking through a codebase of sufficident size to catch this? Admittedly, this is example is slightly disingenuous because it assumes developers have already committed several anti-patterns by this point. But it shows how passing objects containing parameters allows greater room for error and ambiguity, requiring a greater degree of conscientiousness and observance of const correctness.

Just my two-cents on the issue!


For a function that usually uses some predefined arguments you would better use option object. The opposite example will be something like a function that is getting infinite number of arguments like: setCSS({height:100},{width:200},{background:"#000"}).


I would look at large javascript projects.

Things like google map you will frequently see that instantiated objects require an object but functions require parameters. I would think this has to do with OPTION argumemnts.

If you need default arguments or optional arguments an object would probably be better because it is more flexible. But if you don't normal functional arguments are more explicit.

Javascript has an arguments object too. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

참고URL : https://stackoverflow.com/questions/12826977/multiple-arguments-vs-options-object

반응형