자바 스크립트 함수 최고의 뱅! 통사론


204

나는 지금 몇 가지 라이브러리 에서이 구문을 보았으며 이점이 무엇인지 궁금합니다. (폐쇄에 대해 잘 알고 있으며 코드가 수행하는 작업을 잘 알고 있지만 구문상의 차이점에 대해서만 걱정하고 있습니다)

!function(){
  // do stuff
}();

보다 일반적인 대안으로

(function(){
  // do stuff
})();

익명 함수 자체 호출

몇 가지 궁금합니다. 우선, 가장 좋은 예가 실제로 작동하는 것은 무엇입니까? 이 문장이 구문 적으로 정확하도록하기 위해 왜 강타가 필요한가? 나는 또한 그 +효과가 있다고 들었고 대신 다른 사람들도 확신합니다.!

둘째, 장점은 무엇입니까? 내가 말할 수있는 것은 그것이 단일 캐릭터를 절약한다는 것입니다. 그러나 그것이 수많은 입양자를 유치하는 것이 큰 이점이라고 상상할 수 없습니다. 내가 놓친 다른 이점이 있습니까?

내가 볼 수있는 유일한 다른 차이점은 자체 호출 함수의 반환 값이지만 두 예제 모두 클로저를 만드는 데만 사용되므로 함수의 반환 값에 대해서는 신경 쓰지 않습니다. 누군가 왜 첫 번째 구문을 사용할 수 있는지 말해 줄 수 있습니까?


프레임 워크는 축소자가 최적화 할 수없는 문자를 최대한 많이 저장하는 것을 좋아합니다.
alex

첫 번째 이점은 내 머리에 온다. (function ($) {...}) (jQuery);
JS 테일러

2
두 예제 모두 이것을 달성합니다. 언급했듯이, 나는이 기능들이 무엇을하는지 이해하고 있으며, 나는 구문상의 차이에 더 관심이있다
brad

8
나는 이전 승무원보다 더 세련된 방식으로 귀여워 야한다는 필요성에 기인했습니다. "아, 그 괄호가없는 이방인들, 우리는 !!"
러드 패리쉬

2
나는 이것에 대해 전혀 몰랐다. 나는 !그것이 집행되고 있음을 강조하기 때문에 좋아한다 .
cdmckay

답변:


97

이상적으로는이 모든 것을 다음과 같이 간단하게 수행 할 수 있어야합니다.

function(){
  // do stuff
}(); 

이것은 익명 함수를 선언하고 실행하는 것을 의미합니다. 그러나 JS 문법의 특성으로 인해 작동하지 않습니다.

이것을 달성하는 가장 짧은 형태는 UnaryExpression (그리고 CallExpression)과 같은 표현식을 사용하는 것입니다.

!function(){
  // do stuff
}(); 

또는 재미를 위해 :

-function(){
  // do stuff
}(); 

또는:

+function(){
  // do stuff
}(); 

또는:

~function(){
  // do stuff
  return 0;
}( );

3
그럼 유일한 장점은?
brad


5
표현할 것입니다. 한 번 실행되는 경우 속도는 실제로 중요하지 않습니다.
c-smile

1
호기심으로, 나는 bang and bang이 가장 빠른 성능을 보이지는 않지만 Chrome의 진화에서 어딘가에서 bang이 no bang보다 빠르다는 것을 알았습니다. (아마 통계적으로 무의미하지만 ...) 이유가 있습니까? 나는 후드 아래의 코드에 대해 많이 알지 못하지만 매우 흥미 롭습니다.
jmk2142

세미콜론이 없으면 두 개의 단항 연산자를 이진으로 해석 할 수 있습니다. 첫 번째와 마지막이 가장 안전합니다.

73

Javascript에서으로 시작하는 줄 function은 함수 명령문 으로 예상되며 다음과 같이 보입니다.

function doSomething() {
}

다음과 같은 자체 호출 기능

function(){
  // do stuff
}();

해당 형식에 맞지 않으며 함수 이름이 없으므로 첫 번째 여는 paren에서 구문 오류가 발생하므로 대괄호는 익명 함수 expression을 나타내는 데 사용됩니다 .

(function(){
  // do stuff
})();

그러나 (함수 문과 달리) 식을 만드는 것은 무엇이든 할 것입니다. ! . 이것은 인터프리터에게 이것이 함수 문장이 아니라고 말하고 있습니다. 그 이외의 연산자 우선 순위는 부정 전에 함수가 호출되도록 지시합니다.

