모던 JS 딥다이브 정리용 글입니다.
예)
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
변수의 이름은 식별자이다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름이다.
식별자는 변수, 함수, 클래스 등의 이름으로 모두 사용되며 값이 아닌 메모리 주소를 기억하는 것이다.
- 변수 선언을 위한 키워드
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= {} / [] 배열, 객체는
값을 할당하는 것이 아닌 해당 배열 객체의 위치인 레퍼런스가 할당되는 것이기 때문에 안의 값들은 변경 가능하다.
console.log(score); //undefined
var score;
호이스팅이란 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다. 즉, 모든 선언문은 선언이 되기 이전에 참조 가능하다.
How?
JS엔진은 코드 실행(Runtime)이전에 평가과정을 거치는데, 이 평가과정 단계에서 선언문들이 호이스팅됨. 이후 런타임때 순차적으로 코드가 실행되며 할당이 이루어지는 것이다.
var score;
score = 80;
var score = 80; //하나의 문(statement)로도 표현 가능
var score = 80;
score = 90;
- 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어, 달러기호를 포함 가능
- 숫자로 시작 허용 X
- 예약어는 식별자로 사용 불가.(ex: awiat, null, class 등등)
//카멜케이스 var firstName; //스네이크 케이스 var first_name //파스칼 케이스 var FirstName;
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, 이런식으로 출력되게 됨.