[JS]4장 변수

JH Cho·2022년 12월 10일
0

모던JS DeepDive 공부

목록 보기
4/27
post-thumbnail

모던 JS 딥다이브 정리용 글입니다.

4.1_ 변수란 무엇인가?

  • 애플리케이션은 데이터를 다루며 아무리 복잡한 APP이라도 데이터를 INPUT / OUTPUT 하는 것이 전부이다.
  • 변수는 프로그래밍 언어에서 데이터를 관리하기 위한 핵심 개념

예) 10 + 20
자바스크립트 엔진은 10과 20이라는 리터럴(literal)과 "+"라는 기호의 의미를 알고 있다.
또한 10 + 20이라는 표현식(expression)의 의미도 해석(parsing)할 수 있어야 한다.

1. 피연산자의 값을 메모리에 기억하고 CPU를 통해 연산한다.
메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체.
셀 하나 당 1바이트(8비트), 컴퓨터는 1바이트 단위로 데이터를 저장(write)/읽기(read)한다.

2. 각 셀은 고유의 메모리 주소를 가지며 피연산자와 연산 결과 값은 각각 임의의 메모리에 저장된다.(2진수로 변환되어)
3. but 메모리주소로 직접 값에 접근하는 것은 허용되지 않기 때문에 값을 재사용하기 위해서 메모리 주소를 가리키는 변수를 선언하고 값을 할당한다.

let a = 30
//let a (변수 선언)
//= 30 (값 할당)

a (참조) // 30

4.2_ 식별자

  • 변수의 이름은 식별자이다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름이다.

  • 식별자는 변수, 함수, 클래스 등의 이름으로 모두 사용되며 값이 아닌 메모리 주소를 기억하는 것이다.

4.3_ 변수 선언

  • 변수 선언이란 변수를 생성하는 것을 의미한다.
  • 값을 저장하기 위한 메모리 공간을 확보하고
  • 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비
  • 변수 선언을 위한 키워드
    var let const
  • var
    var a;
    메모리 주소에 변수 a 바인딩(선언)<-동시 -> 메모리에 undefined 할당(초기화)
  • 선언하지 않은 변수를 호출하면 Reference Error 뜸

  • var & let & const 차이

  • var
    중복선언, 재할당 가능
    function scope외에 전역 변수로 선언됨.
  • let
    중복선언 X
    재할당 O
    block scope.
  • const
    중복선언 X
    재할당 X
    block scope
    주의) const a= {} / [] 배열, 객체는
    값을 할당하는 것이 아닌 해당 배열 객체의 위치인 레퍼런스가 할당되는 것이기 때문에 안의 값들은 변경 가능하다.

참고) var를 지양해야하는 이유

  • 함수 레벨 스코프
  • 전역 변수의 남발
  • for loop 초기화식에서 사용한 변수를 for loop 외부나 전역에서 참조 가능하게 되버림.
  • var 키워드를 생략 허용하기 때문에 의도치 않게 변수가 전역화 된다.
  • 중복 선언이 허용되어 의도치 않게 변수 값이 변경
  • 변수 호이스팅이 되어 변수가 선언되기 전에 참조가 가능하다.

var let const 차이

4.4_ 변수 선언의 실행 시점과 변수 호이스팅

console.log(score); //undefined

var score;
  • JS는 인터프리터에 의해 한 줄씩 순차적으로 실행된다.
  • 어떻게 콘솔에 에러가 아닌 undefined?
  • 변수 선언이 런타임(순차실행)이 아닌 그 전 단계에 먼저 실행되기 때문이다.
  • 자바스크립트 엔진은 런타임 전에 소스코드의 평가과정을 거치면서 변수선언을 포함한 모든 선언문을 먼저 찾아내어 실행한다.
  • 평가과정 이후 런타임이 실행된다.
  • 이렇게 평가과정에서 선언문을 먼저 실행하는 것을 변수 호이스팅이라고 한다.(var, let, const, function, class)

호이스팅 이해해보기

호이스팅이란 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다. 즉, 모든 선언문은 선언이 되기 이전에 참조 가능하다.

