블록 레벨 스코프와 함수 레벨 스코프에 대해서 설명해주세요
- 블록 레벨 스코프: 모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등의 중괄호 { }로 둘러싸인 코드 영역) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
- 함수 레벨 스코프: 함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다. 함수 레벨 스코프는 ES5 이전의 JavaScript에서 주로 사용되었지만, 현재는 블록 레벨 스코프가 더 일반적입니다.
let 키워드로 선언한 변수의 생명 주기에 대해서 설명해주세요
- let으로 선언한 변수는 블록 레벨 스코프를 따르며, 변수의 생명 주기는 변수가 선언된 블록 내에서 시작하여 블록을 빠져나가면 종료됩니다. 즉, 변수는 블록의 시작에서 초기화되며, 블록의 끝에서 소멸합니다.
var로 변수를 선언하는 방식이 왜 더 이상 권장되지 않을까요
- var는 함수 스코프를 따르므로 블록 스코프와는 다르게 동작합니다. 또한, var 선언된 변수는 호이스팅(hoisting)으로 인해 변수 선언이 스코프의 최상단으로 끌어올려지며, 초기화 이전에 접근 가능합니다. 이러한 특성은 예상치 못한 결과를 초래할 수 있습니다.
- ES6(ES2015)에서 let와 const 키워드가 도입되었고, 이러한 키워드는 블록 스코프를 따르며 호이스팅을 제한합니다. 이로 인해 코드의 가독성과 예측성이 향상되었고, 버그를 줄일 수 있게 되었습니다. 따라서 var보다는 let와 const를 사용하는 것이 권장됩니다.
- var는 동일한 이름을 갖는 변수를 중복해서 선언이 가능하기 때문에 문제가 생길 수 있습니다.
var과 let, const를 각각 언제 사용하는 것이 좋은가요?
- var: ES6 이전의 환경에서 사용하거나, 호환성 문제로 인해 사용해야 할 때를 제외하고는 var를 피하는 것이 좋습니다.
- let: 블록 스코프 변수를 선언할 때 사용합니다. 재할당이 필요한 경우, let을 사용합니다.
- const: 상수값을 선언할 때 사용합니다. 한 번 할당된 이후에는 값을 변경할 수 없는 변수를 정의할 때 유용합니다. const로 선언된 변수는 재할당이 불가능하며, 값이 변하지 않는 것을 보장합니다.
- 변수를 선언하는 시점에는 재할당이 필요할지 잘 모르는 경우가 많다. 그리고 객체는 의외로 재할당을 하는 경우가 드물다. 따라서 변수를 선언할 때에는 일단 const 키워드를 사용하도록 하자. 반드시 재할당이 필요하다면 그 때 const를 let 키워드로 변경해도 결코 늦지 않는다.
let과 const는 왜 호이스팅이 발생하지 않는 것처럼 보이나요?
- let과 const는 사실 호이스팅(hoisting)이 발생합니다. 그러나 호이스팅된 변수는 "일시적인 사각지대(Temporal Dead Zone, TDZ)"에 빠집니다. TDZ 내에서 변수를 참조하려고 하면 에러가 발생합니다. 이것은 변수가 실제로 선언되기 전에 접근하려고 할 때 예기치 않은 동작을 방지하기 위한 메커니즘입니다. 이로써 코드가 더 예측 가능하고 안정적으로 동작하도록 도와줍니다.
- JavaScript 엔진은 코드 실행 전에 변수 선언을 모두 찾아서 해당 스코프 내의 최상단으로 끌어올립니다. 그러나 let와 const의 경우 변수를 선언할 때 초기화되지 않기 때문에 실제로는 TDZ에 있습니다. TDZ에서 변수에 접근하려고 하면 이는 변수가 아직 정의되지 않았고 초기화되지 않았기 때문에 ReferenceError가 발생합니다. 이것은 개발자에게 변수를 사용하기 전에 변수를 초기화하도록 유도하고 예기치 않은 동작을 방지하는 데 도움이 됩니다. let와 const는 변수를 선언한 라인에서 초기화되며, 변수가 호이스팅된 상태에서 초기화가 이루어집니다. 이것은 변수가 선언되기 전에 변수에 접근하지 못하게 함으로써 코드의 가독성과 예측성을 향상시킵니다.
- 요약하면, let와 const는 호이스팅되지만 TDZ를 도입하여 변수를 초기화하기 전에 변수에 접근하려는 시도를 방지하고 변수 사용의 예기치 않은 동작을 방지합니다.
- let, const로 변수를 선언하는 경우, 자바스크립트 내부에서는 코드 실행 전에는 변수 선언만 해두며, 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행한다. 그렇기 때문에 호이스팅이 발생하기는 하지만, 값을 참조할 수 없어서 호이스팅이 발생하지 않는 것처럼 보이는 것이다.
변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간인 TDZ(Temporal Dead Zone)에 빠졌기 때문에 보이는 현상이다.
자바스크립트가 왜 prototype-based language로 설명되는지 말해주세요.
- 자바스크립트는 프로토타입 기반 언어로 분류됩니다. 이것은 객체지향 프로그래밍의 한 스타일을 의미합니다. 프로토타입 기반 언어에서 객체는 다른 객체로부터 직접 상속받습니다. 객체는 프로토타입(원형) 객체로부터 속성과 메서드를 상속받고 확장할 수 있습니다.
프로토타입 기반의 상속과 클래스 기반의 상속의 차이는 무엇인가요?
- 프로토타입 기반의 상속은 객체 간의 직접적인 연결을(프로토타입 체인) 기반으로 합니다. 한 객체가 다른 객체의 프로토타입이 되고, 상위 객체의 속성과 메서드를 하위 객체가 상속받습니다. 클래스 기반의 상속은 클래스가 인스턴스를 생성하고 인스턴스는 클래스의 정의에 따라 생성됩니다.
프로토타입이란 무엇인가요?
- 프로토타입은 객체 지향 프로그래밍에서 객체 간의 상속 구조를 나타내는데 사용됩니다. 모든 객체는 다른 객체로부터 속성과 메서드를 상속하는데, 이 상속 정보는 해당 객체의 프로토타입 객체에 저장됩니다. 다른 객체의 프로토타입 객체를 참조하고 해당 프로토타입 객체의 속성과 메서드를 상속해서 코드 재사용을 간편하게 할 수 있습니다.
클래스 기반 언어와 프로토타입 기반 언어의 차이점에 대해 설명해주세요.
- 클래스 기반 언어는 클래스라는 추상적인 템플릿을 정의하고 이를 기반으로 객체를 생성합니다. 프로토타입 기반 언어는 객체가 다른 객체를 기반으로 생성되며 클래스 개념이 없습니다.
- 클래스 기반 언어는 상속을 클래스 간의 계층 구조를 통해 관리하는 반면, 프로토타입 기반 언어는 객체 간의 직접적인 연결을 통해 상속을 처리합니다.
- 클래스 기반 언어에서는 객체 생성 후에 클래스 구조를 변경하기 어려울 수 있지만, 프로토타입 기반 언어에서는 런타임에 객체를 동적으로 수정할 수 있습니다.
proto 접근자 프로퍼티와 prototype 프로퍼티의 공통점과 차이점에 대해 설명해 주세요.
- 공통점: 둘 다 프로토타입 체인에서 상속을 관리하는 데 사용됩니다.
- 차이점:
__proto__
: 이것은 객체 자체에 속한 접근자 프로퍼티로, 해당 객체의 프로토타입을 가리킵니다. 이것은 브라우저에서 사용하는 것이며 ECMAScript 표준에서는 권장되지 않습니다.prototype
: 이것은 함수 객체에 속한 프로퍼티로, 생성자 함수로부터 생성된 객체의 프로토타입을 정의합니다. 이것은 주로 객체 생성을 위한 생성자 함수와 함께 사용되며, 클래스 기반의 상속에서 주로 나타납니다.
암시적 바인딩과 명시적 바인딩에 대해서 설명해주세요.
- 암시적 바인딩: 함수 호출 시, 호출한 객체를 가리키는 것을 의미합니다. 주로 메서드 내부에서 사용되며, this 키워드를 통해 암시적으로 바인딩됩니다. 예를 들어, 객체 내부의 메서드를 호출할 때 메서드 내부에서 this는 그 객체를 가리킵니다.
- 명시적 바인딩: 개발자가 명시적으로 this를 지정하는 것을 의미합니다. JavaScript에서는 call, apply, bind를 사용하여 this를 특정 객체로 명시적으로 바인딩할 수 있습니다.
this를 이용하여 개발한 경험 알려주세요. 없다면, 언제 쓰면 유용할 것 같으신가요?
- JavaScript에서 this는 매우 중요한 개념이며, 객체 지향 프로그래밍에서 주로 사용됩니다. 객체의 메서드 내에서 데이터에 접근하거나 조작하는 데 매우 유용합니다. 또한, 이벤트 핸들러와 콜백 함수에서 this를 사용하여 이벤트가 발생한 요소나 호출 문맥을 참조할 수 있습니다. 따라서 JavaScript를 사용하면서 this를 잘 다루는 것이 중요합니다.
call, apply, bind의 역할은 무엇이고 어떻게 사용되나요?
- call과 apply: 함수를 호출하면서 this를 특정 객체로 명시적으로 바인딩하고, 다른 매개변수를 함수에 전달할 수 있게 합니다. call은 매개변수를 일렬로 전달하고, apply는 매개변수를 배열로 전달합니다.
- bind: 함수를 호출하지 않고 새로운 함수를 생성하며, 원래 함수와 this가 바인딩된 새로운 함수를 반환합니다. 나중에 호출할 수 있습니다.
일반 함수의 this와 화살표 함수의 this는 어떻게 다른가요?
- 일반 함수의 this는 함수가 호출될 때 호출 컨텍스트에 따라 동적으로 결정됩니다. 함수를 호출하는 주체에 따라 this가 달라질 수 있습니다.
- 화살표 함수의 this는 정적으로 결정됩니다. 화살표 함수는 자신의 상위 스코프에서 this를 상속하며, 호출 컨텍스트에 영향을 받지 않습니다. 이것은 주로 콜백 함수 내에서 혼동을 줄이고 원래 컨텍스트(this 값)를 유지하기 위해 사용됩니다.
일반 함수 호출, 메서드 호출, 생성자 함수 호출마다 this는 어떤 값으로 바인딩 되나요?
- 일반 함수 호출: this는 전역 객체(브라우저에서는 window)를 가리킵니다. (+ strict 모드에서는 undefined)
- 메서드 호출: this는 메서드를 호출한 객체를 가리킵니다.
생성자 함수 호출: this는 생성된 객체를 가리킵니다. 생성자 함수 내에서 this를 사용하면 새로운 객체가 생성되고 이 객체가 반환됩니다.
https://poiemaweb.com/es6-block-scope
https://dev-coco.tistory.com/112