다른 함수에서만 사용되는 함수를 해당 함수 내에 배치해야합니까?


30

특히, 나는 JavaScript로 쓰고 있습니다.

기본 함수가 함수 A라고 가정 해 봅시다. 함수 A가 함수 B를 여러 번 호출하지만 함수 B가 다른 곳에서는 사용되지 않는다면 함수 B를 함수 A 내에 두어야합니까?

좋은 습관입니까? 아니면 여전히 기능 B를 기능 A와 동일한 범위에 두어야합니까?

답변:


32

나는 일반적으로 JavaScript에서 중첩 함수를 선호합니다.

  • JavaScript에서 함수의 가시성을 제한하는 유일한 방법은 다른 함수 안에 중첩시키는 것입니다.
  • 헬퍼 함수는 개인용 구현 세부 사항입니다. 같은 범위에 두는 것은 클래스의 개인 함수를 공개하는 것과 유사합니다.
  • 더 일반적으로 사용되는 것으로 판명되면 도우미가 현재 해당 기능 중 하나만 사용하고 있다고 확신 할 수 있기 때문에 쉽게 이동할 수 있습니다. 즉, 코드를보다 응집력있게 만듭니다.
  • 함수 시그니처와 구현을 덜 장황하게 만드는 매개 변수를 종종 제거 할 수 있습니다. 변수를 전역으로 만드는 것과는 다릅니다. 개인 메서드에서 클래스 멤버를 사용하는 것과 비슷합니다.
  • 충돌에 대해 걱정하지 않고 헬퍼 기능에 더 나은 이름을 제공 할 수 있습니다.
  • 도우미 기능을 쉽게 찾을 수 있습니다. 예, 도움을 줄 수있는 도구가 있습니다. 여전히 눈을 화면 위로 조금 올리는 것이 더 쉽습니다.
  • 코드는 자연스럽게 일종의 추상화 트리를 형성합니다. 루트에서 몇 가지 일반적인 기능은 몇 가지 구현 세부 사항으로 나뉩니다. 함수 접기 / 접기 기능이있는 편집기를 사용하는 경우 중첩을 사용하면 동일한 추상화 수준에서 밀접하게 관련된 함수의 계층 구조가 생성됩니다. 따라서 필요한 수준에서 코드를 쉽게 연구하고 세부 사항을 숨길 수 있습니다.

나는 대부분의 프로그래머들이 C / C ++ / Java 전통에서 자랐거나 다른 누군가에 의해 가르쳐 졌다는 사실에서 많은 반대가 생각된다. 중첩 함수는 프로그래밍을 배우면서 많이 노출되지 않았기 때문에 자연스럽게 보이지 않습니다. 그렇다고해서 유용하지 않다는 의미는 아닙니다.


14

여러 가지 이유로 글로벌 범위에 배치해야합니다.

  • 헬퍼 함수를 ​​호출자에 중첩 시키면 호출자의 길이가 증가합니다. 함수 길이는 거의 항상 음의 지표입니다. 짧은 기능은 이해, 암기, 디버그 및 유지 관리가 더 쉽습니다.

  • 도우미 함수의 이름이 알기 쉬운 경우 근처의 정의를 볼 필요없이 해당 이름을 읽는 것으로 충분합니다. 당신이 경우에 호출자가 너무 많이하고있다, 또는 동시에 추상화 너무 많은 수준에 작동하고 있는지 다음, 호출자의 기능을 이해하기 위해 도우미 정의를 볼 필요가있다.

  • 헬퍼를 전역 적으로 사용할 수있게하면 다른 함수가 일반적으로 유용 할 경우이를 호출 할 수 있습니다. 도우미를 사용할 수 없으면 잘라내어 붙여 넣거나 잊어 버린 후 다시 구현하거나, 다른 기능을 이전보다 길게 만들려고합니다.

  • 도우미 함수를 중첩하면 선언하지 않고 호출자의 범위에서 변수를 사용하려는 유혹이 증가하여 도우미의 입력과 출력이 무엇인지 명확하지 않게됩니다. 함수가 작동하는 데이터와 그 영향을 명확하게 나타내지 않으면 일반적으로 불명확 한 책임의 징조입니다. 도우미 엉덩이를 독립형 함수로 선언하면 실제로 수행하는 작업 만 알 수 있습니다.

편집하다

그것은 내가 생각했던 것보다 더 논란의 여지가있는 질문으로 판명되었습니다. 명확히하기 위해 :

JavaScript에서 큰 파일 확장 기능은 언어가 다른 범위 제한 메커니즘을 제공하지 않기 때문에 클래스의 역할을 수행하는 경우가 많습니다. 분명히 도우미 기능은 외부가 아닌 그러한 준 클래스 내부에 있어야 합니다.

그리고 서브 루틴이 경우에 것을 쉽게 재사용 전제에 대한 포인트 않습니다 가 더 널리 사용, 당신은 완전히 장소의 그것을 밖으로 이동하고 적절한 장소, 예를 들어, 문자열 유틸리티 라이브러리 또는 글로벌 구성 레지스트리에 넣어하고자합니다. 만약 당신이 그런 코드를 주문하고 싶지 않다면 ,보다 "고질적 인"언어 로 된 일반적인 Method Object 를 사용하는 것처럼 서브 루틴을 중첩시킬 수도 있습니다.


