javascript hoisting

26
JavaScript Hoisting

Upload: ohgyun-ahn

Post on 05-Dec-2014

1.801 views

Category:

Technology


2 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Javascript hoisting

JavaScript Hoisting

안 오 균

Page 2: Javascript hoisting

먼저,지역 변수의 유효 범위는 블럭이 아닌 함수!

function foo() { var bar = ‘bar’; console.log(bar); //--> ‘bar’ if (true) { var bar = ‘baz’; console.log(bar); //--> ‘baz’ } console.log(bar); //--> ‘baz’ }

Page 3: Javascript hoisting

즉시 실행 함수로 유효 범위를 제한할 수 있음.

function foo() { var bar = ‘bar’; console.log(bar); //--> ‘bar’ if (true) { (function () { var bar = ‘baz’; console.log(bar); //--> ‘baz’ }()); } console.log(bar); //--> ‘bar’ }

Page 4: Javascript hoisting

호이스팅(Hoisting)

변수 선언과 함수 선언은 인터프리터에 의해 함수의 맨 앞으로 끌어올려진다(옮겨진다).

* hoist = 끌어올리다

Page 5: Javascript hoisting

용어가 좀 헷갈릴 수 있다.

변수 선언(Variable Declaration) var foo = ‘bar’;

함수 선언(Function Declaration) function foo() {}

함수 표현식(Function Expression) var foo = function () {}; (function foo() {});

Page 6: Javascript hoisting

변수 선언인 경우

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); }

Page 7: Javascript hoisting

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]); } }

Page 8: Javascript hoisting

함수 정의인 경우

function foo() { bar(); //--> 'bar' function bar() { console.log('bar'); } }

아래와 동일 function foo() { function bar() { console.log('bar'); } bar(); }

Page 9: Javascript hoisting

함수 표현식인 경우 (변수 선언과 동일)

function foo() { bar(); //--> ReferenceError var bar = function () {}; bar(); // 호출되지 않음 }

아래와 동일 function foo() { var bar; bar(); bar = function () {}; bar(); }

Page 10: Javascript hoisting

변수 선언은 호이스팅으로 맨 앞으로,변수 할당은 실행시점에 수행됨.

호이스팅으로 헷갈릴 수 있으니,함수의 맨 앞 부분에 한 개의 var만 쓸 것을 권장.

function foo() { var a = 1, b = 2, c = 3; }

Page 11: Javascript hoisting

그치만, 눈을 크게 떠야할 때가 있음.

function foo() { var a = 1, b = 3, c = 4; d = 2; }

오류 없이 실행되며, 변수 d는 전역으로 선언됨.린트 툴을 사용할 것을 권장.

Page 12: Javascript hoisting

디버깅이 어려운 경우도 있음.

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; }

Page 13: Javascript hoisting

또한, 분기문 내에 함수 정의를 넣지 말 것.

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'

Page 14: Javascript hoisting

함수 정의 호이스팅에 따라 아래와 같기 때문.

function foo(condition) { function bar() { console.log('first bar'); } function bar() { console.log('second bar'); } if (condition) { } else { } bar(); }

* ES5 strict 모드에서는 SyntaxError 발생

Page 15: Javascript hoisting

상황에 따라 동적으로 할당하고 싶다면. 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'

Page 16: Javascript hoisting

개인적으로는, var는 맨 위에,함수는 읽어내려가기 편하게 작성하는 것을 선호함.

function foo() { var a, b, c;

doAll();

function doAll() { doA(); doB(); } function doA() {} function doB() {} }

Page 17: Javascript hoisting

하지만 리턴문 뒤의 함수 정의는,문맥 상 그다지 좋은 것 같지 않음.

function foo() { return bar();

function bar() { return ‘baz’; } }

* 함수 정의 호이스팅으로 문제 없이 실행됨.

Page 18: Javascript hoisting

끝.

Page 19: Javascript hoisting

부록. 좀 더 자세히 알아보면.

function test(a, b) { console.log(a, b, c, d); var c = 10; function d() {} } test(10);

위와 같은 함수가 전역 범위에서 실행될 때.

Page 20: Javascript hoisting

다음과 같은 식으로 실행됨.

1. foo()가 호출되면,2. foo()의 실행 컨텍스트가 생성되고,3. 실행 컨텍스트는 함수를 실행하기 전 활성화 객체를 생성한다.4. 활성화 객체에는 파라미터 정보, 변수 선언, 함수 정의가 포함된다.5. 함수가 실행되고 변수를 만났을 때엔, 유효범위 체인에 따라 활성화 객체에서 먼저 찾고, 상위 탐색을 진행한다.

Page 21: Javascript hoisting

이 때, 활성화 객체에는 다음 값들이 할당된다.

- 파라미터로 전달된 값 파라미터의 이름과 값을 할당 없는 경우 undefined로 할당

- 모든 함수 선언 함수의 이름과 정의를 할당 이미 정의되어 있는 경우 덮어씀

- 모든 변수 선언 변수의 이름과 undefined를 할당 이미 정의되어 있는 경우 할당하지 않음

Page 22: Javascript hoisting

즉, 아래 코드가 실행되기 전, 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’> };

Page 23: Javascript hoisting

실행 시점에서 변수를 만났을 때엔,활성화 객체의 값을 찾거나 설정한다.

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);

Page 24: Javascript hoisting

함수 표현식은 활성화 객체에 할당되지 않는다.

function test() { var foo = function bar() {}; // foo는 AO에 존재하지만, bar는 존재하지 않는다. // bar의 접근을 시도하면 ReferenceError가 발생한다. (function baz() {}); // 마찬가지로 baz도 AO에 할당되지 않는다. }

Page 25: Javascript hoisting

호이스팅은 활성화 객체의 할당 방식에 따른 현상.

function foo() { console.log(bar); //--> function ‘bar’ // AO[‘bar’] = <reference to function ‘bar’> var bar = 10; function bar() {}; var bar = 20; }

Page 26: Javascript hoisting

정말 끝.