문제

나는 폐쇄에 관한 게시물을 읽고 어디에서나 이것을 보았지만, 그것이 어떻게 작동하는지 명확하게 설명 할 수는 없습니다.

// Create a new anonymous function, to use as a wrapper
(function(){
    // The variable that would, normally, be global
    var msg = "Thanks for visiting!";

    // Binding a new function to a global object
    window.onunload = function(){
        // Which uses the 'hidden' variable
        alert( msg );
    };
// Close off the anonymous function and execute it
})();

좋아, 우리는 새로운 익명 함수를 만들고 실행할 것임을 알았습니다. 따라서이 간단한 코드는 작동해야합니다.

(function (msg){alert(msg)})('SO');

내 질문은 여기서 어떤 종류의 마술이 일어날까요? 나는 내가 썼을 때 다음과 같이 생각했다.

(function (msg){alert(msg)})

그런 다음 새로운 이름이없는 함수가 함수 ""(MSG)처럼 생성됩니다.

그러나 왜 이것이 효과가 없습니까?

(function (msg){alert(msg)});
('SO');

왜 같은 줄에 있어야합니까?

나에게 몇 가지 게시물을 가리키거나 설명해 주시겠습니까?

도움이 되었습니까?

해결책

함수 정의 후 세미콜론을 떨어 뜨립니다.

(function (msg){alert(msg)})
('SO');

위는 작동해야합니다.

데모 페이지 : https://jsfiddle.net/e7ooeq6m/

이 게시물에서 이런 종류의 패턴에 대해 논의했습니다.

jQuery 및 $ 질문

편집하다:

당신이 보면 ECMA 스크립트 사양, 함수를 정의 할 수있는 3 가지 방법이 있습니다. (페이지 98, 섹션 13 기능 정의)

1. 기능 생성자 사용

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2. 기능 선언 사용.

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3. 기능 표현

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

따라서 선언과 표현의 차이점은 무엇입니까?

ECMA 스크립트 사양에서 :

functionDeclaration : 함수 식별자 (FormalParameterListOpt) {functionbody}

FunctionExpression : 함수 식별자 로프트 (FormalParameterListOpt) {functionbody}

알면 '식별자'가 있습니다 선택 과목 기능 표현. 식별자를 제공하지 않으면 익명 기능을 만듭니다. 식별자를 지정할 수 없다는 의미는 아닙니다.

이것은 다음이 유효하다는 것을 의미합니다.

var sum = function mySum(a, b) { return a + b; }

중요한 점은 외부가 아닌 Mysum 기능 본문 내부에서만 'Mysum'을 사용할 수 있다는 것입니다. 다음 예를 참조하십시오 :

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

라이브 데모

이것을 비교하십시오

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

이 지식으로 무장하고 코드를 분석해 보겠습니다.

코드가있을 때

    function(msg) { alert(msg); }

당신은 함수 표현식을 만들었습니다. 그리고이 함수 표현식을 괄호 안에 래핑하여 실행할 수 있습니다.

    (function(msg) { alert(msg); })('SO'); //alerts SO.

다른 팁

이를 자체 투자 함수라고합니다.

당신이 전화 할 때 당신이하는 일 (function(){}) 함수 객체를 반환합니다. 당신이 추가 할 때 () 그것에, 그것은 호출되고 신체의 모든 것이 실행됩니다. 그만큼 ; 진술의 끝을 나타냅니다. 그래서 두 번째 호출이 실패하는 이유입니다.

내가 혼란스러운 한 가지는 "()"가 그룹화 연산자라는 것입니다.

다음은 기본 선언 된 기능입니다.

전. 1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

함수는 객체이며 그룹화 할 수 있습니다. 따라서 기능 주위에 파렌을 던지자.

전. 2 :

var message = 'SO';

function foo(msg) {  //declares foo
    alert(msg);
}

(foo)(message);     // calls foo

이제 동일한 함수를 호출하고 오른쪽을 선언하는 대신 기본 대체를 사용하여이를 선언 할 수 있습니다.

전. 삼.

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

마지막으로, 우리는 이름을 사용하지 않기 때문에 그 여분의 foo가 필요하지 않습니다! 기능은 익명 일 수 있습니다.

전. 4.

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

귀하의 질문에 답하기 위해 예제 2로 다시 참조하십시오. 첫 번째 줄은 이름이없는 기능을 선언하고 그룹화하지만 호출하지는 않습니다. 두 번째 줄은 문자열을 그룹화합니다. 둘 다 아무것도하지 않습니다. (빈센트의 첫 번째 예.)

(function (msg){alert(msg)});  
('SO');                       // nothing.

