오늘은 햇빛을 창문으로만 봤다. 요즘 날씨가 선선하다고 해서 창문을 열어봤더니 모기가 들어왔다. 아직 여름인가보다. 자바스크립트를 공부하면서 코로나도 아닌데 자가격리를 하고있다. 고마운 자바스크립트....ㅎ
오늘은 자바스크립트에서 중요한 개념인 scope와 closure를 배웠다. 바로 본론으로 들어가 살펴보자!
래쑤기릿!!!!🔥
scope(범위)라는 개념이 있기 때문에 어디까지가 잘 동작하는 코드이고, 어디까지가 동작하지 않는 코드인지 파악할 수 있다.
즉, 잘 작동되는 코드를 작성하려면 반드시 알아야 하는 개념이다.
let greeting = 'Hello'; // Global scope function greetSomeone() { // Local scope let firstName = 'Josh'; // Local scope return greeting + ' ' + firstName; // Local scope } // Local scope greetSomeone(); // Global scope, ‘Hello Josh’ firstName; // Global scope, Reference Error
Global Scope
- 전역 변수를 선언하면, 코드 모든 곳에서 해당 변수를 사용할 수 있다. 심지어 함수에서도 말이다.
- 전역 스코프에 변수를 선언할 수 있어도, 그러지 않는 것이 좋다. 왜냐하면, 두 개 이상의 변수의 이름이 충돌하는 경우가 생길 수도 있기 때문이다.
-> 이러한 global scope의 특성으로 인해 let과 const는 재선언을 허용하지 않는다.
Local Scope
- 코드의 특정 부분에서만 사용할 수 있는 변수는 지역 스코프에 있다고 할 수 있다. 이런 변수들은 지역 변수(local variable)라고 불린다.
- 자바스크립트에서는 함수 스코프(function scope)와 블록 스코프(block scope) 두가지의 지역 변수가 존재한다.
- javascript는 함수 선언과 동시에 local scope를 가진다.
-> 함수 스코프(function scope)- 지역변수(local variable)는 함수 내에서 전역 변수(global variable)보다 더 높은 우선순위를 가진다.
Function Scope
function sayHello () { const hello = 'Hello CSS-Tricks Reader!' console.log(hello) } sayHello() // 'Hello CSS-Tricks Reader!' console.log(hello) // Error, hello is not defined
- 변수는 선언한 함수 내부에서만 사용될 수 있다. 함수 바깥에서는 해당 변수를 사용할 수 없다.
- 위의 코드를 보면 변수 hello는 sayHello의 scope 내에 존재한다는 것을 알 수 있다.
function first () { const firstFunctionVariable = 'I’m part of first' } function second () { first() console.log(firstFunctionVariable) // Error, firstFunctionVariable is not defined }
- 또한 함수들이 각각 선언되었을 때, 서로의 스코프에는 접근할 수 없다. 어떤 함수가 다른 함수에서 사용되더라도 말이다.
function outerFunction () { const outer = 'I’m the outer function!' function innerFunction() { const inner = 'I’m the inner function!' console.log(outer) // I’m the outer function! } console.log(inner) // Error, inner is not defined }
- 다만 위와 같이 함수가 다른 함수 내부에서 정의되었다면, 내부 함수는 외부 함수의 변수를 사용할 수 있다. 하지만, 외부 함수는 내부 함수의 변수를 사용할 수 없다.
- 이런 행동을 렉시컬 스코핑(lexical scoping)이라고 부른다.
Block Scope
{ const hello = 'Hello CSS-Tricks Reader!' console.log(hello) // 'Hello CSS-Tricks Reader!' } console.log(hello) // Error, hello is not defined
- 중괄호({}) 내부에서 const 또는 let으로 변수를 선언하면, 그 변수들은 중괄호 블록 내부에서만 접근할 수 있다.
- 위의 코드에서 볼 수 있듯이 변수 hello는 중괄호 내부의 scope에 존재한다.
let과 var
- let은 block단위 scope를 가진다.
- var은 function 단위 scope를 가진다.
- Function scope까진 let과 var가 비슷해 보일 수 있으나, 반복문과 조건문과 같은 Block scope에서 let으로 선언한 변수는 block을 벗어나면 값을 사용할 수 없다.
- 번외) let과 const는 Block scope를 따르나 값을 선언,초기화 해놓고 다시 값을 재정의 할 수 없다.
결론적으로, function scope는 function 을 벗어나면 값을 사용할 수 없고, block scope(let)은 block을 벗어나면 값을 사용할 수 없다.
Currying(커링)
function adder(x) { return function(y) { return x + y; } } adder(2)(3); let add100 = adder(100); add100(2); // 102 add100(10); // 110
- currying(커링)은 함수 하나가 n개의 인자를 받는 과정을 n개의 함수로 각각의 인자를 받도록 하는 것이다.
- 위의 코드를 보면 알 수 있듯이 x의 값을 고정해 놓고 재사용할 수 있다.
function htmlMaker(tag) { let startTag = '<' + tag + '>'; let endTag = '</' + tag + '>'; return function(content) { return startTag + content + endTag; } } let divMaker = htmlMaker('div'); divMaker('안녕하세요'); // “<div>안녕하세요/div>" divMaker(‘다른값’) // “<div>다른값</div>"
- 위와 같이, html에서 생산적인 코드가 될 수 있다.
클로저 모듈 패턴
function makeCounter() { let privateCounter = 0; return { increment: function() { privateCounter++; }, decrement: function() { privateCounter--; }, getValue: function() { return privateCounter; } } } let counter1 = makeCounter(); counter1.increment(); counter1.increment(); counter1.getValue(); // 2 let counter2 = makeCounter(); counter2.increment(); counter2.decrement(); counter2.increment(); counter2.getValue(); // 1
- 모듈 패턴의 반환값은 함수가 아닌 객체이다.
- 위의 코드를 순서대로 보면 counter1, counter2는 키값이 함수인 객체를 반환 받는다
-> counter1, counter2는 내부에 익명의 변수 privateCounter가 각각 따로 존재한다.- 반환 받은 객체의 키값이 함수이고, 해당 함수는 익병의 변수 privateCounter에 접근할 수 있다.
-> 즉, 내부함수가 외부 함수의 변수를 접근할 수 있게 되므로 클로저에 정의와 같다.
오늘 공부하면서 scope는 코드의 안정성을 가져오는 것에 중요한 영향을 끼칠 것이고, closure는 코드의 생산성을 높여주는 역할을 하는데에 중요한 역할을 할 것 같다는 생각을 했다. 그런데 scope는 너무 이론적으로 접근하면 더 헷갈릴것 같다....적당히 감을 익히고 튀어야..🤫
초보 개발자라고 하기에도 쑥스러운 단계지만, 공부하면서 느낀 점이나 생각은 분명히 주니어 개발자로 성장하는데에 있어 큰 영향을 줄 것이라고 생각한다. 지금 공부하는 것이 나중에 빛을 볼 날이 오길 바란다!!!
참고문서
[번역] 자바스크립트 스코프와 클로저(JavaScript Scope and Closures), Hyeokwoo Alex Kwon, https://medium.com/@khwsc1/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80-javascript-scope-and-closures-8d402c976d19 2018.05.05 (접속일: 2020.09.16 01:45AM)
자바스크립트 모듈패턴, recordboy, https://velog.io/@recordboy/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%AA%A8%EB%93%88-%ED%8C%A8%ED%84%B4 2020.06.07 (접속일: 2020.09.16 01:45AM)
개념정리하는데 이만한게없네용 👍