DevLog__[javascript: Scope, Closure]
# Intro
오늘은 햇빛을 창문으로만 봤다. 요즘 날씨가 선선하다고 해서 창문을 열어봤더니 모기가 들어왔다. 아직 여름인가보다. 자바스크립트를 공부하면서 코로나도 아닌데 자가격리를 하고있다. 고마운 자바스크립트....ㅎ
# javascript
오늘은 자바스크립트에서 중요한 개념인 scope와 closure를 배웠다. 바로 본론으로 들어가 살펴보자!
래쑤기릿!!!!🔥
1. Scope
1) scope란?
- 변수 접근 규칙에 따른 유효 범위
-> 쉽게 말해서, 변수와 그 값이 어디서부터 어디까지 유효한지를 판단하는 범위
2) 그렇다면 , scope(범위)를 왜 고려해야 할까?
-
scope(범위)라는 개념이 있기 때문에 어디까지가 잘 동작하는 코드이고, 어디까지가 동작하지 않는 코드인지 파악할 수 있다.
-
즉, 잘 작동되는 코드를 작성하려면 반드시 알아야 하는 개념이다.
3) Global Scope와 Local 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
- 보이는 바와 같이 변수 firstName에 접근할 수 있는 범위가 존재한다.
- Local scope(greetSomeon 메소드) 안쪽에서 선언된 변수는 밖에서 사용할 수 없다.
- 결론적으로, 안쪽 Scope에 있는 변수는 바깥쪽 Scope에서 사용할 수 없고, 바깥쪽 Scope에 있는 변수는 안쪽 Scope에서 사용할 수 있다.
Global Scope
- 전역 변수를 선언하면, 코드 모든 곳에서 해당 변수를 사용할 수 있다. 심지어 함수에서도 말이다.
- 전역 스코프에 변수를 선언할 수 있어도, 그러지 않는 것이 좋다. 왜냐하면, 두 개 이상의 변수의 이름이 충돌하는 경우가 생길 수도 있기 때문이다.
-> 이러한 global scope의 특성으로 인해 let과 const는 재선언을 허용하지 않는다.
Local Scope
- 코드의 특정 부분에서만 사용할 수 있는 변수는 지역 스코프에 있다고 할 수 있다. 이런 변수들은 지역 변수(local variable)라고 불린다.
- 자바스크립트에서는 함수 스코프(function scope)와 블록 스코프(block scope) 두가지의 지역 변수가 존재한다.
- javascript는 함수 선언과 동시에 local scope를 가진다.
-> 함수 스코프(function scope)- 지역변수(local variable)는 함수 내에서 전역 변수(global variable)보다 더 높은 우선순위를 가진다.
4) Function Scope와 Block Scope
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을 벗어나면 값을 사용할 수 없다.
5) 전역 변수(local variable)와 Window 객체
- Global scope에서 선언된 함수와 var 키워드를 통해 선언된 변수는 window객체와 연결 된다.
6) 선언없이 초기화된 전역 변수
- consol 최 상단에 ‘use strict’를 사용하면 문법적으로 실수 하는 부분을 에러로 판단할 수 있다.
2. Closure
1) closure란?
- 외부 함수의 변수를 사용할 수 있는 내부 함수
- 함수를 리턴하면 함수는 실행되지 않고 함수의 내용 자체가 리턴된다.
2) 유용한 closure 예제
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에 접근할 수 있다.
-> 즉, 내부함수가 외부 함수의 변수를 접근할 수 있게 되므로 클로저에 정의와 같다.
# Work Off
오늘 공부하면서 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)
기본기가 탄탄한 풀스택 개발자가 되는 그날까지 🔥🔥🔥
Author And Source
이 문제에 관하여(DevLog__[javascript: Scope, Closure]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hongin/인자한-개발로그javascript-3회차-lsop2lx0저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)