# scope #
1. 개념
: 변수는 어떠한 환경 내에서만 사용 가능하며, 프로그래밍 언어는 각각의 변수 접근 규칙을 갖고있다.
- 변수와 그 값이 어디서부터 어디까지가 유효한 지를 판단하는 범위
- 즉, Scope는 변수 접근 규칙에 따른 유효 범위를 의미
- JavaScript에서는 함수가 선언되는(Lexical) 동시에 자신만의 Scope를 가짐.
( 선언시점에 스코프결정 /// 즉, 정적 유효범위 )
(1) 예시 1
var greeting ='hello';
function greetSomeone(){
var firstName = 'Josh'
return greeting +' ' +firstName;
}
greetSomeone(); // -> 'hello Josh'
firstName // -> ReferenceError
(2) 예시 2
자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다. 이러한 유효범위의 방식을 정적 유효범위(static scoping), 혹은 렉시컬(lexical scoping)이라고 한다.
1 2 3 4 5 6 7 8 9 10 11 12 |
var i = 5;
function a(){ var i = 10; b(); }
function b(){ console.log(i); }
a(); |
실행 결과는 5이다.
https://opentutorials.org/course/743/6495
2. Local Scope VS. Global Scope
- scope는 중첩이 가능
- 하위 scope가 상위 scope의 변수 접근 가능
- Global Scope는 어디에서도 접근 가능
- 우선순위 : 지역변수 > 전역변수
3. Block level vs. Function level
; JavaScript는 기본적으로, function level의 scoping 규칙을 따름
(1) Function level
: var
(2) Block level
- let : 재정의 X , 재 할당 O
- const: 재정의 X , 재 할당 X
4. 전역변수와 window 객체
- 함수 외부에서 선언된 모든 변수는 전역 범위
- 전역 범위를 대표하는 객체 = window
- 모든 전역 변수는 window 객체와 연결
5. 선언 없이 초기화 된 변수는 전역 변수
Ex)
Function showAge(){
//age는 전역변수이다
age = 30;
console.log(age);
}
showAge(); // 90
console.log(age); // 90
6. Hoisting
(1) 변수
- 변수 선언은 범위에 따라 선언과 할당으로 분리됨
- 자바스크립트 엔진이 내부적으로 변수 선언을 scope의 상단으로 끌어 올림 (hoist) —> [var 의 경우만]
Ex1)
a = 2;
var a;
cosole.log(a); // -> 2
Ex2)
cosole.log(a); //—> undefined
var a = 2;
(2) 함수
- 함수 선언식은 항상 상단으로 hoisting
- 함수 표현식은 할당된 변수만 상단으로 hoisting (--> 아래 예제 참고)
ex)
show(); var show;
var show = function() { ====> show(); //-->TypeError ( undefined 값 호출)
console.log('abcd'); show = function() {
} console.log('abcd');
}
# Closure #
- 개념
- 외부함수의 변수에 접근할 수 있는 내부 함수
- scope chain 으로 표현되기도 한다.
- 보통 함수를 return 하여 사용
- return 하는 내부 함수를 closure 함수로고 지칭
- 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성
(https://opentutorials.org/course/743/6544. 참고)
2. 예제
function outer() {
console.log('outer fn invoked')
function inner(){
console.log('inner fn invoked')
}
return inner; --------ㄱ.
}
outer(); //--->'outer fn invoked'. 하고 inner 함수 호출
outer()(); // -->'inner fn invoked'. <--- outer 에서 inner 함수를 리턴한 경우에만 가능(ㄱ.)
var innerFn = outer();
innerFn(); //---> 'inner fn invoked'
3. Closure 의 scope chain
- closure 자신에 대한 접근 (closure function 내에 정의된 변수)
- 외부 함수 변수에 대한 접근
- 전역 변수에 대한 접근
4. closure의 사용 이유(유용성)
(1) Currying ( Function Programming)
- 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법
- 예시
* without Currying |
with Currying |
function add(x,y){ return x + y; } add(2,3) // -->5 |
function adder(x){ reuturn function(y){ return x + y ; } } adder(2)(3) //--> 5 |
-> closure가 저장된 parameter를 사용하므로, template 함수를 만들고자 할 때 유용 (아래 예제)
(즉, 한개의 특정 인자를 고정해 놓고, 재활용시 유용 )
function elementMaker(tagName) {
var startTag = '<' + tagName + '>';
var endTag = '</' + tagName + '>';
return function(content) {
return startTag + content + endTag;
}
}
elementMaker('div')('hello world'); // <div>hello world</div>
var divMaker = elementMaker('div');
divMaker('code states'); // <div>code states</div>
divMaker('great'); // <div>great</div>
var h1Maker = elementMaker('h1');
h1Maker('Headline'); // <h1>Headline</h1>
(2) Closure Module Pattern
- 변수를 scope 안쪽에 감추어 함수 밖에서 노출시키지 않을 수 있음.(아래 예제)
- 즉, private 한 변수 만들기.
function makeCounter() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
getValue: function() {
return privateCounter;
}
}
}
var counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue(); // 2
var counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue(); // 1
'프로그래밍공부 > 자바스크립트' 카테고리의 다른 글
정규표현식 기본 (0) | 2019.06.20 |
---|---|
클래스 (0) | 2019.06.20 |
arguments 와 전개연산자(...xxx) (0) | 2019.06.20 |