이 JavaScript / jQuery 구문은 어떻게 작동합니까 : (function (window, undefined) {}) (window)?


153

jQuery 1.4 소스 코드를 살펴본 후 다음과 같은 방식으로 캡슐화되는 방법을 살펴 보았다.

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

JavaScript Namespacing 에 대한 기사 와 " Parens of Parens "라는 다른 기사를 읽었 으므로 여기서 무슨 일이 일어나고 있는지 알 수 있습니다.

그러나 나는이 특정 구문을 본 적이 없다. 무엇이다 undefined이 일을? 그리고 왜 window지나 가서 다시 끝에 나타나야 하는가?


3
Paul Irish가이 비디오에서 이에 대해 이야기하고 싶다고 덧붙이고 싶습니다
Mottie

@ Bergi 내 질문을 다른 질문으로 복제했지만 거의 1 년 전에 질문을했습니다. 캐스트는 다른 방향이어야합니다.
dkinzer

@ dkinzer : 그것은 초기에 묻는 것이 아니라 최고 품질의 답변에 관한 것입니다. 분명히이 경우에는 목과 목이지만 CMS의 답변이 가장 좋은 것으로 나타났습니다. 이 내용 을 논의하기 위해 chat.stackoverflow.com/rooms/17방문하십시오
Bergi

답변:


161

정의되지 않은 변수는 일반 변수이며으로 간단히 변경할 수 있습니다 undefined = "new value";. 따라서 jQuery는 정의되지 않은 로컬 "정의되지 않은"변수를 만듭니다.

창 변수는 성능상의 이유로 로컬로 만들어집니다. JavaScript는 변수를 찾을 때 변수 이름을 찾을 때까지 로컬 변수를 먼저 통과합니다. 발견되지 않으면 JavaScript는 전역 변수를 통해 필터링 할 때까지 다음 범위 등을 거칩니다. 따라서 창 변수를 로컬로 만들면 JavaScript가 더 빨리 찾을 수 있습니다. 추가 정보 : JavaScript 속도 향상-Nicholas C. Zakas


1
감사! 매우 유익한 비디오였습니다. "창 변수가 로컬로 만들어졌습니다"라고 응답을 편집해야한다고 생각합니다. 이것이 가장 좋은 대답이라고 생각합니다. JQuery 소스 코드에서 window 객체가 적어도 17 번 호출되었다는 것을 계산하고 발견했습니다. 따라서 창을 로컬 범위로 옮기는 데 큰 영향을 미칩니다.
dkinzer

@ DKinzer 아, 물론 당신은 rght입니다. 물론 로컬로 만들어졌습니다. 기꺼이 도와 드리겠습니다 =)
Vincent

1
이 업데이트 된 테스트에 따르면 jQuery를 통해 창 상수를 얻을 때 특히 'Safari'에 나쁜 경우 'window'를 전달하는 jsperf.com/short-scope/5 가 실제로 느립니다. 따라서 '정의되지 않음'에 유스 케이스가 있지만 '창'이 모든 경우에 특히 유용하다는 확신은 없습니다.
hexalys

1
또한 코드 축소에 긍정적 인 영향을 미칩니다. 따라서 "창"및 "정의되지 않은"의 모든 사용법은 축소 기에서 더 짧은 이름으로 바꿀 수 있습니다.
TLindig

2
@ lukas.pukenis 수백만 개의 웹 사이트에서 사용되는 라이브러리를 만들 때 미친 사람들이 무엇을 할 것인지에 대해 가정하지 않는 것이 좋습니다.
JLRishe

54

찾으시는 주소가 없습니다

undefined인수 로 선언 하지만 값을 전달하지 않으면 전역 범위에서 단순히 덮어 쓸 수있는 변수이기 때문에 항상 정의되지 않습니다. 이렇게하면 몇 가지 문자를 절약 할 수 a === undefined있는 안전한 대안이됩니다 typeof a == 'undefined'. 또한 코드를 더 undefined축소하기 쉽게 만들 수 있습니다. u예를 들어 몇 문자를 더 절약 할 수 있습니다.

창문

window인수로 전달 하면 로컬 범위에 사본이 보관되어 성능에 영향을줍니다 ( http://jsperf.com/short-scope) . 에 대한 모든 액세스 window는 이제 스코프 체인보다 한 단계 아래로 이동해야합니다. 와 마찬가지로 undefined로컬 사본을 다시 사용하면보다 적극적인 축소가 가능합니다.


사이드 노트 :

이것이 jQuery 개발자의 의도가 아닐 수도 있지만, 전달 window하면 라이브러리가 서버 측 자바 스크립트 환경 (예 : 전역 객체 가없는 node.js)에보다 쉽게 통합 될 수 있습니다 window. 이러한 상황에서는 한 줄만 변경하면 window개체를 다른 줄로 바꿀 수 있습니다 . jQuery의 경우 windowHTML 스크래핑 목적으로 모의 객체를 생성하고 전달할 수 있습니다 ( jsdom 과 같은 라이브러리 가이를 수행 할 수 있음).


2
, 축소에서는 언급 +1 내가 jsperf +2를 수 소원 - 축소 된 버전이 (function(a,b){})(window);- a그리고 b보다 훨씬 짧은 windowundefined:)
gnarf

+1 이전 에 스코프 체인에 대해 들어 봤지만 용어를 잊었습니다. 감사!
alex

