[자바스크립트 ES6+ 기본] 2. let/const 변수

Speedwell🍀·2021년 12월 24일
0

변수 구분

  • 로컬(지역) 변수, 글로벌(전역) 변수

  • 변수를 구분하는 이유는?

    • 기능과 목적이 다르기 때문
  • 글로벌 변수의 기능, 목적

    • 다른 js 파일에서 변수값 공유
    • 파일에서 공통 변수 개념으로 사용
    • 의도는 좋으나 처리 속도가 떨어짐
  • 로컬 변수의 기능, 목적

    • 빠르게 식별자를 해결하기 위해 가까운 스코프의 변수를 사용하려는 것
  • var 키워드 문제


글로벌 변수 오해

  • 글로벌 변수는

    • 글로벌 오브젝트의 로컬 변수
    • var value = 100처럼 var 키워드 사용이 정상
  • var 키워드를 작성하지 않으면

    • 글로벌 변수로 간주하는데 이것이 문제
// "use strict";
value = 100;
funciton point(){
  value = 300; // 함수 안에서 글로벌 변수에 값을 설정하는 것은 좋은 모슴이 아님
  log("함수:", value);
};
point();

// 함수:300
  • log()는 console.log()의 약칭

use strict 사용

  • 함수 안에서
    • var 키워드를 사용하지 않으면 에러 발생
    • ES5에서 도입했으나 근본적인 접근은 아님
"use strict":
function point(){
  try {
    value = 300;
  } catch(e) {
    log("글로벌 변수 사용 불가");
  };
};
point();

// 글로벌 변수 사용 불가
  • ES6+
    • "use strict"가 디폴트 환경
    • 전체는 아님


블록 스코프 유형

function 블록

  • function name(){}도 블록 스코프
  • function 안과 밖에
    • 같은 이름의 let 변수 선언 가능
    • 스코프가 다르기 때문
let sports = "축구";
function show(){
  let sports = "농구";
  log("안: ", sports);
};
show();
log("밖: ", sports);

// 안: 농구
// 밖: 축구
  • function 밖의 let 변수를
    • function 안에서 사용 가능(클로저)
let sports = "축구";
function show(){
  log(sports);
};
show();

// 축구

try-catch

  • try-catch문도 블록 스코프
  • try 블록 {} 기준으로
    • 안과 밖에 같은 이름의 let 변수 선언 가능
let sports = "축구";
try {
  let sports = "농구";
  log("안: ", sports);
} catch(e){};
log("밖: ", sports);

// 안: 농구
// 밖: 축구
  • catch()에서 try 밖의 변수 사용
let sports = "축구";
try {
  let sports = "농구";
  log("안: ", sports);
  abc = error;
} catch(e) {
  log("catch: ", sports);
};
log("밖: ", sports);

// 안: 농구
// catch: 축구
// 밖: 축구

switch-case

  • switch문도 블록 스코프
  • switch 블록 기준으로
    • 같은 이름의 let 변수 작성 불가
let item = 1;
switch(item) {
  case 1:
    let sports;
    break;
  case 2:
    // let sports;
  default:
    log(sports);
};

// switch 블록 안에서 let을 사용하여 선언한 변수가 있는데 다시 let을 사용하여 변수 선언 => 에러 (실행 에러가 아니라 컴파일 에러)


let 변수

let 변수 개요

  • let book = "책";

    • 블록(block) 스코프를 가진 변수
    • 변수가 선언된 블록이 스코프
  • 스코프 적용 기준

    • 블록{}, 문, 표현식
let sports = "축구";
if (sports) { // 여기서부터
  let sports = "농구";
  log("안: ", sports);
}; // 여기까지가 하나의 스코프
log("밖: ", sports);

// 안: 농구
// 밖: 축구
  • 블록{} 안과 밖이 스코프가 다름
    • 변수 이름이 같아도 값이 대체되지 않음

let 변수 선언

  • Syntax
    let name1 [= value1], name2 [= value2]]

  • name1, name2에 변수 이름 작성

    • 식별자로 사용
    • []는 생략 가능
    • 값을 할당하지 않아도 됨
