Programming

캡슐화 된 익명 함수 구문 설명

procodes 2020. 2. 28. 19:36
반응형

캡슐화 된 익명 함수 구문 설명


요약

JavaScript로 캡슐화 된 익명 함수에 대한 구문의 이유를 설명 할 수 있습니까? 왜 이것이 효과 (function(){})();function(){}();있습니까?


내가 아는데 것을

JavaScript에서 다음과 같은 명명 된 함수를 만듭니다.

function twoPlusTwo(){
    alert(2 + 2);
}
twoPlusTwo();

익명 함수를 만들어 변수에 할당 할 수도 있습니다.

var twoPlusTwo = function(){
    alert(2 + 2);
};
twoPlusTwo();

익명 함수를 만든 다음 대괄호로 묶고 즉시 실행하여 코드 블록을 캡슐화 할 수 있습니다.

(function(){
    alert(2 + 2);
})();

이것은 Greasemonkey 스크립트, jQuery 플러그인 등과 같이 잠재적으로 충돌하는 변수로 현재 범위 또는 전역 범위를 어지럽히 지 않도록 모듈 식 스크립트를 만들 때 유용합니다.

이제 이것이 왜 작동하는지 이해합니다. 대괄호는와 같이 내용을 묶고 결과 만 표시합니다 (나는 그것을 설명하는 더 좋은 방법이 있다고 확신합니다) (2 + 2) === 4.


내가 이해하지 못하는 것

그러나 이것이 왜 똑같이 작동하지 않는지 이해하지 못합니다.

function(){
    alert(2 + 2);
}();

저에게 설명해 주시겠습니까?


로 구문 분석되고 있기 때문에 작동하지 않으며 FunctionDeclaration함수 선언의 이름 식별자는 필수 입니다.

괄호로 묶으면로 평가되며 FunctionExpression함수 표현식의 이름을 지정할 수 있습니다.

문법은 FunctionDeclaration다음과 같습니다.

function Identifier ( FormalParameterListopt ) { FunctionBody }

그리고 FunctionExpressions :

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

보시다시피 Identifier(Identifier opt ) 토큰 FunctionExpression은 선택 사항이므로 이름을 정의하지 않고 함수 표현식을 가질 수 있습니다.

(function () {
    alert(2 + 2);
}());

또는 명명 된 함수 표현식 :

(function foo() {
    alert(2 + 2);
}());

괄호 (공식적으로 그룹화 연산자 라고 함 )는 표현식 만 둘러 쌀 수 있으며 함수 표현식이 평가됩니다.

두 가지 문법 제작은 모호 할 수 있으며 다음과 같이 정확하게 똑같이 보일 수 있습니다.

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

구문 분석기는 표시 되는 컨텍스트 에 따라 a FunctionDeclaration또는 a 인지 알고 있습니다.FunctionExpression

위의 예에서 쉼표 연산자 는 표현식 만 처리 할 수 있으므로 두 번째 표현식은 표현식입니다.

반면에, FunctionDeclarations는 실제로 " Program"코드, 즉 전역 범위 외부 및 FunctionBody다른 함수 내부의 코드를 의미하는 코드 에만 나타날 수 있습니다.

블록 내부의 함수는 다음과 같은 예기치 않은 동작을 유발할 수 있으므로 피해야합니다.

if (true) {
  function foo() {
    alert('true');
  }
} else {
  function foo() {
    alert('false!');
  }
}

foo(); // true? false? why?

위의 코드는 실제로 명령문을 포함 할 수 SyntaxError있기 때문에 실제로는을 생성해야 Block하지만 ECMAScript 스펙은 함수 명령문을 정의하지 않습니다. 그러나 대부분의 구현은 허용되며 두 번째 함수 인 경보를 수행합니다 'false!'.

Mozilla 구현 (Rhino, SpiderMonkey)은 다른 동작을합니다. 이들의 문법에는 비표준 함수 명령문이 포함되어 있습니다. 이는 함수가 s에서 발생하는 구문 분석 시간이 아니라 런타임에 평가됨을 의미합니다 FunctionDeclaration. 이러한 구현에서 첫 번째 함수가 정의됩니다.


함수는 다른 방식으로 선언 될 수 있으며 다음을 비교하십시오 .

1- 변수에 곱한 함수 생성자로 정의 된 함수 곱하기 :

var multiply = new Function("x", "y", "return x * y;");

2- multiply 라는 함수의 함수 선언 :

function multiply(x, y) {
    return x * y;
}

3- 변수에 곱한 함수 표현식 :

var multiply = function (x, y) {
    return x * y;
};

4- 변수에 곱하는 명명 된 함수 표현식 func_name :

var multiply = function func_name(x, y) {
    return x * y;
};

이것은 오래된 질문과 답변이지만 오늘날 많은 개발자들이 루프를 던지는 주제에 대해 설명합니다. 나는 나에게 함수 선언과 함수 표현식의 차이 말할 수있는 자바 스크립트 개발자 후보 내가 인터뷰 한의 수를 셀 수 없다 하고 있는 즉시 호출 함수 표현식이 무엇인지 단서가 없었다 있습니다.

그래도 Premasagar의 코드 스 니펫에 이름 식별자를 부여해도 작동하지 않는다는 매우 중요한 점을 언급하고 싶습니다.

function someName() {
    alert(2 + 2);
}();

