| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
- react
- React Native
- 네이티브 css
- 리액트 네이티브
- FlatList
- 비지니스로직
- react native routes
- react native navigation
- 리액트 무한스크롤
- react-native
- 전역상태관리
- expo-location
- 리액트 사진크기
- 리액트
- 리액트 네이티브 캐러셀
- 리액트네이티브 라우트
- ui로직
- 리액트쿼리
- HTML
- 자바스크립트
- 리액트쿼리 무한스크롤
- 플랫리스트
- 무한스크롤
- JavaScript
- 리액트 네이티브 네비게이션
- 부트캠프항해
- 리액트네이티브 검색
- React-qurey
- 리액트 네이티브 map
- 프론트엔드 개발블로그
- Today
- Total
솧디의 개발로그
🐥JS 언어특성 공부하기01🐥 본문

🐤 JavaScript의 자료형과 JavaScript만의 특성은 무엇일까 ?
🐳느슨한 타입(loosely typed)의 동적(dynamic) 언어
동적타입 언어: 자료의 타입은 있지만 변수에 저장된 값이 언제든지 바뀜 숫자, 문자로 형태가 변형될 수 있다.
let num = 10;
num = 'hello';
console.log(num)
num을 10이란 숫자를 주었지만 num을 다시 'hello'라는 글자형태로 넣었을 때 값은 'hello'로 변경된다.
문자에서 숫자, 숫자에서 문자로의 변경이 간단하게 가능하다.
[변수]
🌿var
var num = 10
var num = 30
console.log(num)
위 의 경우 num의 값이 '10,30'으로 출력이된다. var 변수의 중복선언이 가능하다. 협업시 서로 같은 변수값을 넣을경우에 모두다 출력된다.
그래서 잘 사용하지않음!
🌿let
let num = 10
let num = 30
console.log(num)
위 의 경우 마지막 선언문과 함께 잘못되었다고 오류가 뜬다. let 데이터를 밑에 데이터로 변경가능고 중복선언이 불가하다.
let num = 20;
num = 30;
위 의 경우 30이 출력이 된다. num값이 마지막 입력한 값으로 변경되었다.
[상수]
🌿const
const num = 10
const num = 30
console.log(num)
위 의 경우에도 오류메세지와 함께 중복선언이 불가하다.
const num = 10;
const num1 = 10;
console.log(num)
위의 경우는 10의 출력값이 나온다. let처럼 중복선언은 불가하지만
변하지않는 상수로써 num, num1은 다른 값을 지닌다.
🐳 JavaScript 형변환이란?
🌿 0은 숫자이지만 '0'으로 [']을 붙여주면 문자로 인식된다.
🐳 ==, ===
'0' === 0
false
0 === 0
true
0 == '0'
true
0 == 0
true
==은 자료형이 달라도 값이 둘다 0이기 때문에 true이다.
표면적인 모습만 맞아도 인식해도 맞는것
===은 정수형과 문자형까지도 둘 다 일치해야 true이다.
외적도 일치하고 내적으로 속성이 일치해야 함
그래서
typeof 10 === 'number'는 true가 나오는데
자료형의 숫자의 속성과 일치하기에 true이다.
🐳 느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지 생각해보세요.
자동형변화의 경우 '10' == 10도 true로 인식되기에 만약 표면적인게 같아도 속성이 달라 오류가 날 수 있다.
이런경우에 ===을 사용해 외,내적 속성이 모두 일치하도록 사용한느것이 좋다고 판단된다.
또한 자바스크립트의 타입이 문자인지 숫자인지 불분명할수있기에 타입스크립트로 문자나, 숫자값이 어떤 값인지 정의를 해주어
오류를 빨리파악하여 디버깅이 쉬워진다.
타입스크립트 예시)
function sum(a: number, b: number) {
return a+ b;
}
sum("x", "y") //Error
🐳 undefined와 null의 미세한 차이들을 비교해보세요.
둘 다 메모리가 할당되지않음은 똑같지만 차이가있음
🌿 undefined : 변수의 값이 할당되기 전에 비워져있는데 비워진게 아니라 undefined이란 값으로 자동 할당 되어있다.
그래서 값이 할당이 되지않았다면 값을 출력했을때 'undefined'로 출력된다.
🌿 null: 명시적으로 변수공간이 비어있음을 의미할 때 사용한다. 즉 사용자가 임의로 이공간을 비워두었다를 표시함
//undefined
let num;
console.log(num) //undefined
//null
let num = null;
console.log(num)//null
🐤 JavaScript 객체와 불변성이란 ?
🐳 기본형 데이터와 참조형 데이터
☑️자료형이란 값이 가질 수 있는 여러가지 유형을 구분한 개념
| 원시타입 | 참조타입 |
| 숫자형(number) | 배열(array) |
| 문자열형(string) | 객체(object) |
| 논리형(boolean) | 함수(function) |
| null | |
| undefined | |
| symbol |
▶️원시타입(기본자료형)
let number = 1; //숫자형(number)
let str ="abc"; /문자열형(string)
let bool =true; //flase or true 논리형(boolean)
let und = undfined; // undfined
let nul = null //null(object)
let symbol(); // symbol
console.log(typeof(1)); // 자료형을 나타냄, 출력값은 number, 자료의 형태를 나타내줌
▶️참조타입 자료형
let arry = [값,값,값]; //배열(objet) 배열에는 값만 존재함
let obj = {키:값};//객체(object)키와 값을 속성이라하기도함
let func = function(){}; //함수(function)
▶️array형 자료예시
//국어, 영어, 수학, 과학점수
let score = [90,80,70,90]
console.log(score[0,1,2])//90,80,70이 출력됨
array는 점수만있고 어떤점수인지 주석이나 설명이없다면 알기가 어려움
▶️object형 자료예시
let student1 = {
koreaScore:90, //국어점수
'englishScore':70,//영어점수, 문자열로 쓰는경우 띄어쓰기할수있음 다만 점연산자로는 쓸수없음
'"mathScore":80,//수학점수
scienceScore:60//과학점수
};
//대괄호 연산자
console.log(student1["koreaScore"]);
//.점 연산자
console.log(student1.englishScore);
array보다 직관적이고 어떤값인지 바로 파악이 가능함
🐳 JavaScript 형변환
할당되는 값은 대부분 적절한 자료형으로 자동변환되는 것을 형변환이라 합니다.
let str = "123";
alert(typeof str); // string
let num = Number(str); // 문자열 "123"이 숫자 123으로 변환됩니다.
alert(typeof num); // number
예를 들어 숫자를 ""를 통해 문자로 입력했다면 문자입니다. 그래서 typeof는 문자입니다.
이 숫자를 number()라는 메소드(명령어)를 이용해서 문자처리된거를 정수로 바꿔주는 것입니다.
불린는 0아님 1이다.
펄시는 0,null,undefined,NaN,'',불리언false
(보통 0이라 생각하면됨)
트루는 1이다.
펄시면(0)이면 실행안되고, 1(트루시)이면 실행되는것
🐳 불변 객체를 만드는 방법
원시타입의 값은 변경불가능한 값이다.
let으로 num값을 80을 주었다고치자, num의 값이 90으로 바뀌었다고해도 진짜 값이 바뀐게 아니라 마지막에 입력된 값을 보여주는 주소가 바뀐 것 뿐이다. 즉 재할당 된 원시값을 가르키고있는것 뿐이다.
그러므로 원시타입의 값을 변경이 불가능하다.
참조변수는 불변객체를 만드는 것이 가능하다.
//참조변수는 변경가능한 값
var o1 ={name:'lee'};
name = 'kim';
console.log(o1)//kim으로 출력됨
그러므로 이러한 점을 막기위해 객체를 불변하게 만들어야한다.
이때 object.freeze 로 객체를 불변하게 만들어주면된다.
//object.freeze로 객체불변하게 만들기
var o1 = {name:'lee'};
object.freeze(o1)
name = 'kim';
console.log(o1)//lee으로 출력됨
🐳 얕은 복사와 깊은 복사
[ 얕은 복사 (Shallow copy)]
우리가 흔히 알고 있듯이, 객체가 담겨 있는 변수를 다른 변수에 할당하면 calll by reference(데이터 복사가 아닌 참조)가 일어나게 되어, 한 변수의 데이터를 변경하면 다른 변수의 데이터도 함께 변경이 된다.
const personq1 = {name:'inyong'};
const person2 = person1;
person1.name = 'jung';
// result
person2.name // 'jung'
person1 === person2; // true - 같은 데이터 주소를 바라보고 있는 두 변수
데이터가 그대로 하나 더 생성된 것이 아닌 해당 데이터의 메모리 주소를 전달하게 돼서, 결국 한 데이터를 공유하게 되는 것이다.
[ 깊은 복사 (Depth copy) ]
한 데이터의 공유가 아닌, 똑같은 구조의 객체를 하나 더 생성하여 따로 사용하고자 할 때가 있다.
이럴 때 우리는 '깊은 복사'라는 개념을 사용한다.
const person1 = { name : "inyong"};
const person2 = Object.assign({}, person1);
person1.name = "jung";
//result
person2.name // 'inyong' - 전혀 다른 메모리 주소의 데이터이므로, person2의 값은 변하지 않음.
person1 === person2 // false - 형태만 같고, 각자 다른 메모리 주소에 저장되어 있는 데이터다.
[출처] JavaScript 객체와 불변성이란 ?|작성자 은둥이
🐤 호이스팅과 TDZ는 무엇일까 ?
🐳스코프, 호이스팅, TDZ
호이스팅
JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않음.
호이스팅을 설명할 땐 주로 "변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는" 것으로 말하곤 한다. 따라서 변수를 정의하는 코드보다 사용하는 코드가 앞서 등장할 수 있다. 다만 선언과 초기화를 함께 수행하는 경우, 선언 코드까지 실행해야 변수가 초기화된 상태가 됨을 주의.
출처:https://developer.mozilla.org/ko/docs/Glossary/Hoisting
호이스팅의 대상
자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
let/const 변수 선언과 함수 표현식 에서는 호이스팅이 발생하지 않음.
foo();
foo2();
function foo() { // 함수선언문
console.log("hello");
}
var foo2 = function() { // 함수표현식
console.log("hello2");
}
함수 선언문과 함수 표현식에서 호이스팅
함수 선언문에서의 호이스팅
함수 선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석 할 때 맨위로 끌어 올려진다.
/* 정상 출력 */
function printName(firstname) { // 함수선언문
var result = inner(); // "선언 및 할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
function inner() { // 함수선언문
return "inner value";
}
}
printName(); // 함수 호출
함수 표현식에서의 호이스팅
함수 표현식은 함수 선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있음.
- 함수 표현식에서는 선언과 할당의 분리가 생긴다.
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
var result = inner(); // ERROR!!
console.log("name is " + result);
var inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
호이스팅은 함수 선언문과 함수 표현식에서 서로 다르게 동작하기 때문에 주의해야 한다. 변수에 할당된 함수 표현식은 끌어 올려지지 않기 때문에 이때는 변수의 스코프 규칙을 그대로 따른다.
Q. printName에서 “inner is not defined” 이라고 오류가 나오지 않고, “inner is not a function”이라는 TypeError가 나오는 이유?
A. printName이 실행되는 순간 (Hoisting에 의해) inner는 ‘undefined’으로 지정되기 때문
inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미
함수 표현식의 선언이 호출보다 아래에 있는 경우
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // ERROR!!
let result = inner();
console.log("name is " + result);
let inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > ReferenceError: inner is not defined
console.log(inner);에서 inner에 대한 선언이 되어있지 않기 때문에 inner is not defined 오류가 발생
호이스팅 사용시 주의할 점
코드의 가독성과 유지 보수를 위해 호이스팅이 일어나지 않도록 해야함.
- 호이스팅을 제대로 모르더라도 함수와 변수를 가급적 코드 상단부에서 선언하면, 호이스팅으로 인한 스코프 꼬임 현상은 방지할 수 있다.
var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까? - ES6를 어디서는 쓸 수 있으려면 아직 시간이 더 필요하다. 그렇기 때문에 ES5로 트랜스 커파일을 해야한다.
위의 이유로 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.
스코프
- 스코프(scope)는 식별자(ex. 변수명, 함수명, 클래스명 등)의 유효범위를 뜻하며, 선언된 위치에 따라 유효 범위가 달라진다. 전역에 선언된 변수는 전역 스코프를, 지역에 선언된 변수는 지역 스코프를 갖는다.
- 전역 변수는 어디에서든지 참조가 가능한 값이다. 반면, 지역 변수는 함수 몸체 내부를 말한다. 따라서 지역 변수는 자신의 지역 스코프와 그 하위 지역 스코프에서 유효하다.
- 한 가지 주의해야 할 점은, 자바스크립트에서 모든 코드 블록(if, for, while, try/catch 등)이 지역 스코프를 만들며, 이러한 특성을 블록 레벨 스코프라 한다. 하지만 var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정한다. 이를 함수 레벨 스코프라 한다.
var a = 1
if (true) {
var a = 5
}
console.log(a) // output: 5
함수가 아닌 곳에서 var 키워드를 이용해 a를 선언했기 때문에 전역 변수로 취급한다. 기존에 있던 a 변수가 중복 선언되면서, 최하단의 console에서도 출력 값이 5로 바뀐 것을 확인할 수 있다.
해당 예제는 코드가 짧아서 어디에서 문제가 일어난지 바로 알 수 있었지만, 실무에서는 그렇지 않다. 전역 변수로 인해 재할당이 발생하거나, 전역 스코프를 공유하기 때문에 어딘가에 동일한 이름이 있다면 예상치 못한 결과를 가져올 수 있는 위험이 있다. 따라서 오로지 함수 코드 블록만을 지역 스코프로 인정하는 var 대신, 블록 레벨 스코프를 지원하는 const와 let을 사용하는 것을 권장한다.
스코프 체인
자바스크립트에서 전역 변수는 전역 객체의 프로퍼티이다. (ECMAScript 명세에 정의되어 있음)
지역 변수는 그런 규정이 없지만, 변수를 각 함수 호출과 연관된 객체(call object)의 프로퍼티로 생각할 수 있다.
지역 변수를 어떤 객체의 프로퍼티로 생각한다면, 자바스크립트의 모든 코드는 스코프 체인을 갖고 있다. 스코프 체인은 해당 코드의 유효 범위(in scope) 안에 있는 변수를 정의하는 객체의 체인, 리스트다.
자바스크립트가 변수 값을 얻으려고 할 때(variable resolution, 변수 해석) 스코프 체인에서 변수를 찾는다. 스코프 체인은 위에서 말했다시피 객체의 리스트이므로, 첫 번째 객체에서 해당 변수를 찾고, 없으면 그 다음 객체에서 해당 변수를 찾고, 여기도 없으면 그 다음 객체에서 찾는 식이다. 리스트의 끝까지 탐색했는데도 그 변수가 없다면 reference error가 발생하는 것이다.
최상위 자바스크립트 코드(어떠한 함수에도 속하지 않는 코드)의 스코프 체인에는 하나의 객체만 있고, 그것이 전역 객체이다. 중첩되지 않은 함수의 스코프 체인은 2개의 객체로 이루어진다. 하나는 함수의 매개변수와 지역 변수를 정의하는 객체고, 다른 하나는 전역 객체다.
함수가 정의될 때, 함수는 스코프 체인을 저장한다.
함수가 호출될 때, 함수는 지역 변수를 보관하는 새로운 객체를 만들고 그 객체를 기존에 만들어둔 스코프 체인에 추가한다.
변수 은닉화
(function () {
var a = 'a';
})();
console.log(a); // a is not defined
함수 외부에서 a를 출력해보면, 아직 정의되지 않았다(a is not defined)는 에러메세지를 확인할 수 있다. 이러한 방식과 같이 직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것을 은닉화라고 한다.
이러한 은닉화과정을 클로저를 통해 자세히 알아보도록 하자.
클로저를 통한 은닉화
자바스크립트에서 일반적인 객체지향 프로그래밍 방식으로 prototype를 사용하는데 객체 안에서 사용할 속성을 생성할 때 this 키워드를 사용하게 된다.
하지만 이러한 Prototype을 통한 객체를 만들 때의 주요한 문제가 하나 있습니다. 바로 Private variables에 대한 접근 권한 문제이다.
아래 코드를 예시로 보도록 하자.
function Hello(name) {
this._name = name;
}
Hello.prototype.say = function() {
console.log('Hello, ' + this._name);
}
let a = new Hello('영서');
let b = new Hello('아름');
a.say() //Hello, 영서
b.say() //Hello, 아름
a._name = 'anonymous'
a.say() // Hello, anonymous
현재 Hello() 함수를 통해 생성된 객체들은 모두 _name이라는 변수를 가지게 된다. 변수명 앞에 underscore(_)를 포함했기 때문에 일반적인 JavaScript 네이밍 컨벤션을 생각해 봤을때 이 변수는 Private variable으로 쓰고싶다는 의도를 알 수 있다.
하지만 실제로는 여전히 외부에서도 쉽게 접근가능한 것을 확인할 수 있다.
이 경우 클로저를 사용하여 외부에서 직접적으로 변수에 접근할 수 있도록 캡슐화(은닉화)할 수 있다.
function hello(name) {
let _name = name;
return function () {
console.log('Hello, ' + _name);
};
}
let a = new hello('영서');
let b = new hello('아름');
a() //Hello, 영서
b() //Hello, 아름
이렇게 a와 b라는 클로저를 생성함으로써 함수 내부적으로 접근이 가능하도록 만들 수 있다.
이번에는 조금 더 간단한 예제를 살펴보도록 하겠다.
function a(){
let temp = 'a'
return temp;
}
// console.log(temp) error: temp is not defined
const result = a()
console.log(result); //a
현재 위 함수 내부적으로 선언된 temp에는 직접적으로 접근을 할 수 없다. 함수 a를 실행시켜 그 값을 result라는 변수에 담아 클로저를 생성함으로써 temp의 값에 접근이 가능하다.
이렇게 함수 안에 값을 숨기고 싶은 경우 클로저를 활용해볼 수 있다.
Temporal Dead Zone(TDZ)
Temporal Dead Zone(TDZ)이란?
선언 전에 변수를 사용하는 것을 비 허용하는 개념상의 공간이다.
const 변수 선언 부터 시작해보자. 변수를 선언하고, 초기화 하면 변수에 접근 할 수 있다.
const white = '#FFFFFF';
white; // => '#FFFFFF'
이번에는 선언 전에 white 변수에 접근
white; // throws `ReferenceError`
const white = '#FFFFFF';
white; // => '#FFFFFF'
const white ='#FFFFFF' 구문 전 줄 까지, white 변수는 TDZ에 있다.
TDZ에 있는 white 변수에 접근하게 되면, ReferenceError: Cannot access 'white' before initialization 자바스크립트 에러가 발생