나는이 관습을 알지 못했지만 그것이 일반적이되면 가독성에 기여할 수있다. 내가 의미하는 바는 !function큰 코드 블록의 상단에서를 읽는 사람 은 우리가 볼 때 이미 똑같이 기대하는 방식으로 자체 호출을 기대한다는 것 (function입니다. 그 성가신 괄호를 잃어 버릴 것입니다. 속도 나 캐릭터 수의 절감과는 반대로 이것이 바로 그 이유라고 생각합니다.


이 "함수로 시작하는 줄은 예상된다 ..."는 매우 희미 해 보인다. var foo = {CR/LF here} function bar() {}
c-smile

45

이미 언급 된 것 외에도! 세미콜론없이 자바 스크립트를 작성하는 경우 유용합니다.

var i = 1
!function(){
  console.log('ham')
}()

i = 2
(function(){
  console.log('cheese')
})()

첫 번째 예제는 예상대로 'ham'을 출력하지만 두 번째 괄호로 인해 i = 2 문이 종료되지 않기 때문에 두 번째 오류가 발생합니다.

또한 연결된 자바 스크립트 파일에서 앞의 코드에 세미콜론이 누락 되어도 걱정할 필요가 없습니다. 따라서 일반적인; (function () {}) (); 자신의 휴식을 취하기 위해.

내 답변이 늦다는 것을 알고 있지만 아직 언급되지 않았다고 생각합니다.)


6
팁과 추억에 +1 ... 요즘 세미콜론없이 자바 스크립트를 작성하는 사람은 없습니다.
Pablo Grisafi

4
트위터 부트 스트랩은 세미콜론이없는 모든 JS이며, 매우 새롭습니다 ... (위의 의견이 비꼬는 경우 미안하고 그것을 놓친 경우).
brandwaffle

2
이것은 사실이 아닙니다. 다음 예제를 고려하십시오.! function () {console.log ( "ham");} ()! function () {console.log ( "cheese")} (); "SyntaxError : 예기치 않은 토큰!"오류가 발생합니다.
heavysixer

네, 맞아요. 같은 줄에 넣으면 오류가 있습니다. 나는 그것에 대해 생각하지 않았다. 그러나 지금까지 사용한 연결 스크립트 / lib는 없습니다. 그리고 파일을 축소 및 연결하면 세미콜론이 추가됩니다. 솔직히 말해서, 당신이 그 문제에 부딪친 사례를 상상할 수 없습니다. 다른 한편으로, 여기 2am이고 나는 무지 할지도 모른다 :)
Smoe

6

우선 jsPerf는 !(UnaryExpression)을 사용하는 것이 일반적으로 더 빠르다 는 것을 보여줍니다 . 때때로 그들은 평등하게 나오지만, 그렇지 않을 때, 나는 다른 사람보다 뱅킹되지 않은 하나의 승리를 아직 많이 보지 못했습니다 : http://jsperf.com/bang-function

이것은 가장 오래된 (예 :.) Chrome 버전 8의 최신 Ubuntu에서 테스트되었으므로 결과는 다를 수 있습니다.

편집 : 어떻 delete습니까?

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

또는 void?

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

흥미 롭다! Safari에서 속도가 빠르지 만 뱅킹되지 않은 것은 확실히 50/50입니다. 잠재적 속도 차이에 대한 이론이 있는지 궁금합니다.
brad

@brad 사파리와 관련이 있어야합니다. 테스트를 보면 대부분의 다른 브라우저가 선호하는 것 같습니다 !. 그러나 나는 또한 이것에 대한 이론을 찾고 싶습니다 :)
Shaz

3
무효와 같은 내가 그것을 명시 적으로 "내가 반환 값에 대한 상관 없어"라고하고, 다른 언어의 규칙을 생각 나게하기 때문에 때문에
code_monk

4

여기 에서 볼 수 있듯이 자바 스크립트에서 자체 호출 된 메소드를 수행하는 가장 좋은 방법은 다음을 사용하는 것입니다.

(function(){}()); -> 76,827,475 ops/sec

!function(){}();  -> 69,699,155 ops/sec

(function(){})(); -> 69,564,370 ops/sec

1
성능이 하나의 구문 또는 다른 구문을 사용해야하는 이유는 의심 스럽습니다. 70M ops / sec에서 클로저 선언은 어쨌든 내부 코드보다 수천 배 빠를 것입니다.
Eloims

3

따라서 부정 "!" +,-, ~, delete, void와 같은 다른 모든 단항 연산자는 요약하면 다음과 같습니다.

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

또는

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

또는

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

그리고 재미를 위해 바이너리 연산자 를 사용하는 몇 가지 경우가 더 있습니다. :)

1 > function() {
   alert("Hi!"); 
}();

또는

1 * function() {
   alert("Hi!"); 
}();

또는

1 >>> function() {
   alert("Hi!"); 
}();

또는

1 == function() {
   alert("Hi!"); 
}();

다른 사람을 위해 삼항을 떠나기 :)


12
0?0:function() { alert("Hi!"); }();
daniel1426

빙고, 댄! 우리는 삼항 하나;)
Arman McHitarian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.