함수를 반환하는 함수


109

나는 '함수를 반환하는 함수'라는 개념을 고수하고 있습니다. 저는 Stoyan Stefanov의 'Object Oriented Javascript'라는 책을 참조하고 있습니다.

스 니펫 1 :

    function a() {
      
        alert('A!');
    
        function b(){
            alert('B!'); 
        }
    
        return b();
    }
    
    var s = a();
    alert('break');
    s();

산출:

A!
B!
break

스 니펫 2

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b;
}

var s = a();
alert('break');
s();
산출:

A!
break
B!

누군가 가 위의 스 니펫에서 반환 b과 차이를 말해 줄 수 있습니까 b()?


2
첫 번째 스 니펫이 s ();
weirdalsuperfan

답변:


121

함수에 변수를 할당하면 (괄호없이) 함수에 대한 참조가 복사됩니다. 함수 이름 끝에 괄호를 넣으면 함수를 호출하여 함수 반환 값을 반환합니다.

데모

function a() {
    alert('A');
}
//alerts 'A', returns undefined

function b() {
    alert('B');
    return a;
}
//alerts 'B', returns function a

function c() {
    alert('C');
    return a();
}
//alerts 'C', alerts 'A', returns undefined

alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());

귀하의 예에서는 함수 내에서 함수를 정의하고 있습니다. 예 :

function d() {
    function e() {
        alert('E');
    }
    return e;
}
d()();
//alerts 'E'

이 함수는 여전히 호출 가능합니다. 여전히 존재합니다. 이것은 JavaScript에서 항상 사용됩니다. 기능은 주위에 전달 될 수있는 단지 다른 값처럼. 다음을 고려하세요:

function counter() {
    var count = 0;
    return function() {
        alert(count++);
    }
}
var count = counter();
count();
count();
count();

함수 개수는 외부에 정의 된 변수를 유지할 수 있습니다. 이것을 클로저라고합니다. JavaScript에서도 많이 사용됩니다.


스 니펫 1 : var hero = {name : 'Rafaelo', sayName : function () {return hero.name; }, nayName : hero.sayName} hero.nayName (); 스 니펫 2 : var hero = {name : 'Rafaelo', sayName : function () {return hero.name; }, nayName : this.sayName} hero.nayName (); 첫 번째 스 니펫은 올바른 출력을 제공하지만 두 번째 스 니펫은 그렇지 않습니다. 왜? 문안 인사.
Cafecorridor

this함수 본문 내부의 무언가를 의미하고 그렇지 않으면 전역 적입니다. 당신이 말하는 것은 존재하지 않는 this.sayName전역 변수 sayName를 원한다는 것입니다. 정의되지 않았으므로 호출 할 수 없습니다.
kzh

7
나는 d () (); 처음에는 첫 번째 ()가 d를 호출하고 두 번째 ()가 d의 반환 값인 e를 호출한다는 것을 깨달았습니다.
skud

1
8 년이 지난 지금도 여전히 관련이 있습니다!
Brad Vanderbush

45

없이 함수 이름을 ()반환 하면 함수에 대한 참조가 반환되며 var s = a(). s이제 함수에 대한 참조가 포함 b()되며 호출 s()은 기능적으로 호출과 동일합니다 b().

// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;

()return 문에서 함수를 호출하면 함수가 실행되고 함수에서 반환 된 값이 반환됩니다. 호출과 비슷 var x = b();하지만 반환 값을 할당하는 대신 b()호출 함수에서 반환합니다 a(). 함수 b()자체가 값을 반환하지 않으면에서 undefined다른 작업을 수행 한 후 호출이 반환 됩니다 b().

// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;

1
모든 답변 중 단순성으로 인해 귀하의 답변이 더 마음에 들었습니다.
anar khalilov 2013 년

잘 했어! 이 답변을 이해하기 매우 쉽습니다.
AndrewSteinheiser

함수가 호출이 정의되지 않은 값을 반환하지 않는지에 대한 비트를 확인해 주셔서 감사합니다. 최근에이 문제를 발견했습니다. 함수가 명시 적으로 null을 반환하더라도 반환 된 값을 변수에 할당하면 null이 아니라 정의되지 않습니다. null과 undefined가 ===와 절대적으로 동일하지 않기 때문에 이것이 일부 코드베이스에서 많은 이상한 문제를 일으켰다 고 생각합니다.
Benjamin

