이벤트 위임이란?
- 이벤트 위임은 event bubbling을 활용해 이벤트 리스너를 하위 요소에 추가하는 대신 상위 요소에 추가하여, 이벤트 핸들러를 줄임으로써 메모리 사용을 줄이는 방법을 말한다.
이벤트 전파의 의미와 그 종류?
- 이벤트 전파란 여러 이벤트가 발생하는 순서를 정하는 방식을 말한다. 이는 HTML 태그가 중첩되어 있기 때문이며, 여러 태그에 각각 이벤트가 설정되어 있을 때(이게 중요하다! 만약 자식 태그에만 이벤트가 등록됐을 경우, 부모 태그는 무시하고 자식 태그의 이벤트만 발생될 것이기 때문임) 어떤 것부터 실행할지를 결정하는 것을 말한다. 종류는 이벤트 캡처링과 이벤트 버블링 2가지가 있다.
- 이벤트 버블링이란 하위 태그에서부터 상위 태그로 올라가는 것을 말한다. 기본적으로 설정된다.
- 이벤트 캡처링이란 반대로 상위 태그에서 시작해서 하위 태그로 이벤트가 전파되는 구조를 말한다. addEventListner의 세번째 인자에 capture: "true" 속성을 추가함으로써 가능하다.
// html
<body>
<div class="one">
1
<div class="two">
2
<div class="three">
3
</div>
</div>
</div>
</body>
// ① 이벤트 버블링 방식 (Event Bubbling)
var divs = document.querySelectorAll("div");
divs.forEach(function (div) {
div.addEventListener("click", logEvent);
});
function logEvent(event) {
console.log(event.currentTarget.className);
}
// ② 이벤트 전파 방식 (Event Capture)
var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
div.addEventListener('click', logEvent, {
capture: true // default 값은 false입니다.
});
});
function logEvent(event) {
console.log(event.currentTarget.className);
}
JavaScript에서 this는 무엇이며 this가 작동하는 방식은?
- this는 실행 컨텍스트에 속하며, 이는 실행 컨텍스트가 전역 범위와 함수 범위로 구분됨에 따라, this의 값도 바뀌게 된다. 전역 컨텍스트의 자바스크립트(브라우저 측)에선 this는 전역객체인 window를 가리키며, Node.js에선 module.exports를 가리킨다. 함수 컨텍스트에서의 this는 JavaScirpt에선 여전히 window를 가리키며, 객체 메서드 안에선 객체를 가리킨다. Node.js에선 global 객체를 가리킨다. global 객체에는 우리가 자주 쓰는 console, process 등이 속한다.
- this의 값은 함수가 호출되는 방식에 따라 다르다. 규칙은 다음과 같다.
- new keyword로 함수를 호출하면, 해당 함수 내부에 있는 this는 완전히 새로운 객체이다.
- apply, call, bind가 함수의 호출 및 생성에 사용되는 경우, 함수 내의 this는 apply, call, bind의 인수로 전달된 객체이다. 다르게 말하면, apply, call, bind 함수는 매개변수로 등록되는 객체의 this를 사용하기 위해 사용한다고 볼 수 있다.
- obj.method()와 같이 함수를 메서드로 호출하는 경우,
this
는 함수가 프로퍼티인 객체이다. - 위 경우를 제외하면 this는 전역 객체이며, 브라우저에서는 window 객체이다. 엄격 모드('use strict') 일 경우, this는 undefined가 된다.
- 복수의 조건에 해당되는 경우, this 값을 설정한다.
- 함수가 ES2015 화살표 함수인 경우 위의 모든 규칙을 무시하고 생성된 시점에서 주변 스코프의 this값을 받습니다.
프로토타입 상속의 작동 원리는?
- 객체의 프로퍼티에 접근할 때 해당 객체에 해당 프로퍼티가 없으면, 객체의
__proto__
와__proto__
의__proto__
와 같이 프로토타입 체인을 따라 내려가, 해당 프로퍼티 정의가 있을 때까지 찾는다.
CommonJS와 AMD의 등장배경을 설명하시오.
- 과거에는 주로 브라우저에서 HTML 파일내부에 태그를 삽입하여 Javascript 모듈을 로드했다. 그러나 이 방식은 자바스크립트 파일(또는 모듈)끼리 서로 모듈을 공유하는데 제약이 없다는 점에서 한계가 있다. 그 이유는 script 태그로 로드된 모듈은 모두 window 객체의 속성이기 때문에 서로 다른 파일에 위치하면서도 모든 객체를 공유할 수 있기 때문이다. 이 때문에, 모듈을 관리하기 위해 클로저를 이용했다.
- 이를 해결하기 위한 수단으로 모듈이라는 개념을 도입하여 정의한 방법(또는 표준)이 CommonJs 와 AMD이다.
CommonJS란?
- ES2015(ES6)에서 등장한 방식인 CommonJS는 모듈 방식의 노드 스타일에 가까운 방식으로 동기식 모듈 시스템이다. 웹팩과 같은 번들링 도구를 사용할 때도 CommonJS를 사용한다.
- 모듈을 내보낼 때는 exports 및 module.exports, 가져올 땐 require 를 사용한다.
- ES6 모듈시스템을 사용하려면, Node.js 버젼이 13이상인 경우에는 pacakage.json에 { "type" : "module" }을 추가하거나 .mjs로 저장해주면 된다.
AMD란?
- CommonJS와는 다르게, AMD(Asynchronous Module Definition)는 비동기 방식의 모듈 시스템이다. AMD는 브라우저 환경에서도 모듈을 사용할 수 있도록 만드는 것을 목표로 한다.
ES6의 모듈 시스템
- 모듈을 불러올 때는 import, 모듈을 내보낼 때는 export를 사용한다.
- 반대로 package.json에 { "type" : "commonjs" }를 추가하거나, .cjs로 파일을 저장하면 commonJS 방식의 모듈 시스템을 사용할 수 있다.
IIFE란 무엇이고 어디에 쓰이며, function foo(){ }();를 IIFE로 만들기 위해서는 무엇을 바꿔야하나요?
- 먼저 IIFE란 즉시호출함수를 말하며, 호출가 동시에 실행되는 함수를 말한다. 주로 한 번 사용되고 다른 곳에서는 사용할 필요가 없는 콜백으로 사용된다.
- (function foo(){ })() 그리고 (function foo(){ }())와 같이 함수를 ()로 묶으면 함수 식이 되고, 이렇게하면 다음 ()로 함수를 실행할 수 있다. 이러한 함수는 전역 범위에 노출되지 않으며, 본문 내에서 이 함수 자체를 참조할 필요가 없는 경우에는 해당 함수의 이름을 생략할 수도 있다.
null, undefined, undeclared의 차이점은 무엇인가요?
- null은 아무런 값도 할당하지 않있다는 것을 명시적으로 나타낸 것이다. undefined는 변수가 선언되었지만, 값은 할당되지 않았을 때 나타나는 타입이다. undeclared는 var, let, const를 사용하지 않고 생성한 변수에 값을 할당할 때 생성된다.
렉시컬 환경이란 무엇인가?
- 자바스크립트에선 실행 중인 함수, 코드 블록 {...}, 스크립트 전체는
렉시컬 환경(Lexical Environment)
라 불리는내부 숨김 연관 객체
를 갖는다. 그리고 렉시컬 환경 객체는 환경 레코드와 외부 렉시컬 환경에 대한 참조로 구분된다. - 변수를 예로 들어보자. 변수에는 전역변수와 지역변수로 나뉘는데, 자바스크립트에서 지역변수는 블록 스코프를 따르는 변수이다. 이는 하나의 블록 안에서만 값을 사용할 수 있는 경우를 말하며, 이는 렉시컬 환경에서 환경 레코드로 관리된다.
- 함수의 경우, 함수를 함수 선언식으로 선언하거나 함수를 호출하면 새로운 렉시컬 환경이 생성된다. 예를 들어, 파라미터가 있는 함수를 호출했을 때 해당하는 렉시컬 환경이 생성되고 그 후 이는 외부 렉시컬 환경으로 전역 렉시컬 환경을 참조하게 된다. 이는 다르게 표현하면, 스코프 체인이 생성되었다고도 말한다.
클로저는 무엇이며, 어떻게/왜 사용하나요?
- 클로저린 함수와 해당 함수가 선언된 렉시컬 환경의 조합을 말한다. 클로저는 외부함수가 반환된 후에도 외부 함수의 변수 범위 체인에 접근할 수 있는 함수를 말한다.
- 클로저는 주로 private method를 모방할 때 활용된다. 또한 자바스크립트 디자인 패턴 중, 모듈 패턴에서 주로 활용되며 이는 CommonJS와 같은 모듈 시스템을 구성하는 주요 패턴이다.
- 또한 아래와 같이 선언되자마자 호출되는 함수를 즉시호출함수(IIFE)라고 하며, 클로저에서 주로 사용된다. 그리고 클로저 함수는 외부에서 직접 접근할 수 없는 private 변수에 접근하여 값을 조작하는 함수를 말한다.
var testModule = (function () {
var counter = 0;
return {
incrementCounter: function () { // 클로저 함수 ① 비공개 변수인 counter의 값을 1만큼 증가시킨다.
return counter++;
},
resetCounter: function () { // 클로저 함수 ②, 비공개 변수인 counter의 값을 0으로 초기화한다.
console.log( "counter value prior to reset: " + counter );
counter = 0;
}
};
})();
// Usage: Increment our counter
testModule.incrementCounter();
// Check the counter value and reset
// Outputs: counter value prior to reset: 1
testModule.resetCounter();
실행 컨텍스트란 무엇인가요?
- 실행 컨텍스트란
실행 가능한 코드가 실행되기 위해 필요한 환경
을 말한다. 이는 렉시컬 환경, 변수 객체(파라미터와 변수 정보), this로 구성된다. - 또한 이는 전역 컨텍스트와 함수 컨텍스트로 나뉜다. 브라우저가 스크립트를 로딩하면 전역 컨텍스트가 먼저 생성된 후, 함수 호출 시마다 컨텍스트가 생성된다.
- 컨텍스트 생성 후 함수가 실행되는데, 사용되는 변수들은 변수 객체 안에서 값을 찾고 없다면 스코프 체인을 따라 올라가며 찾는다.
- 함수 실행이 마무리되면 해당 컨텍스트는 사라진다.
호이스팅이란 무엇인가?
- var 변수 선언과 함수 선언문으로 함수를 선언할 때 선언 부분이 최상단으로 끌어올려지는 현상을 말한다. 함수표현식은 호이스팅되지 않는다.
- 자바스크립트 Parser는 함수를 실행하기 전에 해당 함수를 한 번 쭉 훑은 후, 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 아래 쪽에 존재하는 내용 중 필요한 값들을 끌어올려 실행한다.
// 작성한 코드 ①
console.log(firstName);
var firstName = "joonho"; // var 변수
let lastName = "lee"; // let 변수
// 호이스팅된 결과 ②
var firstName; // Hoisting "선언"
console.log(firstName); // undefined
firstName = "joonho"; // "할당"
let lastName = "lee"; // Hoisting 발생 X
// 작성한 코드 ②
catName("Chloe");
function catName(name) {
console.log("My cat's name is " + name);
}
// 호이스팅된 결과 ②
function catName(name) {
console.log("My cat's name is " + name);
}
catName("Chloe");
- 코드의 가독성과 유지보수의 편의성을 위해, 호이스팅 현상은 사전에 예방할 필요가 있다. 따라서 var 변수 대신, let/const를 사용하는 편이 좋다.
프로토타입 상속은 어떻게 작동하나요?
var arr = ['zero', 'one'];
var obj = {
'0':'zero',
'1':'two'
}
function func () {
return console.log("function");
}
console.log(typeof arr); // 출력결과: object
console.log(typeof obj); // 출력결과: object
console.log(typeof func); // 출력결과: function (그러나 함수 또한 객체이다)
- 자바스크립트 객체의 종류에는 배열(Array.prototype), 일반 객체(Object.prototype), 함수(Function.prototype, 1급 객체라고 표현하기도 함)가 있다. 모든 자바스크립트 객체는 다른 객체에 대한 참조인 proto 프로퍼티를 가진다. Object의 proto 프로퍼티는 Object.prototype을 가리키며, 함수의 proto 는 Function.prototype을 가리킨다. 그리고 각각의 prototype은 각 객체의 부모 객체가 된다.
- 특정 객체의 프로퍼티에 접근했음에도 아무런 값이 없는 경우, 부모 객체의 프로퍼티를 조회한다. 만약 부모 객체에도 없을 경우, 그 부모의 부모 객체를 조회하는 방식으로 동작한다.
일급객체(first-class-object)란 무엇이며, 해당 성격을 통해 무엇을 만들 수 있나요?
- 프로그래밍 언어 디자인에서, 특정 언어의 first-class citizens(first-class type, 또는 first-class object, 또는 first-class value라고도 할수 있는데)이란 보통 다른 객체들에게 적용 가능한 연산을 모두 지원하는 객체를 말한다.
- Javascript에서는 함수가 일급 객체이다. 따라서 함수를 반환하거나 파라미터로 전달 할 수 있을 뿐만 아니라 변수로 전달 받을 수도 있습니다. 또한 함수를 받을 수 있는 함수를 만들수 있으니 함수형 프로그래밍으로 Javascript가 인기가 있어지는 이유이도 합니다. 그래서 다음과 같이, 하나 이상의 함수를 인수로 받거나 함수를 반환하는 고차 함수를 만들 수 있다. 이는 자바스크립트에서 가능하므로, 리액트에서도 당연히 가능하다.
// ① 먼저, 함수(클래스도 사실 함수이므로)를 선언합니다.
class CommentList extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
// "DataSource" 는 글로벌 데이터 소스입니다.
comments: DataSource.getComments()
};
}
componentDidMount() {
// 변화감지를 위해 리스너를 추가합니다.
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
// 리스너를 제거합니다.
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
// 데이터 소스가 변경될때 마다 comments를 업데이트합니다.
this.setState({
comments: DataSource.getComments()
});
}
render() {
return (
<div>
{this.state.comments.map((comment) => (
<Comment comment={comment} key={comment.id} />
))}
</div>
);
}
}
// ② 이 함수는 컴포넌트(함수)를 매개변수로 받고..
function withSubscription(WrappedComponent, selectData) {
// ...다른 컴포넌트를 반환하는데...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ... 구독을 담당하고...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... 래핑된 컴포넌트를 새로운 데이터로 랜더링 합니다!
// 컴포넌트에 추가로 props를 내려주는 것에 주목하세요.
// ③ 이렇게 컴포넌트(함수)를 리턴해줄 수 있습니다.
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
// ④ 또한 이런 식으로 함수를 변수(여기선 리액트 컴포넌트)에 할당할 수 있습니다.
const CommentWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
함수선언식 방식과 함수 표현식, 그리고 화살표 함수 방식의 차이점은?
- 먼저 함수 선언식 방식과 함수 표현식 방식의 차이는 전자는 호이스팅에 영향을 받지만, 후자는 호이스팅에 영향을 받지 않는다는 점이다. 그리고 ES6 부터 추가된 화살표 함수 표현식은 함수 표현식(익명 함수)의 단축 표현이다.
- 그러나 function을 이용한 선언 방식(함수 표현식 방식을 포함)과 화살표 함수의 차이점이 있는데, 서로 this 값이 달라진다는 점이다. 다음은 객체의 메소드로 function을 이용한 선언 방식과 화살표 방식의 차이를 보여준다. 전자의 this는 자신이 속한 객체를 가리키고, 후자의 this는 undefined를 가리킨다. 이는 화살표 방식으로 호출된 함수에 속하는 this는 자기 자신을 가리키기 때문이다.
let car = {
name: "sonata",
ph: "5",
fullInfo: function () {
return this.name + " " + this.ph;
},
funcFullInfo() {
return this.name + " " + this.ph;
},
arrowFullInfo: () => {
return this.name + " " + this.ph;
},
whatIsThis: () => {
return this;
}
};
console.log(car.fullInfo()); // "sonata 5"
console.log(car.arrowFullInfo()); // "undefined"
console.log(car.funcFullInfo()); //"sonata 5"
console.log(car.whatIsThis() === this); // true
- 또한 class(사실 function)으로 선언된 경우는 this가 자신이 종속된 객체를 가리키고 화살표 함수는 자신이 종속된 인스턴스를 가리킨다.
class black() {
this.name = "흰둥이";
return {
name: "검둥이",
bark: function() {
console.log(this.name + "멍멍");
}
}
}
const blackDog = new BlackDog();
blackDog.bark(); // "검둥이(this)" + "멍멍"
class white(){
this.name = "흰둥이";
return {
name: "검둥이",
bark: () => {
console.log(this.name + "멍멍");
}
}
}
const whiteDog = new WiteDog(); // 인스턴스 생성
whiteDog.bark(); // "흰둥이(this)" + "멍멍"
반응형
'Language > JS(Node.js)' 카테고리의 다른 글
프론트엔드 면접 질문 정리 ⑤ TypeScript 질문 (0) | 2021.05.27 |
---|---|
[JavaScript 내장함수 다루기 ③] Array.Prototype.map, 배열의 원소를 1:1 매핑해보자. (0) | 2021.05.17 |
[JavaScript 내장함수 다루기 ②] Array.Prototype.Filter, 조건에 부합하는 값만 반환한다. (0) | 2021.05.12 |
[JavaScript 객체 파헤치기 ①] Object.key(obj), 객체의 필드 값을 배열로 반환해준다 (0) | 2021.05.12 |
[JavaScript 내장함수 다루기 ①] Array.Prototype.Sort, 자바스크립트로 정렬하기 (0) | 2021.05.06 |
댓글