How?
JS엔진은 코드 실행(Runtime)이전에 평가과정을 거치는데, 이 평가과정 단계에서 선언문들이 호이스팅됨. 이후 런타임때 순차적으로 코드가 실행되며 할당이 이루어지는 것이다.

  • 변수의 생성 과정
    • 선언 단계 : 변수 객체에 변수 등록
    • 초기화 단계 : 변수 객체에 등록된 변수를 메모리에 할당(값이 undefined로 초기화)
    • 할당 단계 : undefined로 초기화 된 변수에 실제 값을 할당.

4.5 값의 할당

  • 변수에 값을 할당할 때는 할당 연산자를 사용한다.
  • JS의 할당은 JS 엔진이 알아서 타입을 지정하지 않아도 추론하여 타입을 결정해준다. ( 동적 타이핑 )
var score;
score = 80;

var score = 80; //하나의 문(statement)로도 표현 가능
  • 주의: 선언은 호이스팅 할당은 런타임에 실행.

4.6_ 값의 재할당

var score = 80;
score = 90;
  1. 선언은 평가과정에서 이미 실행, undefined 초기화 된 상태
  2. score = 80 ; undefined를 80으로 변경 X
    새로운 메모리 공간을 확보하고 그곳에 할당 값 80을 저장
  3. score = 90; 위와 마찬가지.

4.7_ 식별자 네이밍 규칙

  • 식별자는 어떤 값을 구별하여 식별해낼 수 있는 고유한 이름
  • 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어, 달러기호를 포함 가능
  • 숫자로 시작 허용 X
  • 예약어는 식별자로 사용 불가.(ex: awiat, null, class 등등)
  • 네이밍 컨벤션
//카멜케이스
var firstName;
//스네이크 케이스
var first_name
//파스칼 케이스
var FirstName;

마무리 Check!

1번)

if(true){
  let a = 1;
  var b = 2;
  if(true){
    let b = 3;
  }
  console.log(b);
}
--------------------
콘솔창 출력?  2

2번)

if(true){
  let a = 1;
  var b = 2;
  if(true){
    b = 3;
  }
  console.log(b);
}
----------------
콘솔창 출력? 3

3번)

함수();
function 함수() {
  console.log(안녕);
  let 안녕 = 'Hello!';
}  // error let 선언의 경우 호이스팅은 되지만
   // 초기화는 런타임에 실행되기 때문에 에러가 뜬다/
// 선언 할당문을 호출 위로 올리면 정상 작동한다.
함수();
var 함수 = function() {
  console.log(안녕);
  var 안녕 = 'Hello!';
} // error 함수는 function이 아니다.
// var 함수는 호이스팅 되지만 할당은 런타임에 하기때문
let a = 1;
var b = 2;
window.a = 3;
window.b = 4;

console.log(a + b);
// 프로토타입 체인으로 인함.
// let a의 경우 스크립트 내에서 선언 할당이 이루어짐.
// var b는 최상위 객체(전역)에 선언 할당.

// 정확한지는 모르겠음. 이런 꼴임.
window {
a : 3
b : 4
script {
a : 1
}
}


```js
for (var i = 1; i < 6; i++) { 
  setTimeout(function() { console.log(i); }, i*1000 ); 
} // 얘는 6만 출력됨.

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

for (var i = 1; i < 6; i++) { 
  console.log(i)
} // 1 2 3 4 5

이거 중요!!

setTimeout은 비동기 함수.
그래서 que에서 대기하게 되는데

que 대기실
 setTimeout(function() { console.log(1); }, i*1000 ); 
 setTimeout(function() { console.log(2); }, i*1000 ); 
 setTimeout(function() { console.log(3); }, i*1000 ); 
 setTimeout(function() { console.log(4); }, i*1000 ); ....

이런 식으로 대기하게 된다.

하지만 var의 경우 function 블록 스코프 제외 블록에서는 전역 변수로 선언이 되기 때문에 나중에 콜 스택이 비워지고 que에 있던 함수들이 실행될 때는 전역변수가 6이 되버리고 난 후이다. 그래서 6이 한꺼번에 출력되는 것이다.

반대로 let의 경우 block scope의 특성이 있으므로 할당된 그대로 다른 i 선언을 재할당 하지 않으므로 1, 2,3, 이런식으로 출력되게 됨.

profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글