[javascript] 여러 인수와 옵션 개체

여러 인수로 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 개의 매개 변수에만 실제로 적합하지는 않지만 더 좋을 수 있습니다.


답변

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

객체를 생성하면 옵션을 여러 기능에서 쉽게 사용할 수 있습니다.

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

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

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


답변

무언가를 인스턴스화하거나 객체의 메소드를 호출하는 경우 옵션 객체를 사용하고 싶다고 생각합니다. 하나 또는 두 개의 매개 변수에서만 작동하고 값을 반환하는 함수 인 경우 인수 목록이 바람직합니다.

어떤 경우에는 두 가지를 모두 사용하는 것이 좋습니다. 함수에 하나 또는 두 개의 필수 매개 변수와 여러 개의 선택적 매개 변수가있는 경우, 처음 두 개의 매개 변수를 필요로하고 세 번째는 선택적 옵션 해시로 만드십시오.

귀하의 예에서 나는 할 것 map(nodeList, callback, options)입니다. 노드 목록과 콜백이 필요하며 호출을 읽는 것만으로도 상황을 쉽게 알 수 있으며 기존 맵 함수와 같습니다. 다른 옵션은 선택적 세 번째 매개 변수로 전달할 수 있습니다.


답변

질문에 대한 귀하의 의견 :

이 예에서 마지막 3 개는 선택 사항입니다.

그럼 왜 안 해? (참고 : 이것은 상당히 원시적 인 자바 스크립트입니다. 일반적으로 default해시를 사용하고 Object.extend 또는 JQuery.extend 등 을 사용하여 전달 된 옵션으로 업데이트합니다 .)

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

이제 선택 사항과 그렇지 않은 사항이 훨씬 분명해 졌으므로 이러한 기능은 모두 유효합니다.

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,
});


답변

이 답변으로 파티에 조금 늦을 수도 있지만이 주제에 대한 다른 개발자의 의견을 찾고 있었고이 스레드를 발견했습니다.

나는 대부분의 응답자들에 동의하지 않으며 ‘다중 논쟁’접근법과 관련이 있습니다. 나의 주요 주장은 “param 객체의 변경과 반환”또는 “같은 param 객체를 다른 함수에 전달”과 같은 다른 안티 패턴을 사용하지 않는 것입니다. 나는이 안티 패턴을 광범위하게 악용 한 코드베이스에서 일했으며, 이것을하는 디버깅 코드는 빠르게 불가능합니다. Javascript는 강력하게 유형이 지정되지 않았으며 임의로 구조화 된 객체를 허용하기 때문에 이것은 매우 Javascript 고유의 경험 법칙이라고 생각합니다.

필자의 개인적인 의견은 개발자가 함수를 호출 할 때 명시 적이어야하며 중복 데이터를 전달하지 않고 참조 기준 수정을 피해야한다는 것입니다. 이 패턴이 간결하고 정확한 코드 작성을 방해하는 것은 아닙니다. 프로젝트가 나쁜 개발 관행에 훨씬 쉽게 빠질 수 있다고 생각합니다.

다음과 같은 끔찍한 코드를 고려하십시오.

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;
}

이러한 종류의 의도를 명시하기 위해서는보다 명확한 문서가 필요할뿐만 아니라 모호한 오류가 발생할 여지가 있습니다. 어떤 개발자 수정하는 경우 param1bar() ? 이것을 포착하기 위해 충분한 크기의 코드베이스를 살펴 보는 데 얼마나 걸립니까? 물론,이 예제는 개발자들이이 시점에서 이미 여러 가지 안티 패턴을 커밋했다고 가정하기 때문에 약간 불분명합니다. 그러나 매개 변수를 포함하는 객체를 전달하면 오류와 모호성이 더 커질 수 있으며 양심 성과 const 정확성의 준수가 더 필요한 방법을 보여줍니다.

이 문제에 대한 나의 2 센트!


답변

때에 따라 다르지.

인기있는 라이브러리 디자인에 대한 나의 관찰을 바탕으로 옵션 객체를 사용해야하는 시나리오는 다음과 같습니다.

  • 매개 변수 목록이 길다 (> 4).
  • 일부 또는 모든 매개 변수는 선택 사항이며 특정 순서에 의존하지 않습니다.
  • 향후 API 업데이트에서 매개 변수 목록이 커질 수 있습니다.
  • API가 다른 코드에서 호출되며 API 이름이 매개 변수의 의미를 알기에 명확하지 않습니다. 따라서 가독성을 위해 강력한 매개 변수 이름이 필요할 수 있습니다.

매개 변수 목록을 사용하는 시나리오 :

  • 매개 변수 목록이 짧습니다 (<= 4).
  • 대부분 또는 모든 매개 변수가 필요합니다.
  • 선택적 매개 변수는 특정 순서로되어 있습니다. (예 : $ .get)
  • API 이름으로 매개 변수 의미를 쉽게 알 수 있습니다.