익명 JavaScript 함수 자동 실행을위한 괄호 위치?


107

최근에 json2.js 의 현재 버전을 프로젝트에있는 버전과 비교 했는데 함수 표현식이 생성되고 자체 실행되는 방식에 차이가 있음을 발견했습니다.

익명 함수를 괄호로 묶은 다음 실행하는 데 사용되는 코드,

(function () {
  // code here
})();

하지만 이제는 자동 실행 함수를 괄호로 묶습니다.

(function () {
  // code here
}());

의 허용 대답 CMS에 의해 주석이 자바 스크립트의 캡슐화 된 익명 함수 구문을 설명 하는 것이 "모두 : (function(){})();와이 (function(){}());. 유효은"

차이점이 무엇인지 궁금합니다. 전자가 전역 익명 함수를 떠나 메모리를 차지합니까? 괄호는 어디에 있어야합니까?



관련 : 즉시 함수 호출 구문 (JSLint)
Bergi

1
또한 읽어 이 구조의 목적 , 또는 (검사 기술 ) 설명 (도 여기에 ). 괄호가 필요한 이유는 이 질문을 참조하십시오 .
Bergi

답변:


66

거의 동일합니다.

첫 번째는 함수를 괄호로 묶어 유효한 표현식으로 만들고 호출합니다. 식의 결과가 정의되지 않았습니다.

두 번째는 함수를 실행하고 자동 호출을 괄호로 묶어 유효한 표현식이됩니다. 또한 정의되지 않은 것으로 평가됩니다.

표현의 결과가 같기 때문에 "올바른"방법이 없다고 생각합니다.

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"

8
JSLint는 "(function () {} ());"을 원합니다. JSLint는 "함수를 포함하는 괄호로 호출을 이동하십시오."라고 말합니다.
XP1 2011

27
실제로이 두 가지에만 국한되지 않고 컴파일러가 함수가 +function(){}()또는 문이 아니라 표현식의 일부임을 인식하게하는 거의 모든 것을 사용할 수 있습니다 !function(){}().
Tgr

49
@ XP1 : JSLint는 실질적인 것이 아니라 Crockford의 스타일에 특정한 많은 것을 원합니다 . 이것은 그들 중 하나입니다.
TJ Crowder

@TJCrowder. 어떤 것을 권 하시죠? jQuery는 첫 번째 스타일을 사용하고 Crockford는 두 번째 스타일을 사용합니다.
Teej 2012

4
@ThorpeObazee : 진심으로 중요하지 않으므로 원하는대로하세요. 나는 좀 더 외진 적 인 것 ( -function(){}();, !function(){}();및 기본적으로 function작동 하기 직전에 다른 모든 연산자 에 대해 권장 하지만 괄호를 사용하는 버전을 고수합니다). 나는 두 번째보다 첫 번째를 더 많이 봅니다. 나에게도 더 이해가되지만 주관적입니다. FWIW : jsbin.com/ejaqow
TJ 크라우

13

그 경우는 중요하지 않습니다. 첫 번째 정의에서는 함수로 해석되는 표현식을 호출하고 두 번째 예제에서는 함수를 정의하고 즉시 호출합니다. 첫 번째 예제의 함수 표현식은 함수 정의 일 뿐이므로 비슷합니다.

함수로 확인되는 표현식을 호출하는 데 분명히 유용한 다른 경우가 있습니다.

(foo || bar)()

3
다른 독자들에게 설명하기 위해 (주로 내가 처음에는 이해하지 못했기 때문에 :)), foo 및 / 또는 bar는 이미 일부 기능과 동일해야합니다. (예 foo = function(){alert('hi');}. 만약 둘은 기능없는 오류가 발생합니다.
알렉산더 새

3
@AlexanderBird 추가 설명- foo"truthy"이지만 함수가 아닌 경우 오류가 발생 합니다.
JLRishe

9

구문 외에는 차이가 없습니다.

두 번째 방법에 대한 우려 사항 :

치다:

(function namedfunc () { ... }())

namedfunc이름을 제공 했더라도 여전히 전역 범위에 포함되지 않습니다. 익명 함수도 마찬가지입니다. 해당 범위에서 가져 오는 유일한 방법은 괄호 안의 변수에 할당하는 것입니다.

((namedfunc = function namedfunc () { ... })())

바깥 쪽 괄호는 필요하지 않습니다.

(namedfunc = function namedfunc () { ... })()

하지만 어쨌든 그 글로벌 선언을 원하지 않으 셨죠?

따라서 다음과 같이 요약됩니다.

(function namedfunc () { ... })()

그리고 당신은 그것을 더 줄일 수 있습니다 : 이름은 결코 사용되지 않기 때문에 불필요합니다 (당신의 함수가 재귀 적이 지 않는 한 .. 그리고 심지어 당신이를 사용할 수 있지 않는 한 arguments.callee)

(function () { ... })()

그것이 제가 생각하는 방식입니다 (아직 ECMAScript 사양을 읽지 않았을 수도 있습니다). 도움이되기를 바랍니다.


참고 arguments.calleeES5부터 사용되지 않습니다 (및 엄격한 모드 금지)된다.
nyuszika7h

"외부 괄호는 불필요합니다."-파일이 연결될 때 오류를 방지한다고 생각합니다. 그렇지 않으면! 또는 뭔가.
Jimmyt1988

-3

Douglas Crockford IIFE 의 첫 번째 스타일을 좋아하지 않기 때문에 차이점이 존재합니다 ! (진심으로) 이 영상에서 보시다시피 !! .

추가 래핑 (){in both styles}이 존재하는 유일한 이유 는 Function Declaration 을 즉시 호출 할 수 없기 때문에 코드의 해당 섹션을 Function Expression으로 만드는 것입니다 . 일부 스크립트 / 바로 사용 작게하다는-ERS , , & 대신 너무 괄호를. 이렇게 :+!-~

+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();

그리고이 모든 것은 당신의 대안과 똑같습니다. 이러한 경우를 선택하는 것은 전적으로 본인이 결정하며 차이가 없습니다. { 1 바이트 더 큰 파일()생성 하는 것 ;-)}

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