JavaScript의 핵심적인 개념에 대해 얼마나 깊이 이해하고 있는지,
그리고 이러한 이해를 바탕으로 복잡한 문제를 해결할 수 있는 능력이 있는지 평가하려는 것입니다.
//함수 (기명함수)
function add(num1, num2) {
return num1 + num2;
}
//함수를 변수에 할당한 것 (익명함수)
const add2 = (num1, num2) {
return num1 + num2;
}
const add3 = function (num1, num2) {
return num1 + num2;
}
add(2, 3); //5
add2(2, 3); //5
add3(2, 3); //5
const someFn = (callback) => {
const someValue = callback();
returen somValue;
}
함수 선언(Function Declaration)과 함수 표현식(Function Expression) : JavaScript에서 함수는 선언적 형식과 표현식 형식으로 정의될 수 있습니다. 이들 간의 차이점과 언제 어떤 것을 사용해야 하는지에 대해 이해해야 합니다.
익명함수(Annonymous Function)와 기명 함수(Named Function) : JavaScript에서 함수는 이름이 있거나 없을 수 있습니다. 이들 간의 차이점과 언제 어떤 것을 사용해야 하는지에 대해 이해해야 합니다.
실행 컨텍스트(Execution Context) : JavaScript의 실행 컨텍스트는 실행 가능한 코드에 제공할 환경 정보들을 모아놓은 객체로, 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념입니다. 이것은 변수, 함수 선언, 스코프, this 키워드 등을 관리합니다.
변수 환경(Variable Environment)와 활성 객체(Active Object) : 이들은 실행 컨텍스트 내부에 존재하며, 변수와 함수 선언을 담당합니다.
호이스팅(Hoisting) : JavaScript에서 변수와 함수 선언이 그들의 포함된 스코프의 상단으로 끌어올려지는 동작을 의미합니다. 이것이 어떻게 작동하는지에 대해 이해해야 합니다.
클로저(Closure) : 클로저는 JavaScript의 함수 실행 컨텍스트, 그리고 스코프 체인과 밀접한 관련이 있습니다. 클로저는 함수가 선언된 시점의 환경을 기억하는 JavaScript의 중요한 특징입니다.
this 키워드 : JavaScript의 this 키워드는 함수가 실행되는 컨텍스트를 참조합니다. this는 다른 프로그래밍 언어와 달리, JavaScript에서는 함수가 호출되는 방식에 따라 결정됩니다.
스코프(Scope)와 스코프 체인(Scope Chain): 스코프는 변수와 함수의 접근성과 생명 주기를 결정합니다. 스코프 체인은 변수의 검색을 위한 메커니즘입니다.
전역 컨텍스트(Global Context): JavaScript 코드가 시작 실행될 때, JavaScript 엔진은 전역 실행 컨텍스트를 생성합니다. 전역 컨텍스트는 코드가 실행되는 동안 유지되며, 전역 변수와 전역 함수를 포함합니다.
함수 컨텍스트(Function Context): 함수가 호출될 때마다, JavaScript 엔진은 해당 함수를 위한 새로운 실행 컨텍스트를 생성합니다. 이 컨텍스트는 함수의 매개변수, 내부 변수 및 함수 선언에 대한 정보를 포함합니다.
실행 컨텍스트 스택(Execution Context Stack): 실행 컨텍스트는 실행 컨텍스트 스택 (또는 호출 스택)에 푸시되고 팝되는 방식으로 관리됩니다. 현재 실행 중인 컨텍스트는 항상 스택의 맨 위에 있습니다.
렉시컬 환경(Lexical Environment): 렉시컬 환경은 식별자 변수를 위한 환경 레코드와 외부 환경에 대한 참조를 포함하는 구조입니다. 실행 컨텍스트는 렉시컬 환경을 이용해 변수와 함수를 관리합니다.
블록 스코프(Block Scope): let과 const 키워드를 사용해 선언된 변수는 블록 스코프를 가집니다. 이는 해당 변수가 선언된 블록 내에서만 접근 가능하다는 것을 의미합니다.
함수 호이스팅(Function Hoisting)과 변수 호이스팅(Variable Hoisting): 함수 선언은 함수 호이스팅이 발생하며, var 키워드로 선언된 변수는 변수 호이스팅이 발생합니다. 그러나 let과 const 키워드로 선언된 변수는 호이스팅이 발생하지 않습니다.
즉시 실행 함수 표현식(IIFE, Immediately Invoked Function Expression): IIFE는 선언과 동시에 실행되는 JavaScript 함수입니다. 이것은 변수 충돌을 피하고 코드를 모듈화하는 데 유용합니다.
const { log } = console;
const sayHello = () => {
log('안녕하세요');
}
sayHello(); // '안녕하세요'
//즉시 실행함수
(() => {
log('안녕하세요')
})(); // '안녕하세요'
🧐 CallStack (Execution Context Stack)에 대해 더 깊게 파보자. primitive한 값들은 콜스택에 쌓인다고 했는데 도대체 어디에 쌓이는지 어떤식으로 실행할 코드에 제공할 환경 정보들을 모아놓는지
자세히 알아보자
📖 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로, 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념입니다. (...) 실행 컨텍스트는 자바스크립트에서 가장 중요한 핵심 개념 중 하나입니다. 사실 클로저를 지원하는 대부분의 언어에서 이와 유사하거나 동일한 개념이 적용되어 있습니다. 실행 컨텍스트를 정확히 이해하는 것은 자바스크립트 뿐 아니라 일반적인 개발자로서의 실력 향상에도 큰 도움이 될 것입니다.
장재남, <코어 자바스크립트>
💡 실행 컨텍스트(EC)는 JavaScript 코드가 실행되는 환경으로 정의되고, 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
여기서환경
이란? JavaScript 코드가 특정 시간에 엑세스 할 수 있는this
, 변수, 객체, 함수의 값을 의미한다.
var outer = function () {
var count = 1;
var inner = function () {
return ++count;
};
return inner;
}
var outer2 = outer();
console.log(outer2); //inner 함수 반환
console.log(outer2()); //inner() 인데 inner함수는 가로막혀있다 클로저에 의해 count 값 업데이트 됨
💡 Lexical Environment 안에 있는 Record 와 Outer Environment 를 가지고 호이스팅과 스코프를 알아보자
- 호이스팅 ? 선언문이 마치 최상단에 끌어올려진 듯한 현상
- Environment Record ? 식별자와 식별자에 바인딩된 값을 기록
JS 엔진이 우리의 스크립트를 받게 되면, 첫 번째 일은 우리 코드의 데이터를 위한 메모리 설정입니다. 이 시점에서 코드는 실행되지 않으며, 단순히 실행을 위한 모든 것을 준비하는 것 뿐입니다. 함수 선언과 변수가 저장되는 방식은 다릅니다. 함수는 전체 함수에 대한 참조와 함께 저장됩니다(함수 호이스팅).
여기선 선언문만 실행해서 Record에 기록 하는 일을 하고,
함수일 경우 함수 호이스팅을 하고
var, const, let 키워드로 만들어진 변수일 경우 변수 호이스팅을 합니다.
console.log(name);
var name = 'nuri';
console.log(name2);
let name2 = 'nuri2';
// Environment Record
{
name: undefined,
name2: <uninitialized> // let으로 선언된 변수는 undefined로 초기화 되지 않음 >> 레퍼런스 에러가 뜸
}
함수 호이스팅과 변수 호이스팅 차이점?
차이점은 생성단계시점에서 value의 담을 때 어떤 값을 담느냐 입니다
- 함수 호이스팅 :: 함수식별자, 함수를 모두 기록합니다.
- 변수 호이스팅 :: 변수식별자를 담고 값은 undefined로 초기화 합니다.
선언문 외의 나머지 코드를 순차적으로 실행합니다.
이 때는 Environment Record를 참조하거나 업데이트할 사항이 있다면 업데이트 합니다.
console.log(sum(2, 3));
console.log(city);
console.log(name);
function sum(x, y) {
return x+y;
}
const name = "nuri";
let info = {
age: 21,
nationality: "Korea"
}
var city = "Seoul";
// Environment Record (Execution Context 생성단계)
{
sum : <function>,
name : <uninitialized>,
info : <uninitialized>,
city : undefined
}
// (실행 후)
{
sum : <function>,
name : "nuri",
info : <Object>,
city : "Seoul"
}
const name = "nuri";
const age = 21;
const city = "Seoul";
function getPersonInfo {
const name = "Sori";
const age = 24;
return `${name} is ${age} and lives in ${city}`;
}
console.log(getPersonInfo()); // Sori is 24 and lives in Seoul
//Global Execution Context
{
name: "nuri",
age: 21,
city: "Seoul"
}
//Local Executioin Context
{
name: "Sori",
age: 24
//city가 function 내에 존재하지 않기 때문에 외부에서 찾게 된다. (스코프체이닝)
}
const name = "sol";
const age = 20;
const city = "Seoul";
function getPersonInfo (name, age){
return `${name} is ${age} and lives in ${city}`;
}
console.log(getPersonInfo('Sihyun', 25)); //Sihyun is 25 and lives in Seoul