(foo); 
(msg); //Still nothing.

하지만

(foo)
(msg); //works

익명 함수는 이름 ""의 함수가 아닙니다. 단순히 이름이없는 함수입니다.

JavaScript의 다른 값과 마찬가지로 함수는 이름을 만들 필요가 없습니다. 실제로 다른 값과 마찬가지로 이름에 실제로 바인딩하는 것이 훨씬 더 유용합니다.

그러나 다른 값과 마찬가지로, 때때로 이름에 바인딩하지 않고 사용하기를 원합니다. 그것은 자기 침입 패턴입니다.

여기에는 기능과 숫자가 있습니다. 바운드가 아닌 숫자는 없습니다. 아무것도하지 않으며 절대 사용할 수 없습니다.

function(){ alert("plop"); }
2;

따라서 다른 값과 마찬가지로 사용할 수 있도록 변수에 저장해야합니다.

var f = function(){ alert("plop"); }
var n = 2;

구문 설탕을 사용하여 기능을 변수에 바인딩 할 수도 있습니다.

function f(){ alert("plop"); }
var n = 2;

그러나 이름 지정이 필요하지 않으며 혼란과 가독성이 줄어든 경우 즉시 사용할 수 있습니다.

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5

여기에서 내 기능과 숫자는 변수에 바인딩되지 않지만 여전히 사용할 수 있습니다.

이렇게 말하면, 자기 침입 기능은 실제 가치가없는 것처럼 보입니다. 그러나 JavaScrip Scope Delimiter는 블록 ({})이 아니라 기능이라는 점을 명심해야합니다.

따라서 자체 침입 함수는 실제로 C ++, C# 또는 Java 블록과 동일한 의미를 갖습니다. 이는 내부에 생성 된 변수가 범위 밖에서 "누출"되지 않음을 의미합니다. 이것은 전역 범위를 오염시키지 않기 위해 JavaScript에서 매우 유용합니다.

JavaScript가 작동하는 방식입니다. 이름이 지정된 기능을 선언 할 수 있습니다.

function foo(msg){
   alert(msg);
}

그리고 그것을 호출하십시오 :

foo("Hi!");

또는 익명 기능을 선언 할 수 있습니다.

var foo = function (msg) {
    alert(msg);
}

그리고 그것을 부르십시오 :

foo("Hi!");

또는 기능을 이름으로 바인딩 할 수 없습니다.

(function(msg){
   alert(msg);
 })("Hi!");

함수는 또한 함수를 반환 할 수 있습니다.

function make_foo() {
    return function(msg){ alert(msg) };
}

(make_foo())("Hi!");

본문에서 "var"로 정의 된 변수는 아무것도 가치가 없습니다. make_foo 반환 된 각 함수에 의해 닫힙니다 make_foo. 이것은 폐쇄이며, 한 기능에 의해 값에 대한 모든 변경이 다른 함수에 의해 보일 것임을 의미합니다.

원하는 경우 정보를 캡슐화 할 수 있습니다.

function make_greeter(msg){
    return function() { alert(msg) };
}

var hello = make_greeter("Hello!");

hello();

그것은 거의 모든 프로그래밍 언어이지만 Java가 작동하는 방식입니다.

당신이 보여주는 코드,

(function (msg){alert(msg)});
('SO');

구성됩니다 진술. 첫 번째는 함수 객체를 생성하는 표현입니다 (이는 저장되지 않기 때문에 쓰레기가 수집됩니다). 두 번째는 문자열을 생성하는 표현입니다. 함수를 문자열에 적용하려면 문자열을 생성 될 때 (위에 표시 될 때) 함수에 인수로 문자열을 전달해야하거나 실제로 기능을 변수에 저장해야합니다. 나중에 여가 시간에 적용하십시오. 그렇게 :

var f = (function (msg){alert(msg)});
f('SO');

변수에 익명 함수 (Lambda 함수)를 저장하면 효과적으로 이름을 제공합니다. 따라서 정기적 인 기능을 정의 할 수 있습니다.

function f(msg) {alert(msg)};
f('SO');

이전 의견 요약 :

function() {
  alert("hello");
}();

변수에 할당되지 않은 경우 구문 오류가 발생합니다. 코드는 함수 명령문 (또는 정의)으로 구문 분석되며, 이는 닫는 괄호를 구문 적으로 부정하게 만듭니다. 함수 부분 주위에 괄호를 추가하면 통역사 (및 프로그래머)에게 이것이 기능 표현식 (또는 호출)임을 알려줍니다.

(function() {
  alert("hello");
})();

