변수 총 정리

beenvyn·2024년 7월 11일
0

Javascript 심화

목록 보기
3/18
post-thumbnail

📏 변수 비교

선언, 할당, 범위로 나눠서 알아두면 편함

재선언재할당범위
varoofunction
letxo{ }
constxx{ }

재선언

var 이름 = 'Kim';
var 이름 = 'Park';

var는 이렇게 같은 이름의 변수를 두번 이상 재선언할 수 있다.

재할당

var 이름; // 선언
이름 = 'Park'; // 할당
let 이름 = 'Kim';
이름 = 'Park';  // ✅

const 나이 = 30;
나이 = 40; // ❌

const는 애초에 constant의 약자로 바뀌지 않는 일정한 값을 뜻함
➡️ const로 만들면 값 재할당이 불가능

그러나...⭐ const로 오브젝트를 만들었을 때 오브젝트 내부 값을 변경해도 에러가 안남!
const 변수 자체를 재할당한게 아니기 때문이다.

const 사람 = { 이름 : 'Kim' }
사람.이름 = 'Park';

수정 불가능한 오브젝트를 만드는 법

const 사람 = { 이름 : 'Kim' }
Object.freeze(사람);

사람.이름 = 'Park';

사람 오브젝트가 수정 불가능해짐


🎣 Hoisting 현상

변수의 선언 & 함수의 선언을 변수 범위 맨위로 끌고오는 현상
→ js는 원래 이렇게 동작한다.

변수의 Hoisting

~~~~ // 코드
  
var 나이 = 30;
function 함수(){}
var 나이;
function 함수(){}

~~~~~~ // 코드
  
나이 = 30;

근데 여기서 중요한 건..

var는 호이스팅 시 undefined가 자동으로 할당이 되고
let과 const는 undefined가 할당이 되지 않는다!

console.log(이름); // undefined
var 이름 = 'Kim';

console.log(이름); // ⚠️ 에러!
let 이름 = 'Kim';

undefined는 변수가 선언은 되었는데 값이 아무것도 할당되지 않았을 때 출력되는 값이다. 즉, 정해지지 않은 값 이라고 생각하면 된다.

함수의 Hoisting

함수의 선언 부분을 맨 위로 끌고 오기 때문에 함수 선언 전에 함수 호출이 가능하다.

함수();
function 함수() {
  let 안녕 = 'Hello!';
} 

근데 여기서 주의할 점은..

function 함수(){} : 전부가 Hoisting 됨
var 함수 = function(){} : 선언 부분만 Hoisting 됨

함수();
var 함수 = function() {
  console.log(안녕);
  var 안녕 = 'Hello!';
} 

➡️ 딱 var 함수만 위로 당겨지기 때문에 에러가 난다.


🧪 변수 동시에 여러개 만들기

// before
var 나이 = 20;
var 이름 = 'Kim';
var 성별;

// after
var 나이 = 20, 이름 = 'Kim', 성별;

🌎 전역변수

모든 곳에서 쓸 수 있는 변수

1) 가장 바깥에서 var를 사용해 선언해서 전역변수 만들기

바깥에 있는 변수는 안에서 그대로 사용할 수 있음.

var 나이 = 20; // 바깥

function 함수(){ // 안
  console.log(나이); // ✅
}

2) window로 전역변수 만들기

window.이름 = '김';


✍️ 연습 문제

Q. 코드가 다음과 같을 때 출력되는 값은?

let a = 1;
var b = 2;
window.a = 3;
window.b = 4;

console.log(a + b);

A. a는 1, b는 4가 출력된다.
b가 4가 되는 이유는 var b = 2window.b = 4는 거의 동일한 기능을 하는 코드기 때문에 b는 그냥 4로 재할당 된 것이다.
a의 경우 let으로 선언한 값이 글로벌 변수보다 범위가 작기 때문에 '나랑 더 가까운 값'인 1을 참조한 것이다.

Q. 콘솔창에 1초에 한번씩 1부터 5까지의 정수를 출력해주고 싶을 때 다음 코드를 어떻게 수정해야 할까?

for (var i = 1; i < 6; i++) { 
  setTimeout(function() { console.log(i); }, i*1000 ); 
}

이 코드는 1초마다 6이 출력돼서 원하는 대로 동작하지 않는다.

A. let 변수를 사용한다.
setTimeout안에 들어있는 console.log(i)는 바로바로 실행되는 코드가 아니다. 따라서 반복문이 다 완료된 후 차례대로 실행이 되는데 이 시점에서 i 값은 반복문이 다 실행되고 전역변수 var i = 6;로 남아있다. 따라서 계속 6이 출력되는 것이다.

for (let i = 1; i < 6; i++) { 
  setTimeout(function() { console.log(i); }, i*1000 ); 
}

let 변수는 범위가 중괄호이므로 i값이 아래와 같이 for 반복문 내에 남아있게 된다.

for (let i = 1; i < 6; i++) { 
  let i = 3
  setTimeout(function() { console.log(i); }, i*1000 ); 
}

따라서 반복문이 다 끝나고 console.log(i)가 실행될 때 for 반복문 내에 남아있는 i값을 가져다 쓰게 된다.

Q. 버튼을 누르면 모달창을 띄우고 싶을 때 다음 코드를 어떻게 수정해야 할까?

<div style="display: none">모달창0</div>
<div style="display: none">모달창1</div>
<div style="display: none">모달창2</div>

<button>버튼0</button>
<button>버튼1</button>
<button>버튼2</button>

<script> 
var 버튼들 = document.querySelectorAll('button');
var 모달창들 = document.querySelectorAll('div');

for (var i = 0; i < 3; i++){
  버튼들[i].addEventListener('click', function(){
    모달창들[i].style.display = 'block';
  });
}
</script> 

A. let 변수를 사용한다.
위의 문제와 유사하다.
이벤트리스너 내부 코드 모달창들[i].style.display = 'block';는 반복문이 다 끝나고 나중에 클릭이라는 현상이 일어날 때 실행이 된다.
따라서 클릭이 일어났을 때 i값을 채우려고 봤더니 전역변수 var i = 3; 밖에 남아있지 않으므로 i에 3을 채우게 되는 것이다.

for (let i = 0; i < 3; i++){
  let i = 2
  버튼들[i].addEventListener('click', function(){
    모달창들[i].style.display = 'block';
  });
}

이렇게 let을 사용하면 반복문이 다 끝나고 나서도 중괄호 안에 let = ~가 남아있기 때문에 그 값을 모달창들[i].style.display = 'block';의 i값으로 가져다 쓰게 된다.

profile
୧ʕ•̀ᴥ•́ʔ୨

0개의 댓글