TDZ의 영향을 받는 구문


현재 스코프 안에서 TDZ 동작
TDZ는 선언문이 존재하는 스코프 범위 안에서 변수에 영향을 준다.

let, const, var, function 원리
[ var ]
es6 이전애는 변수를 선언할 때 var를 이용하여 변수를 선언하였다.
var의 경우엔 function 단위의 scope를 가진다. 이는 함수안에서만 선언 될 경우에 scope를 가지는 것을 의미한다.
if나 for문안에서 var를 선언할 경우 해당 변수는 scope를 if나 for가 아닌 상위의 함수(없으면 전역)를 scope로 가지게 된다.
function func() { var a = 1; // func scope } console.log(a) // error for(var i =0; i<10;i++) { var b = 2; // 전역 scope } console.log(b) // 2
b가 scope가 전역으로 설정이 되면서 다음과 같이 이상한 코드가 발생하게 된다.
function scope와 호이스팅 개념이 만나 다음과 같은 원리로 동작된다고 생각하면 된다.(실제로 이렇게 동작하진 않는다.
var b; function func() { var a; a = 1; } console.log(a) // error for(var i =0; i<10;i++) { b = 2; } console.log(b) // 2
[ let, const ]
let과 const는 es6 이후에 선언 되었다.
위에 처럼 이상한 코드가 실제로 코드를 작성하는 입장에서는 헷갈릴 만한 요소가 많아 block scope로 설정되었다.
block scope는 중괄호 단위로 스코프가 설정되는 것으로 이해하면 된다.
그로인해 for문과 if문안에서 선언할 경우에는 if문과 for문 안에서만 사용가능한 변수로 설정이 된다.
const b = 1; for(var i =0; i<10; i++) { coonsole.log(b) // error const b = 2; }const b = 1; for(var i =0; i<10; i++) { coonsole.log(b) // error const b = 2; }[ let, const는 호이스팅이 일어나지 않나요? ]
이렇게 보면, const, let 에선 호이스팅이 일어나지 않는 것처럼 보인다.
하지만 호이스팅이란 개념은 결국 실행컨텍스트로 인해 발생하는 것임으로 const, let, var 모두 호이스팅이 발생한다.
그러면 왜 호이스팅이 일어나지 않는 것 처럼 보이는 걸까?
이는 const와 let의 값 할당 시점이 var와 다르기 때문이다.
일반적으로 변수는 다음과 같이 실행된다.
변수 선언 > 변수 초기화 > 변수 값 할당
var 의 경우는 변수의 선언과 초기화가 동시에 일어난다.
이말인 즉 변수가 초기화가 되는데 할당이 되기 이전의 상태로 undefiend상태로 존재하게 된다.
그러나 let과 const는 변수의 선언과 초기화가 동시에 일어나지 않는다.
변수의 선언만 인정되어 실행 컨택스트에는 담기게 되나 (호이스팅이 일어난다.) 초기화가 되지 않았기 때문에 초기화 되기 이전에 console 로 실행시키게 되면 error가 발생하게 된다.
[ 결론 ]
var
- function scope
- 호이스팅이 일어난다
- 변수의 선언과 초기화가 동시에 진행
let, const
- pblock scope
- 호이스팅이 일어난다
- 변수의 선언만 일어난다. 변수의 선언과 초기화가 동시에 일어나지 않는다.
실행 컨텍스트와 콜 스택
[ 함수 실행에 대한 이해 ]
- 자바스크립트는 하나의 스레드로 단 1개의 동시성만 다루는 언어
- 한번에 1개의 작업만 다룰 수 있다.
- JS의 Heap Queue Stack => 크롬의 V8 내부에 구현되어 있다.
- 콜스택 CallStack
- 함수의 호출을 기록하는 자료구조
- 우리가 프로그램 안에서 위치한 곳
- 함수 실행 시 스택에 push 된다.
- 함수로부터 반환 받을 때, 스택에서 pop된다.
2. 힙 Heap
- 오브젝트(객체)들은 힙 내부에 할당
- 거의 구조화되지 않은 영역(unsteuctured)의 메모리
- 변수와 객체들의 모든 메모리 할당이 여기서 일어남
3. 큐 Queue
- 자바스크립트 런타임은 메시지 큐를 갖고 있다.
- 메세지 큐
- 실행될 콜백함수나 실행될 메세지들에 대한 리스트
- 스택이 충분한 공간(capacity)를 갖고 있을 때, 메세지는 큐 밖으로 나오고 메세지가 가지고 있던 함수 목록들이 실행된다. -> 초기 스택 프레임
- 스택이 다시 빌 때 메세지 수행도 끝난다.
- 이벤트들에 대한 콜백 함수가 제공되었다면 메세지들은 외부 비동기 이벤트들에 대한 응답으로 큐에 쌓인다.
- 외부 비동기 이벤트들이란 마우스 클릭, HTTP요청 등을 말합니다. 하지만 만일 한 사용자가 버튼을 눌렀는데 아무런 콜백함수도 등록되어 있지 않다면 어떠한 메시지도 큐에 들어가지 않을 것입니다.
- 메시지들은 웹 브라우저에서 언제든 이벤트가 발생했을 때 추가 된다.
[ 실행 컨텍스트 ]
- 실행 컨텍스트는 scope, hoistiong, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리이다.
- ESMAScript 스펙에 따르면 실행 컨텍스트를 실행 가능한 코드를 형성화하고 구분하는 추상적인 개념이라고 정의한다.좀 더 쉽게 말하자면 실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경 이라고 말할 수 있겠다. 여기서 말하는 실행 가능한 코드는 아래와 같다.
- 전역 코드 : 전역 영역에 존재하는 코드
- Eval 코드 : eval 함수로 실행되는 코드
- 함수 코드 : 함수 내에 존재하는 코드
- 일반적으로 실행 가능한 코드는 전역 코드와 함수 내 코드이다.
eval 함수 :
eval()은 전역 객체의 함수 속성입니다.
eval()의 인자는 문자열입니다. 인자가 표현식을 나타낸다면 eval()은 표현식을 평가합니다. 인자가 하나 이상의 JavaScript 명령문을 나타낸다면 모두 실행합니다. 연산식을 계산하기 위해 eval()을 호출하지 마세요. 자바스크립트는 연산식을 알아서 계산합니다.
자바스크립트 엔진은 코드를 실행하기 위하여 실행에 필요한 여러가지 정보를 알고 있어야 한다. 실행에 필요한 여러가지 정보란 아래와 같은 것들이 있다.
- 변수 : 전역변수, 지역변수, 매개변수, 객체의 프로퍼티
- 함수 선언
- 변수의 유효범위(Scope)
- this
이와 같이 실행에 필요한 정보를 형상화하고 구분하기 위해 자바스크립트 엔진은 실행 컨텍스트를 물리적 객체의 형태로 관리한다.
- 컨트롤이 실행 가능한 코드로 이동하면 논리적 스택 구조를 가지는 새로운 실행 컨텍스트 스택이 생성된다. 스택은 LIFO(Last In First Out, 후입 선출)의 구조를 가지는 나열 구조이다.
- 전역 코드(Global code)로 컨트롤이 진입하면 전역 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 쌓인다. 전역 실행 컨텍스트는 애플리케이션이 종료될 때(웹 페이지에서 나가거나 브라우저를 닫을 때)까지 유지된다.
- 함수를 호출하면 해당 함수의 실행 컨텍스트가 생성되며 직전에 실행된 코드 블록의 실행 컨텍스트 위에 쌓인다.
- 함수 실행이 끝나면 해당 함수의 실행 컨텍스트를 파기하고 직전의 실행 컨텍스트에 컨트롤을 반환한다.
느낀점
- 나름 js를 써봤다고 생각했는데 동작원리나 세부적인 오류 과정을 생각해본적이 없었다.
- js를 쓰면서 어떠한 부분에서 오류가 생기는지 조금은 더 빠르게 파악할 수 있게 됐다.
[출처] 호이스팅과 TDZ는 무엇일까 ?|작성자 은둥이
'Javascript 자바스크립트' 카테고리의 다른 글
| JavaScript의 ES란?, ES5/ES6 문법 차이 (0) | 2022.10.02 |
|---|---|
| [자바스크립트] 자주쓰는 배열 함수들 01 (0) | 2022.09.26 |