이것은 자체 침입 기능으로 익명으로 생성되고 즉시 실행되므로 호출이 선언 된 동일한 줄에서 발생하기 때문에 즉시 실행됩니다. 이 자체 침입 함수는 친숙한 구문으로 표시되어 연락이없는 함수를 호출하고 기능 이름 주위에 괄호가 추가됩니다. (myFunction)();.

거기 있습니다 좋은 토론 자바 스크립트 함수 구문.

이 답변은 질문과 엄격하게 관련이 없지만 이러한 종류의 구문 기능이 함수에만 해당되지 않는다는 사실을 알기 위해 관심이있을 수 있습니다. 예를 들어, 우리는 항상 다음과 같은 일을 할 수 있습니다.

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

함수와 관련이 있습니다. 기능에서 상속되는 물체이므로 프로토 타입으로 다음과 같은 작업을 수행 할 수 있습니다.

Function.prototype.foo = function () {
    return function () {
        alert("foo");
    };
};

var bar = (function () {}).foo();

bar(); // alerts foo

그리고 우리는 기능을 실행하기 위해 괄호로 기능을 둘러싸는 것조차 필요조차 없습니다. 어쨌든, 우리가 결과를 변수에 할당하려고하는 한.

var x = function () {} (); // this function is executed but does nothing

function () {} (); // syntax error

당신이 기능으로 할 수있는 또 다른 일은 당신이 그들을 선언하자마자 new 연산자를 통해 물체를 얻습니다. 다음은 동일합니다.

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};

JavaScript 함수가있는 속성이 하나 더 있습니다. 동일한 익명 함수를 재귀 적으로 호출하려는 경우.

(function forInternalOnly(){

  //you can use forInternalOnly to call this anonymous function
  /// forInternalOnly can be used inside function only, like
  var result = forInternalOnly();
})();

//this will not work
forInternalOnly();// no such a method exist

Asker의 질문에 대한 나의 이해는 다음과 같습니다.

이 마법은 어떻게 작동합니까?

(function(){}) ('input')   // Used in his example

나는 틀릴 수있다. 그러나 사람들이 친숙한 일반적인 관행은 다음과 같습니다.

(function(){}('input') )

그 이유는 JavaScript가 일명 괄호가 있기 때문입니다 (), 진술을 포함 할 수 없으며 파서가 함수 키워드를 만나면 함수 선언이 아닌 함수 표현식으로 구문 분석하는 것이 알고 있습니다.

출처 : 블로그 게시물 즉시 침입 된 기능 표현 (IIFE)

괄호가없는 예 :

void function (msg) { alert(msg); }
('SO');

(이것은 void의 유일한 실제 사용입니다, Afaik)

또는

var a = function (msg) { alert(msg); }
('SO');

또는

!function (msg) { alert(msg); }
('SO');

일하십시오. 그만큼 void 할당 및 강타뿐만 아니라 표현이 평가를 유발하고 있습니다. 마지막은 함께 작동합니다 ~, +, -, delete, typeof, 일부 외교 연산자 (void 하나입니다)). 작동하지 않는 것은 Couse입니다 ++, -- 변수의 요구 사항으로 인해.

라인 브레이크가 필요하지 않습니다.

자체 실행 익명 기능입니다. 첫 번째 괄호 세트에는 실행할 표현이 포함되어 있으며 두 번째 괄호 세트는 해당 표현식을 실행합니다.

(function () {
    return ( 10 + 20 );
})();

Peter Michaux는 차이점을 논의합니다 중요한 괄호 쌍.

상위 네임 스페이스에서 변수를 숨기려고 할 때 유용한 구성입니다. 함수 내의 모든 코드는 함수의 개인 범위에 포함되어있어 함수 외부에서 전혀 액세스 할 수 없으므로 진정으로 비공개로 만듭니다.

보다:

  1. 클로저 (컴퓨터 과학)
  2. JavaScript 네임 스케이킹
  3. JavaScript 괄호의 중요한 쌍

또 다른 관점

먼저 익명 기능을 선언 할 수 있습니다.

var foo = function(msg){
 alert(msg);
}

그런 다음 당신은 그것을 호출합니다.

foo ('Few');

왜냐하면 foo = function (msg) {alert (msg);} 따라서 교체 할 수 있습니다 foo 처럼:

function(msg){
 alert(msg);
} ('Few');

그러나 구문 분석 할 때 기능을 선언하는 구문 오류를 피하기 위해 한 쌍의 익명 기능을 괄호 안에 랩핑해야합니다. 그러면 우리는

(function(msg){
 alert(msg);
}) ('Few');