let book;
let one, two;
// 초기값으로 undefined가 할당됨
  • value1, value2에 초기값 작성
    • 표현식 작성 가능, 평가 결과 사용
let book = "책";
let one = 1, two = (10 + 20);
// let five = 5, let six = 6; => SyntaxError (let을 처음에 한 번만 써야 함)
// let five = 5, var six = 6; => 콤마로 구분하여 let과 var 함께 사용 불가능

블록 스코프

  • 블록 기준

    • 중괄호 { 코드 }
    • function name(){ 코드 }
    • if(a === 1){ 코드 }
  • 블록 안과 밖이 스코프가 다름

    • 변수 이름이 같아도 값이 대체되지 않음
let sports = "축구";
if (sports){
  let sports = "농구";
  log("안: ", sports);
};
log("밖: ", sports);

// 안: 농구
// 밖: 축구
let sports = "축구";
sports = "농구";
log(sports);
// let sports = "배구"; ==> let을 사용하여 같은 스코프에 같은 이름의 변수 선언 불가능
{
  let sports = "탁구"; // 블록{}을 사용하여 스코프가 다르므로 let 사용해서 변수 선언 가능
  log(sports);
};

// 농구
// 탁구

let 변수와 var 변수 차이

  • for() 문에서 반복할 때마다
    • var 변수는 스코프를 갖지 않음
    • let 변수는 스코프를 가짐
선택, 클릭
- 축구
- 농구
- 야구

** html 파일 **
<ul class=sports>
    <li>축구</li>
    <li>농구</li>
    <li>야구</li>
</ul>

var 변수와 스코프

// 어떤 것을 클릭하더라도 항상 for() 문이 끝났을 때의 값인 3을 출력
// var k = 0;에서 k 변수의 스코프는 함수
var node = document.querySelector(".sports");
for (var k = 0; k < node.children.length; k++){
  node.children[k].onclick = function(event){
    event.target.style.backgroundColor = "yellow";
    log(k);
  };
};

// 3
// 3
// 3

let 변수와 스코프

// 위의 코드에서 var k = 0;을 let k = 0;으로 바꿈
// 이벤트를 설정할 때의 k 값을 출력
var node = document.querySelector(".sports");
for (let k = 0; k < node.children.length; k++){
  node.children[k].onclick = function(event){
    event.target.style.backgroundColor = "yellow";
    log(k);
  };
};

// 0
// 1
// 2

let 변수와 this

  • 글로벌 오브젝트에서
    • let 변수를 this로 참조 불가
var music = "음악"; // window 오브젝트에 설정됨
let sports = "축구"; // window 오브젝트에 설정되지 않음
log(this.music, this.sports);
// this.music에서 this가 window 오브젝트를 참조하며 music이 window 오브젝트에 설정되어 있으므로 음악 출력
// this.sports에서 sports가 window에 설정되지 않으므로 undefined가 출력

// 음악, undefined
  • 글로벌 오브젝트에서
    • var과 let 변수가 설정되는 위치 구조

      • var로 선언하면 Global(Window) 오브젝트에 설정됨
      • let로 선언하면 Global 오브젝트에 없고, Script에 있음
        let 변수를 블록안에 작성해야 하지만 블록이 없으므로 엔진이 블록을 만들고 이를 스코프로 사용하여 설정하는 개념. Script는 하나의 블록 개념으로 <script>에 작성한 모든 파일에서 공유함

다수의 js 파일 사용

  • 모든 js 파일에서

    • 글로벌 오브젝트에 작성한 var 변수와 let 변수를 공유
  • 블록 안에 작성하면 공유하지 않음

/*
1. 현재 위치는 글로벌 오브젝트
2. html 파일에 2개의 js 파일 작성함
	<script src="./first.js" defer></script>
    <script src="./second.js" defer></script>
3. 현재 first.js를 실행 중
*/

var globalVar = "var 변수";
// 글로벌(window) 오브젝트에 설정됨

let globalLet = "let 변수";
/*
1. 글로벌(window) 오브젝트에 설정되지 않고 Script에 설정됨
2. Script는 스펙에 정의된 이름
*/