이것이 작동하지 않는 이유는 JavaScript 엔진이 이것을 함수 선언으로 해석 한 다음 표현식이 포함되지 않은 완전히 관련이없는 그룹화 연산자로 해석하고 그룹화 연산자 표현식을 포함 해야 하기 때문입니다. JavaScript에 따르면 위의 코드 조각은 다음 코드 조각과 같습니다.

function someName() {
    alert(2 + 2);
}

();

일부 사람들에게 유용 할 수있는 또 다른 지적은 함수 정의 자체를 제외하고 코드의 맥락에서 함수 표현식에 제공하는 이름 식별자는 거의 쓸모가 없다는 것입니다.

var a = function b() {
    // do something
};
a(); // works
b(); // doesn't work

var c = function d() {
    window.setTimeout(d, 1000); // works
};

물론 함수 정의와 함께 이름 식별자를 사용하면 코드 디버깅과 관련하여 항상 도움이되지만 완전히 다른 것입니다 : :-)


큰 답변이 이미 게시되었습니다. 그러나 함수 선언은 빈 완료 레코드를 반환합니다.

14.1.20-런타임 의미론 : 평가

FunctionDeclaration : function BindingIdentifier 형식 ( 매개 변수 ) { FunctionBody }

  1. 정상 완료 (비어 있음)를 반환합니다 .

반환 된 값을 얻는 대부분의 방법은 함수 선언을 함수 표현식으로 변환하기 때문에이 사실은 관찰하기 쉽지 않습니다. 그러나 eval그것을 보여줍니다 :

var r = eval("function f(){}");
console.log(r); // undefined

빈 완료 레코드를 호출하는 것은 의미가 없습니다. 그것이 function f(){}()작동하지 않는 이유 입니다. 실제로 JS 엔진은 그것을 호출하려고 시도하지 않으며 괄호는 다른 문의 일부로 간주됩니다.

그러나 함수를 괄호로 묶으면 함수 표현식이됩니다.

var r = eval("(function f(){})");
console.log(r); // function f(){}

함수 표현식은 함수 객체를 반환합니다. 따라서 다음과 같이 호출 할 수 있습니다 (function f(){})()..


자바 스크립트에서는이를 즉시 호출 된 함수 표현식 (IIFE)이라고 합니다.

함수 표현식으로 만들려면 다음을 수행하십시오.

  1. ()를 사용하여 묶습니다.

  2. 무효 연산자를 배치하기

  3. 변수에 할당하십시오.

그렇지 않으면 함수 정의로 취급되며 다음과 같은 방법으로 함수를 동시에 호출 / 호출 할 수 없습니다.

 function (arg1) { console.log(arg1) }(); 

위의 오류가 발생합니다. 함수 표현식 만 즉시 호출 할 수 있기 때문입니다.

이것은 몇 가지 방법으로 달성 될 수 있습니다 : 방법 1 :

(function(arg1, arg2){
//some code
})(var1, var2);

방법 2 :

(function(arg1, arg2){
//some code
}(var1, var2));

방법 3 :

void function(arg1, arg2){
//some code
}(var1, var2);

방법 4 :

  var ll = function (arg1, arg2) {
      console.log(arg1, arg2);
  }(var1, var2);

위의 모든 것은 즉시 함수 표현식을 호출합니다.


또 다른 작은 말이 있습니다. 코드는 약간만 변경하면 작동합니다.

var x = function(){
    alert(2 + 2);
}();

더 널리 퍼진 버전 대신 위의 구문을 사용합니다.

var module = (function(){
    alert(2 + 2);
})();

vim에서 javascript 파일에 대해 들여 쓰기가 올바르게 작동하지 않았기 때문입니다. vim은 열린 괄호 안의 중괄호를 좋아하지 않는 것 같습니다.


아마도 더 짧은 대답은

function() { alert( 2 + 2 ); }

(익명) 함수 정의 하는 함수 리터럴 입니다 . 표현식으로 해석되는 추가 () 쌍은 최상위 수준이 아니라 리터럴 만 예상됩니다.

(function() { alert( 2 + 2 ); })();

익명 함수 호출 하는 표현식 문있습니다.


(function(){
     alert(2 + 2);
 })();

괄호 안에 전달 된 것은 함수 표현식으로 간주되므로 위의 올바른 구문입니다.

function(){
    alert(2 + 2);
}();

위의 구문은 유효하지 않습니다. Java 스크립트 구문 분석기는 오류를 발생시키는 항목을 찾지 못하므로 함수 키워드 다음에 함수 이름을 찾습니다.


그들은 같은 매개 변수 인수와 함께 사용할 수 있습니다

var x = 3; 
var y = 4;

(function(a,b){alert(a + b)})(x,y)

7로 결과


이러한 추가 괄호는 전역 네임 스페이스와 코드가 포함 된 익명 함수 사이에 추가 익명 함수를 만듭니다. 그리고 다른 함수 안에 선언 된 Javascript 함수는이를 포함하는 부모 함수의 네임 스페이스에만 액세스 할 수 있습니다. 전역 범위와 실제 코드 범위 사이에 추가 개체 (익명 기능)가 있으므로 유지되지 않습니다.


다음과 같이 사용할 수도 있습니다.

! function() { console.log('yeah') }()

또는

!! function() { console.log('yeah') }()

!-neg op는 fn 정의를 fn 표현식으로 변환하므로을 사용하여 즉시 호출 할 수 있습니다 (). 0,fn def또는 사용 동일void fn def

참고 URL : https://stackoverflow.com/questions/1634268/explain-the-encapsulated-anonymous-function-syntax



반응형