이런 식으로, 그것은 나를 쉽게 이해할 수 있습니다.

당신이했을 때 :

(function (msg){alert(msg)});
('SO');

당신은 전에 기능을 끝냈습니다 ('SO') 세미콜론 때문에. 그냥 쓰면 :

(function (msg){alert(msg)})
('SO');

작동합니다.

Working example: http://jsfiddle.net/oliverni/dbvjg/

그것이 작동하지 않는 간단한 이유는 ; 익명 함수의 끝을 나타냅니다. 그것은 없기 때문입니다 () 함수 호출이 끝나면 함수 호출이 아닙니다. 그건,

function help() {return true;}

전화하면 result = help(); 이것은 함수에 대한 호출이며 True를 반환합니다.

전화하면 result = help; 이것은 전화가 아닙니다. 도움이 결과에 할당 될 데이터처럼 취급되는 과제입니다.

당신이 한 일은 세미콜론을 추가하여 익명 기능을 선언/인스턴스화하는 것이 었습니다.

(function (msg) { /* Code here */ });

그런 다음 괄호 만 사용하여 다른 진술에서 호출하려고 시도했습니다. 분명히 함수의 이름이 없기 때문에 이것은 작동하지 않습니다.

('SO');

통역사는 두 번째 줄의 괄호를 새로운 명령/진술로보고 있으므로 다음과 같이 했더라도 작동하지 않습니다.

(function (msg){/*code here*/});('SO');

여전히 작동하지 않지만 통역사가 흰색 공간과 마차를 무시하고 완전한 코드를 하나의 진술로 볼 때 세미콜론을 제거 할 때 작동합니다.

(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');

결론 : 함수 호출은 () 다른 기능에 의해 호출되는 것과 같은 특정 조건에서, 즉, onload = '도움말'은 괄호가 포함되지 않더라도 도움말 기능을 실행합니다. Settimeout과 SetInterval도 이러한 유형의 함수 호출을 허용한다고 생각하며, 인터프리터가 장면 뒤에 괄호를 추가하여 "기능 호출은 괄호가없는 함수 호출이 아닙니다"라고 생각합니다.

(function (msg){alert(msg)})
('SO');

이것은 많은 JavaScript 프레임 워크가 사용하는 클로저로 익명 기능을 사용하는 일반적인 방법입니다.

이 기능은 코드를 컴파일 할 때 자동으로입니다.

배치하는 경우 ; 첫 번째 줄에서 컴파일러는이를 두 개의 다른 라인으로 취급했습니다. 따라서 위와 같은 결과를 얻을 수 없습니다.

이것은 또한 다음과 같이 쓸 수 있습니다.

(function (msg){alert(msg)}('SO'));

자세한 내용은 조사하십시오 JavaScript/익명 함수.

  1. 익명 함수는 런타임에 동적으로 선언 된 함수입니다. 일반 기능과 같은 방식으로 이름이 주어지지 않기 때문에 익명 기능이라고합니다.

    익명 함수는 함수 선언 대신 기능 연산자를 사용하여 선언됩니다. 기능 연산자를 사용하여 표현식을 넣는 데 유효한 곳마다 새 기능을 만들 수 있습니다. 예를 들어 함수 호출에 대한 매개 변수로 새 함수를 선언하거나 다른 객체의 속성을 할당 할 수 있습니다.

    다음은 명명 된 기능의 일반적인 예입니다.

    함수 flytothemoon () {alert ( "Zoom! Zoom! Zoom!"); } flytothemoon (); 익명 기능과 동일한 예는 다음과 같습니다.

    var flytothemoon = function () {alert ( "Zoom! Zoom! Zoom!"); } flytothemoon ();

    자세한 내용은 여기를 참조하십시오.

    http://helephant.com/2008/08/23/javaScript-anonymous-funtions/

iife는 단순히 함수를 구획화하고 숨 깁니다 msg 글로벌 네임 스페이스를 "오염"하지 않도록 변수. 실제로, 당신이 10 억 달러의 웹 사이트를 구축하지 않는 한 간단하게 유지하고 아래에서 좋아합니다.

var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};

당신은 당신을 네임 스페이스 할 수 있습니다 msg a를 사용하는 속성 모듈 패턴 공개 처럼:

var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());

익명의 기능은 귀하가 제공하는 입력에서 출력을 생성 할 수 있도록 즉시 함수를 정의하는 원샷 거래입니다. 입력을 제공하지 않았다는 점을 제외하고. 대신, 당신은 두 번째 줄에 무언가를 썼습니다 ( 'so'). - 기능과 관련이없는 독립적 인 진술. 무엇을 기대 했습니까? :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top