-
JS를 실행하는 프로그램 or 인터프리터 언어
-
엔진에 의한 인터프러터 방식으로 별도의 컴파일 과정이 필요없음.
❓ 인터프리터 언어란 자바스크립트의 경우 코드 한 줄씩 입력해도 바로 실행(런타임)하여 결과 확인이 가능 자바스크립트란 웹문서 구조를 동적으로 나타내기 위한 언어
❓ 컴파일러 언어란 특정 프로그래밍 언어로 쓰여있는 문서를 다른 프로그래밍 언어로 옮기는 언어 번역 프로그램 자바스크립트의 경우 고급 프로그래밍 언어를 기계어라는 다른 프로그래밍 언어로 번역하는 역할 수행
-
V8
- 자바스크립트 대표적인 엔진: Google V8 엔진
- C++로 작성됨.
- Chrome, Node.js에서 사용됨.
-
JavaScript Core
- 애플에서 개발하여, WebKit 프레임워크를 위해 개발됨.
- Safari와 React Native App에서 사용됨.
1) 바이트 코드로의 변환
- 자바스크립트 엔진에 의해 바이트 코드로 변환됨.
2) 기계어로 변환
- CPU마다 기계어를 다르게 해석하기에 가상 머신은 최적화된 기계어 제작함.
- 개발자는 따로 CPU별로 최적화된 기계어를 제작할 필요가 없음.
3) CPU 코드 실행
- 기계어를 실행하여 데이터 저장 및 연산 작업을 진행함.
- 변수 선언 시 새로운 메모리 공간을 할당하므로, 불필요한 값들이 쌓임.이러한 불필요한 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제됨. 단, 메모리에서 언제 해제될지는 예측할 수 없음.
- 자바스크립트의 경우 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당 **개발자의 직접적인 메모리 제어를 허용하지 않음. **➡️ 개발자가 명시적으로 메모리를 할당하고 해제할 수 없음.
- Reference-calling: 어떤 다른 객체를 참조하지 않는 객체를 더이상 필요없다고 판단함.
⚠️ 한계점: 두 객체가 서로 참조하는 속성이 될 경우에는 순환구조가 생성되고 메모리 누수가 발생한다. (가비지 생성 불가능함.) => 현재 참조 카운팅은 js 엔진에서 더이상 지원하지 않음. - Mark-and-Sweep: 루트 객체로부터 도달할 수 없는 객체를 더이상 필요없다고 판단함.
⚠️ 순환 구조가 있다고 해도 함수 호출 리턴된 이후에는 두 개의 객체들이 더이상 전역 객체에서 참조되지 않게 되어 메모리 누수가 발생하지 않음.
평가를 위해서는 literal, operator의 의미를 알아야 한다. 또한, 표현식의 의미 해석(parsing)도 필요하다. => JS 엔진은 피연산자(operand)를 기억한다. 연산(cpu)와 기억(메모리)를 수행하는 영역이 따로 존재한다. 메모리를 통해 데이터를 특정 단위로 읽고 저장하는데, 메모리 주소를 통해 값에 접근하면 오류 발생 가능성이 높아진다. 그래서 JS에서는 객체가 생성되었을 때 자동으로 메모리를 할당하고 더이상 필요하지 않을 때 자동으로 해체하는 과정을 거치도록 한다.
- 변수 == 값을 저장한 메모리를 식별하기 위한 것 / 값의 위치를 가리킴 => 프로그래밍 언어가 기억하고싶은 값을 메모리에 저장하고, 저장된 값을 읽어들여 "재사용"하기 위함
- 배열, 객체와 같은 자료구조를 사용하면 여러 개 값을 그룹화하여 하나의 값처럼 사용
- 변수명 == 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름
- 변수값 == 변수에 저장된 값
- 할당(대입,저장) == 변수에 저장하는 행위
- 참조 == 변수에 저장된 값을 읽어 들이는 것
- 참조 요청시, 자바스크립트 엔진은 변수명과 매핑된 메모리 주소를 통해 메모리 공간에 접근해 저장된 값을 반환함.
- 어떤 값을 구별해서 식별할 수 있는 고유한 이름
- 같은 값이 메모리 공간에 저장되어 있어도 식별자는 각 값들의 메모리 주소 또한 저장하기 때문에 값을 구별해낼 수 있음.
- 변수, 함수, 클래스 등 모두 식별자로 구분 가능
- 선언에 의해 자바스크립트 엔진에 식별자의 존재를 알림
- 변수를 생성하는 것
- 값을 저장하기 위한 메모리 공간 확보한 후 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비
- 변수 선언으로 확보된 메모리 공간은 해제되기 전까지 다른 변수가 사용할 수 없도록 보호됨.
- var, let, const
-
ES6 도입 때, let, const 변수 선언 키워드가 도입됨
종류 특징 var - 함수 스코프
- 호이스팅 불가능, undefined로 초기화됨
- 중복 선언 가능let - 블록 스코프
- 호이스팅 가능, 초기화 X, 선언 전 접근 시 Reference Error 발생const - 블록 스코프
- 재할당 불가능
- 선언과 동시에 초기화 진행 필수
-
❓ 스코프란
- 함수가 실행될 떄, 함수 내 변수에 대한 접근이 어떻게 되는지
- 변수에 접근할 수 있는 범위
- 함수 스코프 == 지역 스코프
- 새로운 함수가 생성될 때마다 새로운 스코프 발생
if(5 > 4) {
var secret = '12345';
}
secret // '12345'
- 함수 선언하지 않을 시, 새로운 환경 및 스코프가 생성되지 않음
- 스코프가 형성되지 않아 동일한 실행 컨텍스트 내 존재
function a() { var secret = '12345'; } secret; //ReferenceError
> - 함수 a에 대한 새로운 실행 컨텍스트 생성됨
> - 실행 컨텍스트 내부에 존재하는 변수 환경에 secret 변수가 저장됨.
> - 함수 외부에서 secret 접근 시, 스코프가 다르기 때문에 해당 변수에 접근 불가능함.
> 2. 블록 스코프
> - 블록{}이 생성될 때 새로운 스코프 생성됨
> ```js
function loop() {
for(var i = 0; i < 5; i++) {
console.log(i);
}
console.log('final',i);
}
loop();
/*
0
1
2
3
4
final 5
*/
- 접근 가능
- 자바스크립트 엔진은 변수 선언을 "선언 단계+초기화 단계"에 거쳐 수행한다.
- 선언 단계: 변수 이름 등록하여 존재를 엔진에게 알림
- 초기화 단계: 값을 저장하기 위한 메모리 공간 확보하고 undefinded로 초기화
- 변수 선언 시, 모든 식별자는 실행 컨텍스트에 등록됨. 실행 컨텍스트에는 코드를 실행하기 위한 환경 정보를 담아놓은 객체. 해당 객체에는 변수 객체, 스코프, this 정보가 담겨있음.
ReferenceError: 참조되지 않은 값을 식별자가 접근하려고 할 때 나는 에러가 var 선언 시에는 발생하지 않는다. JS엔진은 변수 선언을 가장 먼저 실행(== 호이스팅)시키는데, var 키워드는 선언+초기화가 동시에 진행되기 때문이다.
console.log(score); // undefined
var score; // 변수 선언문- 변수를 참조하는 코드가 변수 선언문보다 앞에 있음에도 ReferencError가 나지 않는 이유:
- 변수 선언은 소스 코드가 한 줄씩 순차적으로 실행되는 시점(런타임) 이전 단계에서 먼저 실행됨. == 호이스팅
- 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징
- 모든 식별자는 호이스팅됨 (변수, 함수, 클래스 등)
var score; // 변수 선언
score = 80; // 값의 할당- 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행됨
- 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임 때 실행됨
console.log(score); // undefined
var score; // 변수 선언
score = 80; // 값의 할당
console.log(score); // 80- 변수에 값을 할당할 때 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 80을 새롭게 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고 할당 값 80을 저장함
- 이미 값이 할당되어 있는 변수에 새로운 값을 다시 할당하는 것 == 재할당
- 변수에 저장된 값을 변경할 수 없는 것 == 상수
- 사실
var는 선언 하자마자 undefined로 초기화되기 때문에 값을 할당하면, 이것도 재할당에 해당함 const로 선언된 변수는 재할당이 불가능하다. => const로 상수 표현 가능
- 사실
- 변수나 함수 이름 == 카멜 케이스
- 생성자 함수, 클래스 이름 == 파스칼 케이스