{
  let globalBlock = "block의 let 변수";
  // Script에 설정되지 않고 Block에 설정됨
};
// second.js
// first 파일에 이어서 실행

console.log(globalVar);
/*
1. var globalVar = "var 변수";
2. 글로벌 오브젝트에서 var 키워드를 사용해서 선언한 변수는 window 오브젝트에 설정되며
모든 js 파일에서 변수를 공유
3. console에 "var 변수"가 출력됨
*/

console.log(globalLet);
/*
1. let globalLet = "let 변수";
2. 글로벌 오브젝트에서 let 키워드를 사용해서 선언한 변수는 Script에 설정되며
모든 js 파일에서 변수를 공유
3. console에 "let 변수"가 출력됨
*/

try {
  console.log(globalBlock);
} catch(e) {
  console.log("globalBlock은 공유되지 않습니다.");
};
/*
{
  let globalBlock = "block의 let 변수";
};
1. 글로벌 오브젝트에 작성했지만 블록 안에 작성한 변수
2. 이렇게 블록 안에 작성한 변수는 공유되지 않아 에러가 발생
*/

// ================== 위는 글로벌 오브젝트에 작성한 경우, 아래는 함수에 작성한 경우
function showLocal(){
  // 함수가 스코프이며 var, let 변수 모두 Local에 표시됨
  var localVar = "var";
  let localLet = "let";
  {
    // Block에 표시됨
    let blockLet = "block";
  };
};
showLocal();

다수의 js 파일 사용 정리

  • 글로벌 오브젝트에 작성

    • var 변수: window에 설정, 공유
    • let 변수: Script에 설정, 공유
      • window.sports = {}처럼 의도적으로 작성하지 않아도 됨
    • { let 변수 }: Block에 설정, 공유❌
      • 글로벌 오브젝트에서만 사용하는 로컬 변수로 사용
  • 함수에 작성

    • var 변수, let 변수: Local
    • { let 변수 }: Block

호이스팅(Hoisting)

  • ES5의 실행 콘텍스트 처리 순서
  1. 함수 선언문 설정
  2. 변수 이름을 바인딩, 변수값은 undefined
  3. 소스 코드 실행
/*
변수가 아래에 있지만 식별자 해결 가능
단, 이 위치에서 music은 undefined
이것을 호이스팅이라고 함
식별자 해결을 하지 못하면 에러 발생
*/
log("music 변수: ", music);
var music = "음악";

// music 변수: undefined
  • let 변수는 호이스팅 되지 않음
    • 즉, let 변수 앞에서 변수 사용 불가
try {
  log(sports);
} catch(e) {
  log("호이스팅 불가");
};
let sports = "축구";

// 호이스팅 불가
  • let 변수를 인식하는 시점
  • block 안에 let 변수 작성


const 변수

구문: name1 [= value1], name2 [= value2]]

  • 값을 바꿀 수 없는 변수 선언
  • name1에 변수 이름 작성, 식별자로 사용
const sports = "축구";
try {
  sports = "농구";
} catch(e) {
  log("const 할당 불가");
};
// const 할당 불가
  • value1, value2에 초기값 작성
    • 반드시 값을 작성, 변수 선언만 불가
    • 표현식 작성 가능, 평가 결과 사용
  • JS에서 상수는 대문자 사용이 관례
// const가 상수이지만 값 형태에 따라 바꿀 수도 있음
const bonus = 100;
const POINT = 200; // 코딩 관례
  • 우선 let이 아닌 const 사용 가능을 검토

  • const 변수 전체를 바꿀 수는 없지만 Object의 프로퍼티 값을 바꿀 수 있음

const book = {title: "책"};
try {
  book = {title: "음악 책"};
} catch(e) {
  log("const 전체 할당 불가");
};
book.title = "미술 책";
log(book.title);

// const 전체 할당 불가
  • 배열의 엘리먼트 값도 바꿀 수 있음
const book = ["책"];
try {
  book = ["음악 책"];
} catch(e) {
  log("const 전체 할당 불가");
};
book[0] = "미술 책";
log(book[0]);

// const 전체 할당 불가
// 미술 책

0개의 댓글