37

return b(); b () 함수를 호출하고 그 결과를 반환합니다.

return b; 나중에 호출하기 위해 변수에 저장할 수있는 함수 b에 대한 참조를 반환합니다.


17

반환 b은 함수 객체를 반환하는 것입니다. 자바 스크립트에서 함수는 다른 객체와 마찬가지로 객체 일뿐입니다. 도움이되지 않는다면 "object"라는 단어를 "thing"으로 바꾸십시오. 함수에서 모든 객체를 반환 할 수 있습니다. 참 / 거짓 값을 반환 할 수 있습니다. 정수 (1,2,3,4 ...). 문자열을 반환 할 수 있습니다. 여러 속성이있는 복잡한 개체를 반환 할 수 있습니다. 그리고 함수를 반환 할 수 있습니다. 기능은 단지 일입니다.

귀하의 경우, b반환은 사물을 반환하고 사물은 호출 가능한 함수입니다. 반환 b()은 호출 가능한 함수에서 반환 한 값을 반환합니다.

이 코드를 고려하십시오.

function b() {
   return 42;
}

위의 정의를 사용하여 return b();값 42를 반환합니다. 반면 return b;에 자체적으로 42 값을 반환하는 함수를 반환합니다. 두 가지 다른 것입니다.


4
반환해야합니다 42;)
c69

4

를 반환하면 b함수 b에 대한 참조 일뿐 현재 실행되지는 않습니다.

를 반환 b()하면 함수를 실행하고 그 값을 반환합니다.

시도 alert보내고 typeof(s)당신의 예에. 스 니펫 b는 '기능'을 제공합니다. 스 니펫은 무엇을 제공합니까?


첫 번째는 '정의되지 않음'을 제공합니다. 그것은 return b ()가 완전히 쓸모 없다는 것을 의미합니까? 또한 두 번째 스 니펫에서 함수 b는 비공개입니다. 그러면 함수 외부의 참조에 어떻게 액세스 할 수 있습니까? 가능하면이 개념을 명확하게 설명하는 링크를 제공해주세요. 감사!
Cafecorridor 2011 년

나는 첫 번째 답을 얻었다. 함수 b ()에서 1 + 2를 반환하고 typeof는 숫자를 보여줍니다. 감사.
Cafecorridor 2011 년

알아 내서 기뻐요! private 함수의 경우 : 이미 반환 했으므로 두 번째 예제에서는 실제로 비공개가 아닙니다. 실제로 s. 하지만 return this대신 시도해보십시오 return b… 그러면 할 수있을 것입니다 s.b();)
vzwick

나는 그것을 확실히 시도 할 것이다. 아직 Javascript에서이 개념에 도달하지 못했습니다. 아마도 며칠 후에. 감사! :)
Cafecorridor

function a () {alert ( "A!"); function b () {alert ( "B!"); } return b; } var s = a (); 삭제 a; 에스(); ---- end ---- Javascript의 참조 개념이 Java와 동일합니까? 여기서는 a () 함수를 삭제했지만 s () 호출은 b ()를 실행합니다. 그래서 s에 b의 복사본이 있고 a ()에 정의 된 b ()를 가리 키지 않는다고 말할 수 있습니까?
Cafecorridor

2

함수를 int와 같은 유형으로 상상해보십시오. 함수에서 int를 반환 할 수 있습니다. 함수도 반환 할 수 있으며 "함수"유형의 개체입니다.

이제 구문 문제 : 함수가 값을 반환하기 때문에 반환 값이 아닌 함수를 어떻게 반환 할 수 있습니까?

괄호를 생략하여! 괄호가 없으면 함수가 실행되지 않기 때문입니다! 그래서:

return b;

"함수"를 반환합니다 (숫자를 반환하는 것처럼 상상해보세요).

return b();

먼저 함수 실행 한 다음 실행하여 얻은 값 반환하는 것은 큰 차이입니다!


두 번째 스 니펫에서 함수 b는 비공개입니다. 그러면 함수 외부의 참조에 어떻게 액세스 할 수 있습니까? 동일하게 적용되는 규칙이 있습니까?
Cafecorridor 2011 년

JavaScript의 객체 (함수 포함)는 공유하는 경우 더 이상 비공개가 아닙니다.
kzh