고마워요 참고로, 일반적으로 어떻게 기능을 주문해야합니까? 예를 들어, 현재는 작은 프로그램으로 알파벳순으로 주문합니다. 그러나 도우미와 호출자 기능을 함께 그룹화해야합니까? 예를 들어 응용 프로그램의 어느 부분에 적용되는지에 따라 기능을 적어도 세분화해야한다고 생각합니까?
게리

나는 오랫동안 메소드 정의를 귀찮게하지 않았다. 어느 정도의 전문성을 사용하여 프로그래밍하는 경우 몇 번의 키 입력만으로도 정의로 바로 이동할 수있는 환경이 있어야합니다. 따라서 짧은 방법은 유용하지만 짧거나 잘 정렬 된 클래스 파일은 거의 가치가 없습니다. (물론 JavaScript는 모든 정의가 그 용도보다 위에 있어야하거나 결과적으로 기술적으로 정의되지 않은 동작이 될 수 있습니다. 여전히 그러한 경우인지 기억 나지 않습니다.)
Kilian Foth

2
이것은 좋은 대답입니다. 캡슐화깨진 문제는 내부 함수를 사용할 때 많은 사람들이 고려하지 않은 문제입니다 .
sbichenko

2
지구본은 코드 냄새입니다. 그것들은 리팩토링을 막는 불필요한 커플 링을 일으키고, 이름 충돌을 일으키고, 구현 세부 사항을 노출시킵니다. 이것은 모든 변수가 변경 가능하고 코드가 일반적으로 제 3 자로부터 직접로드되기 때문에 Javascript에서 특히 나쁩니다 (아직) 광범위하게 사용 가능한 모듈 시스템 또는 "let"의 광범위하게 사용 가능한 구현. 이러한 적대적인 환경에서 우리가 가지고 있는 유일한 방어 전략은 원샷 함수 안에 캡슐화하는 것입니다.
Warbo

1
"클래스의 역할 수행"은 마치 다른 것처럼 JS를 작성하려고합니다. "계급의 역할"은 무엇입니까? 타입 검사? 모듈성? 단계별 컴파일? 계승? 문제는 범위 지정과 관련이 있으므로 클래스의 원유 범위 지정 규칙을 의미한다고 가정합니다. 그것은 단지 벅을 통과시키는 것입니다 : 클래스의 범위 는 어떻게 지정해야 합니까? PHP는 그것들을 전역으로 만들어 캡슐화를 제공하지 않습니다. 파이썬은 클래스를 어휘 적으로 범위를 정하지 만, 어휘 범위 블록에 있다면 왜 모든 클래스 범위 블록에 모든 것을 래핑합니까? JS에는 그러한 중복성이 없습니다. 필요한만큼의 어휘 범위 만 사용하십시오.
Warbo

8

두 함수를 클로저 내에 배치하는 세 번째 경로를 제안하겠습니다. 다음과 같습니다.

var functionA = (function(){
    function functionB() {
        // do stuff...
    }

    function functionA() {
        // do stuff...
        functionB();
        // do stuff...
    }

    return functionA;
})();

우리는 두 함수의 선언을 IIFE 에 래핑하여 클로저를 만듭니다 . IIFE의 반환 값은 공용 함수이며 함수 이름의 변수에 저장됩니다. 퍼블릭 함수는 마치 전역 함수로 선언 된 것과 똑같은 방식으로 호출 할 수 있습니다 functionA(). 반환 값 은 함수 에 대한 호출이 아니라 함수이므로 끝 부분에 구문 분석이 없습니다.

이렇게 두 함수를 래핑하면 functionB이제 완전히 비공개이며 클로저 외부에서 액세스 할 수 없지만에만 표시됩니다 functionA. 그것은 글로벌 네임 스페이스를 어수선하게하지 않는, 그리고 정의의 혼란을하지 않습니다 functionA.


0

함수 A 내에서 함수 B를 정의하면 함수 B가 A의 내부 변수에 액세스 할 수 있습니다.

따라서 함수 A 내에 정의 된 함수 B는 B가 A의 지역 변수를 사용하거나 변경하고 있다는 인상 (또는 적어도 가능성)을 제공합니다. A 외부에서 B를 정의하는 동안 B는 그렇지 않다는 것이 분명해집니다.

따라서 코드의 명확성을 위해 B가 A의 로컬 변수에 액세스해야하는 경우에만 A 내에서 B를 정의합니다. B가 A와 독립적 인 명확한 목적을 가지고 있다면 A 외부에서 분명히 정의합니다.


-1

그렇지 않으면 외부 함수를 호출 할 때마다 중첩 된 함수가 다시 작성되므로 중첩해서는 안됩니다.


-3

함수 B는 다른 곳에서 사용되지 않기 때문에 함수 A 내에서 함수로 만들 수도 있습니다. 그것이 함수의 유일한 이유이기 때문입니다.


1
이것은 이전의 3 가지 답변에서 제시되고 설명 된 점들에 비해 실질적인 어떤 것도 추가하지 않는 것 같습니다
gnat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.