Javascript hoisting

2,116 views
2,072 views

Published on

2013.04.02 스터디 팀 복습을 위한 문서.

Published in: Technology
4 Comments
6 Likes
Statistics
Notes
No Downloads
Views
Total views
2,116
On SlideShare
0
From Embeds
0
Number of Embeds
702
Actions
Shares
0
Downloads
21
Comments
4
Likes
6
Embeds 0
No embeds

No notes for slide

Javascript hoisting

  1. 1. JavaScript Hoisting 안오균
  2. 2. 먼저,지역 변수의 유효 범위는 블럭이 아닌 함수! function foo() { var bar = ‘bar’; console.log(bar); //--> ‘bar’ if (true) { var bar = ‘baz’; console.log(bar); //--> ‘baz’ } console.log(bar); //--> ‘baz’ }
  3. 3. 즉시 실행 함수로 유효 범위를 제한할 수 있음. function foo() { var bar = ‘bar’; console.log(bar); //--> ‘bar’ if (true) { (function () { var bar = ‘baz’; console.log(bar); //--> ‘baz’ }()); } console.log(bar); //--> ‘bar’ }
  4. 4. 호이스팅(Hoisting) 변수 선언과 함수 선언은 인터프리터에 의해 함수의 맨 앞으로 끌어올려진다(옮겨진다). * hoist = 끌어올리다
  5. 5. 용어가 좀 헷갈릴 수 있다.변수 선언(Variable Declaration) var foo = ‘bar’;함수 선언(Function Declaration) function foo() {}함수 표현식(Function Expression) var foo = function () {}; (function foo() {});
  6. 6. 변수 선언인 경우 function foo() { console.log(bar); //--> undefined var bar = baz; console.log(bar); //--> baz }아래와 동일 function foo() { var bar; // 변수 선언은 함수의 맨 앞으로 끌어올려진다.(hoisted) console.log(bar); bar = baz; // 할당은 실행 시점에 수행 console.log(bar); }
  7. 7. for 문의 경우도 동일 function foo(arr) { for (var i = 0, len = arr.length; i < len; i++) { console.log(arr[i]); } }아래와 동일 function foo(arr) { var i, len; for (i = 0, len = arr.length; i < len; i++) { console.log(arr[i]); } }
  8. 8. 함수 정의인 경우 function foo() { bar(); //--> bar function bar() { console.log(bar); } }아래와 동일 function foo() { function bar() { console.log(bar); } bar(); }
  9. 9. 함수 표현식인 경우 (변수 선언과 동일) function foo() { bar(); //--> ReferenceError var bar = function () {}; bar(); // 호출되지 않음 }아래와 동일 function foo() { var bar; bar(); bar = function () {}; bar(); }
  10. 10. 변수 선언은 호이스팅으로 맨 앞으로,변수 할당은 실행시점에 수행됨.호이스팅으로 헷갈릴 수 있으니,함수의 맨 앞 부분에 한 개의 var만 쓸 것을 권장. function foo() { var a = 1, b = 2, c = 3; }
  11. 11. 그치만, 눈을 크게 떠야할 때가 있음. function foo() { var a = 1, b = 3, c = 4; d = 2; }오류 없이 실행되며, 변수 d는 전역으로 선언됨.린트 툴을 사용할 것을 권장.
  12. 12. 디버깅이 어려운 경우도 있음. function foo() { var a = 1, b = getComplexValue(a), // 브레이크 포인트를 잡기 어려움 c = b + 3; }상황에 따라 var로 나누는 것도 나쁘지 않은 선택. function foo() { var a = 1; var b = getComplexValue(a); var c = b + 3; }
  13. 13. 또한, 분기문 내에 함수 정의를 넣지 말 것. function foo(condition) { if (condition) { function bar() { console.log(first bar); } } else { function bar() { console.log(second bar); } } bar(); } foo(true); //--> second bar foo(false); //--> second bar
  14. 14. 함수 정의 호이스팅에 따라 아래와 같기 때문. function foo(condition) { function bar() { console.log(first bar); } function bar() { console.log(second bar); } if (condition) { } else { } bar(); }* ES5 strict 모드에서는 SyntaxError 발생
  15. 15. 상황에 따라 동적으로 할당하고 싶다면. function foo(condition) { var bar; if (condition) { bar = function () { console.log(first bar); }; } else { bar = function () { console.log(second bar); }; } bar(); } foo(true); //--> first bar foo(false); //--> second bar
  16. 16. 개인적으로는, var는 맨 위에,함수는 읽어내려가기 편하게 작성하는 것을 선호함.function foo() { var a, b, c; doAll(); function doAll() { doA(); doB(); } function doA() {} function doB() {}}
  17. 17. 하지만 리턴문 뒤의 함수 정의는,문맥 상 그다지 좋은 것 같지 않음. function foo() { return bar(); function bar() { return ‘baz’; } } * 함수 정의 호이스팅으로 문제 없이 실행됨.
  18. 18. 끝.
  19. 19. 부록. 좀 더 자세히 알아보면. function test(a, b) { console.log(a, b, c, d); var c = 10; function d() {} } test(10);위와 같은 함수가 전역 범위에서 실행될 때.
  20. 20. 다음과 같은 식으로 실행됨.1. foo()가 호출되면,2. foo()의 실행 컨텍스트가 생성되고,3. 실행 컨텍스트는 함수를 실행하기 전 활성화 객체를 생성한다.4. 활성화 객체에는 파라미터 정보, 변수 선언, 함수 정의가 포함된다.5. 함수가 실행되고 변수를 만났을 때엔, 유효범위 체인에 따라 활성화 객체에서 먼저 찾고, 상위 탐색을 진행한다.
  21. 21. 이 때, 활성화 객체에는 다음 값들이 할당된다. - 파라미터로 전달된 값 파라미터의 이름과 값을 할당 없는 경우 undefined로 할당 - 모든 함수 선언 함수의 이름과 정의를 할당 이미 정의되어 있는 경우 덮어씀 - 모든 변수 선언 변수의 이름과 undefined를 할당 이미 정의되어 있는 경우 할당하지 않음
  22. 22. 즉, 아래 코드가 실행되기 전, function test(a, b) { console.log(a, b, c, d); var c = 10; function d() {} } test(10);활성화 객체(Activation Object)는 다음과 같이 생성된다. AO = { a: 10, b: undefined, c: undefined, d: <reference to function ‘d’> };
  23. 23. 실행 시점에서 변수를 만났을 때엔,활성화 객체의 값을 찾거나 설정한다. function test(a, b) { console.log(a, b, c, d); // 각각 AO[‘a’], AO[‘b’], AO[‘c’], AO[‘d’]의 값 // 10, undefined, undefined, function var c = 10; // AO[‘c’] = 10; 과 동일하다. function d() {} } test(10);
  24. 24. 함수 표현식은 활성화 객체에 할당되지 않는다. function test() { var foo = function bar() {}; // foo는 AO에 존재하지만, bar는 존재하지 않는다. // bar의 접근을 시도하면 ReferenceError가 발생한다. (function baz() {}); // 마찬가지로 baz도 AO에 할당되지 않는다. }
  25. 25. 호이스팅은 활성화 객체의 할당 방식에 따른 현상. function foo() { console.log(bar); //--> function ‘bar’ // AO[‘bar’] = <reference to function ‘bar’> var bar = 10; function bar() {}; var bar = 20; }
  26. 26. 정말 끝.

×