@Cafecorridor : private 함수가 무언가 (공용 함수)에 의해 반환되거나 공용 변수 (응용 프로그램에서 액세스 할 수있는 변수)에 할당 된 경우 쉽게 yourvariable (); , 그렇지 않으면 반환 된 함수를 변수에 할당하고 다시 수행 yourvariable ();
Francesco Belladonna

2

변수 만들기 :

var thing1 = undefined;

함수 선언 :

function something1 () {
    return "Hi there, I'm number 1!";
}

(첫 번째 변수) 의 을 경고합니다 thing1.

alert(thing1); // Outputs: "undefined".

이제 함수에 thing1대한 참조가 되고 싶다면 something1, 생성 된 함수와 같은 일이 될 것입니다.

thing1 = something1;

그러나 함수 의 return 을 원한다면 실행 된 함수의 반환 값을 할당해야합니다. 괄호를 사용하여 함수를 실행합니다.

thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!" 

-1

스 니펫 1 :

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b(); //return nothing here as b not defined a return value
}

var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain

'b ()'문은 'B!'라는 텍스트가있는 대화 상자를 표시하는 'b'라는 함수를 실행하는 것을 의미합니다.

문 'return b ();' 'b'라는 함수를 실행 한 다음 'b'가 반환하는 함수를 반환하는 것을 의미합니다. 그러나 'b'는 아무것도 반환하지 않으며이 문 'return b ()'도 반환하지 않습니다. b ()가 숫자를 반환하면 'return b ()'도 숫자입니다.

이제 's'에는 'a ()'가 반환하는 값이 할당되며, 이는 'b ()'를 반환합니다. 이것은 아무것도 아닙니다. 따라서 's'는 아무것도 아닙니다 (JavaScript에서는 실제로는 사물이며 '정의되지 않음'입니다. 's'가 어떤 데이터 유형인지 해석하도록 JavaScript에 요청하면 JavaScript 인터프리터는 's'가 정의되지 않음을 알려줍니다.) 's'가 정의되지 않았으므로 JavaScript에이 명령문 's ()'를 실행하도록 요청할 때, 당신은 자바 스크립트에 's'라는 이름의 함수를 실행하도록 요청하고 있는데, 여기서 's'는 함수가 아닌 '정의되지 않음'입니다. 그래서 자바 스크립트는 "야, s는 함수가 아닙니다. to do with this s ","Uncaught TypeError : s is not a function "오류 메시지가 JavaScript에 표시됩니다 (Firefox 및 Chrome에서 테스트 됨).


스 니펫 2

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b; //return pointer to function b here
}

var s = a();  //s get the value of pointer to b
alert('break');
s(); // b() function is executed

이제 'b'라는 함수에 대한 포인터 / 별칭을 반환하는 함수 'a'. 따라서 's = a ()'를 실행할 때 's'는 b를 가리키는 값을 얻습니다. 즉, 's'는 이제 'b'의 별칭이고 's'를 호출하면 'b'를 호출하는 것과 같습니다. 즉 's'는 이제 함수입니다. 's ()'실행은 'b'함수를 실행하는 것을 의미합니다 ( 'b ()'실행과 동일), 'B!'를 표시하는 대화 상자 나타날 것입니다 (즉, 'alert ('B! '); 함수'b '에서 명령문 실행).


-2

이것은 실생활에서 매우 유용합니다.

Express.js 작업

따라서 일반 express경로는 다음과 같습니다.

function itWorksHandler( req, res, next ) {
  res.send("It works!");
}

router.get("/check/works", itWorksHandler );

그러나 래퍼, 오류 처리기 또는 smth를 추가해야하는 경우 어떻게해야합니까?

그런 다음 래퍼에서 함수를 호출합니다.

function loggingWrapper( req, res, next, yourFunction ) {
  try {
    yourFunction( req, res );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", function( req, res, next ) {
  loggingWrapper( req, res, next, itWorksHandler );
});

복잡해 보입니까? 글쎄, 이건 어때?

function function loggingWrapper( yourFunction ) => ( req, res, next ) {
  try {
    yourFunction( req, res, next );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", loggingWrapper( itWorksHandler ) );

당신이 함수를 전달하는 말에보기 loggingWrapper서로 함수로 인수 가지고 itWorksHandler, 그리고 loggingWrapper반환합니다 새 함수 req, res, next인수로합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.