또한 같은 이유로 사용 된 void (0)을 사용하는 대신 사용할 수 있습니다. void (0)은 정의되지 않은 값을 얻는 안전한 방법입니다.
glmxndr

"당신이하는 말"은이 다른 질문과 관련이 있습니다 : stackoverflow.com/questions/4945265/…
gnarf

@gnarf, 질문이 병합되었다는 알림에 감사드립니다. 좀 더 이해하기 위해 대답을 편집하겠습니다;)
David Tang

16

다른 사람들은 설명했다 undefined. undefined모든 값으로 재정의 할 수있는 전역 변수와 같습니다. 이 기술은 누군가가 누군가 undefined = 10어딘가에 썼다면 정의되지 않은 모든 검사가 중단되는 것을 방지하는 것 입니다. 전달되지 않은 인수 undefined변수 의 값에 관계없이 실제 값 이어야 합니다undefined .

창을 통과 한 이유는 다음 예에서 설명 할 수 있습니다.

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

콘솔 로그는 무엇입니까? window객체 의 가치가 맞습니까? 잘못된! 10? 잘못된! 기록 undefined합니다. Javascript 인터프리터 (또는 JIT 컴파일러)는 다음과 같이 다시 작성합니다.

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

그러나 window변수를 인수로 사용하면 var가 없으므로 놀라움이 없습니다.

jQuery가 그것을하고 있는지 모르겠지만 window어떤 이유로 든 함수의 어느 곳에서나 지역 변수를 재정의하는 경우 전역 범위에서 빌려주는 것이 좋습니다.


6

window누군가가 IE에서 창 객체를 재정의하기로 결정한 경우와 같이 전달됩니다 undefined. 나중에 나중에 다시 할당 될 경우를 위해 동일하다고 가정합니다 .

window스크립트 의 최상위 는 "window"라는 인수의 이름을 지정하는 것입니다. 전역 window참조와이 클로저 내부의 코드에서 사용하는 것 보다 더 로컬 인 인수입니다 . window끝에 실제로이 경우, 첫 번째 인수에 대한 현재의 의미를 전달하는 것을 지정하는 것입니다 window희망은 당신이 망쳐하지 않은 것입니다 ... window그런 일이 전에.

이 플러그인, jQuery를에 사용되는 가장 일반적인 경우를 보여줌으로써 생각하는 것이 더 쉬울 수 있습니다 .noConflict()그래서 당신은 여전히 사용할 수있는 코드의 대부분, 처리 $뭔가 의미 경우에도, 다른 이상 jQuery이 범위 밖에서 :

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);

감사. 이것은 많은 의미가 있습니다. 그러나 대답은 이것과 @ C.Zakas의 말의 조합이라고 생각합니다.
dkinzer

@DKinzer 저는 C. Zakas가 아닙니다.)
Vincent

@Vincent, 죄송합니다 :-)
dkinzer

5

1000000 회 반복 테스트되었습니다. 이러한 종류의 지역화는 성능에 영향을 미치지 않았습니다. 1000000 반복에서 단일 밀리 초조차도 아닙니다. 이것은 단순히 쓸모가 없습니다.


2
말할 것도없이, 클로저는 함수의 인스턴스와 함께 모든 변수를 전달하므로 클로저가 100 바이트이고 메모리가 100kb 인 1000 개의 인스턴스가있는 경우.
Akash Kava

@AkashKava와 @Semra, 나는이 테스트가 실제 상황에서 왜 창에 들어 갔는지 설명하지는 않습니다. 스코프 체인을 따라 해당 변수에 추가로 접근하는 깊이 중첩 된 클로저가있는 경우에만 성능이 향상됩니다. 분명히 함수가 스코프 체인에서 변수에서 한 단계 떨어져 있으면 많은 이득을 얻지 못할 것입니다. 그러나 그것이 아래로 waaaay이고 얻을 필요 window가 있다면 지역 사본에 의해 약간의 이익을 볼 수 있습니다.
gabereal

@gabereal의 새로운 JavaScript 엔진은 컴파일 자체에서 클로저를 해결하므로 런타임시 클로저 성능이 향상되지 않습니다. 확신 할 수있는 성능이 있다면 의심 할 여지없이 성능을 보여주는 jsperf 예제를 만들 수 있습니다. 우리가 얻는 유일한 성능은 클로저를 격리하는 것입니다.이 기능은 축소를 개선하여 크기를 줄이고 성능을 높이는 것은 스크립트의 빠른 다운로드 및 구문 분석을 통해 달성됩니다.
Akash Kava

@AkashKava 내가 왜 그렇게 확신 한다고 생각 합니까? 난 그냥 "일부 이익을 볼 수 있습니다"와 "나는 생각하지 않습니다"라고 말했다. 테스트를 만들 수는 있지만 어쨌든이 패턴을 사용하지 않기 때문에 오히려 아닙니다. "컴파일 자체의 클로저 해결"이라는 말의 의미를 설명 할 수 있습니까? 어떤 대안이 아니라? Javascript 엔진은 이전에 어떻게 다르게 작동 했습니까?
gabereal

마지막에 창이 커리지 만 함수 매개 변수에 입력되지 않은 코드를 찾으십시오. 무엇을 의미합니까? 내가 생각하는 창 매개 변수가 없어도 매개 변수가 원래 전역의 범위 개체를 따르는 지 확인합니까?
웹 우먼
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.