Front-End Interview Question - Javascript Question
event delegation에 관해 설명해주세요.
이벤트 위임(Event Delegation)은 다수의 자식 요소에 각각 이벤트 핸들러를 바인딩하는 대신 하나의 부모 요소에 이벤트 핸들러를 바인딩하는 방법입니다.
예제를 통해 살펴보면
#parent Element에 자식으로 #child-* Element가 다수 있습니다. 이때 각각의 자식 요소에 이벤트 리스너를 바인딩합니다.
자식 Element의 갯수만큼 이벤트 리스너는 바인딩 되고 자식 Element의 갯수가 늘어나게 된다면 이벤트 리스너를 바인딩하는 코드 역시 늘어나게 될 것입니다.
이러한 코드의 중복사용을 막기 위하여 Event Delegation을 이용합니다.
이때 Event Bubbling의 원리를 이용해 자식 Element에서 이벤트가 발생하게 되면 부모 Element로 점점 전파되어 document레벨까지 도달하게 됩니다.
즉 모든 자식 Element에게 이벤트를 바인딩 할 필요없이 부모 Element에게만 이벤트 리스너를 바인딩하면 된다는 뜻이죠
바뀐 코드를 살펴보겠습니다.
부모 Element에 이벤트 리스너를 바인딩 한 후 전달받은 e 인자를 통해 Element 타겟을 검사합니다.
e.target.nodeName으로 Elemnt가 li인 요소만 이벤트를 발생하도록 합니다.
이를 통해 모든 자식 Element에서 이벤트 리스너를 바인딩 할 필요 없이 부모 Element에게 이벤트 위임(Event Delegation)되었습니다.
this는 JavaScript에서 어떻게 작동하는지 설명해주세요.
prototype 기반 상속은 어떻게 하는지 설명해주세요.
참조 : Javascript Prototype
AMD와 CommonJS는 무엇이고, 이것들에 대해 어떻게 생각하시나요?
두 가지 모두 ES2015 가 등장할 때까지 JavaScript 에 기본적으로 존재하지 않는 모듈 시스템을 구현하는 방법입니다.CommonJS 는 동기식인 반면 AMD (Asynchronous Module Definition - 비동기식 모듈 정의)는 분명히 비동기식입니다.CommonJS 는 서버-사이드 개발을 염두에 두고 설계되었으며 AMD 는 모듈의 비동기 로딩을 지원하므로 브라우저용으로 더 많이 사용됩니다.
AMD 은 구문이 매우 장황하고 CommonJS 은 다른 언어로 된 import 문을 작성하는 스타일에 더 가깝습니다. 대부분의 경우 AMD 를 필요로 하지 않습니다. 모든 JavaScript 를 연결된 하나의 번들 파일로 제공하면 비동기 로딩 속성의 이점을 누릴 수 없기 때문입니다. 또한 CommonJS 구문은 모듈 작성의 노드 스타일에 가깝고 클라이언트-사이드과 서버-사이드 JavaScript 개발 사이를 전환할 때 문맥 전환 오버 헤드가 적습니다.
ES2015 모듈이 동기식 및 비동기식 로딩을 모두 지원하는 것이 반가운 것은 마침내 하나의 접근 방식만 고수할 수 있다는 점입니다. 브라우저와 노드에서 완전히 작동되지는 않았지만 언제나 트랜스파일러를 사용하여 코드를 변환할 수 있습니다.
참고 : 프론트엔드 인터뷰 핸드북다음 코드가 즉시 호출 함수 표현식(IIFE)로 동작하지 않는 이유에 관해서 설명해보세요:
- function foo(){ }();
- IIFE로 만들기 위해서는 어떻게 해야 하나요?
즉시실행함수의 경우 (function() { })() 와 같은 형태로 작성되어야 합니다.
함수명은 필요 없으며 function keyword 앞에 괄호와 중괄호 뒤 괄호가 필요합니다.
또한 일반적인 함수 호출과는 다르게 함수를 만들고 호출할 필요가 없으며 코드만 넣어주면 됩니다.
null과 unedefined 그리고 undeclared의 차이점은 무엇인가요?
- 두개를 구분하기 위해서는 어떻게 하면 될까요?
null : javascript 에서의 null은 값이 아닌 객체참조의 연결을 해지하는 것을 말합니다.
즉 참조값이 존재 하지 않기 때문에 비어있는 값을 가진 변수가 되는 것입니다.
undefined : 선언만 되어지고 특정 값이 할당되지 않는 경우 javascript 엔진에 의해 자동으로 할당되는 값입니다. 특별히 할당된 값이 없는 경우 일반적인 언어처럼 null 이 아니고 undefiend 가 할당 됩니다.
또한 객체가 소유하지 않은 프로퍼티에 접근하게 될 경우에도 undefined 가 반환됩니다.
undeclared : undeclared 변수란 선언하지 않고도 사용 가능한 변수 입니다.
예를 들어 testVar = ‘hello world’;
와 같이 var keyword를 사용하지 않고 선언된 변수 입니다.
scope 개념에서 보았을 때 유효범위를 지정하지 않았기 때문에 글로벌 변수로 생성 됩니다.
null과 undefiend 비교 : javascript 엔진은 절대로 변수에 null을 할당하지 않습니다.
null은 프로그래머가 할당하는 것이며 변수의 참조링크를 끊기 위해 사용합니다.
반면 undefined는 javascript 엔진에 의해 자동으로 할당됩니다.
클로져(Closure)는 무엇이며, 어떻게/왜 사용하는지 설명해주세요.
클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킵니다.
클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용됩니다.
클로저란 내부함수가 외부함수의 지역변수에 접근 할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 의미합니다.
- javascript
1 | function myName() { |
익명함수(anonymous functions)는 주로 어떤 상황에서 사용하나요?
익명함수의 사용은 함수 선언이 아닌 함수표현식을 이용하는 방법입니다.
이는 곧 람다함수(함수 리터럴을 변수에 할당하는 방식)와 즉시실행구문을 만들어 낼수 있다는 의미이며,
이처럼 즉시실행 구문을 사용하면 javascript 가 유효범위를 선언 할 수 없다고 해도 강제적으로 private 변수를 만들어 내는 것이 가능 합니다.
- javascript
1 | // i 라는 변수는 실행 시점에서만 사용되면 외부에서 접근 할수 없다. |
즉 익명함수는 동적으로 할당되는 유효범위를 가지기 때문에 javascript 내에서 강제적인 유효범위 설정을 하는 경우 사용되게 됩니다.
당신의 코드를 어떻게 구성하는지? (모듈 패턴, 전통적 상속)
모듈 패턴으로 코드를 작성합니다. ES6문법에 따라 export, import를 사용하여 모듈화 합니다.
호스트 객체(Host Objects)와 네이티브 객체(Native Objects)의 차이점은 무엇인가요?
네이티브 객체(Native Object) : 네이티브 객체는 브라우저 혹은 구동 엔진에 내장되어 있는 객체를 말합니다.
네이티브 객체는 built-in 객체와 달리 자바스크립트 엔진이 구성하고 있는 기본객체라고 하기보단 브라우저 혹은 사용되는 자바스크립트 엔진에 영향을 많이 받게 됩니다.
B.O.M 이라는 브라우저객체 모델과 D.O.M 이라는 문서 객체 모델이 네이티브 객체에 포함되는데 이 객체의 사용성이 이를 구현한 구동엔진에 따라 각기 다르게 존재하는 경우가 있기 때문에 크로스 브라우징에 문제를 발생시키기도 합니다.
호스트 객체(Host Object) : 호스트 객체는 빌트인 객체와 네이티브객체에 포함되지 않은 사용자에 의해 생성된 객체를 의미합니다.
자바스크립트 엔진은 빌트인 객체와 네이티브 객체를 구성한 이후 호스트객체를 해석하게 됩니다.
다음 코드의 차이점은 무엇인가요?
- function Person(){}
- var person = Person()
- var person = new Person()
1. function Person() {}
함수를 선언하지만 실행하지는 않습니다.
대개 중괄호 사이에 코드가 있습니다.
2. var person = Person()
변수 (person)을 선언하고, 함수 (person)를 호출하며, person의 값을 함수의 반환 값으로 설정합니다.
3. var person = new Person ()
Person 함수를 기반으로 객체의 새 인스턴스를 만듭니다. 따라서 변수 (person)는 이제 문자열이나 숫자가 아닌 Object입니다.
.call과 .apply의 차이점은 무엇인가요?
둘 다 Context를 조정하기 위한 함수입니다.
함수 안에서 this 를 사용할 때 대체 this가 어디냐를 조정하는 것인데, 기본적으로 브라우저에서는 this는 window 객체를 가리킵니다.
Object의 메서드는 해당 객체를 가리키게 되고, 객체의 메서드만 따로 변수로 참조하는 경우엔 이 Context가 window로 되어 버립니다.
따라서 Context를 조정해야 할 때 call과 apply를 사용합니다.
이 둘의 차이점은 paramater에 있습니다. call의 경우 전달인자를 하나하나씩 보내지만 .apply의경우 배열의 형태로 전달합니다.
- javascript
1 | //.call Example |
Function.prototype.bind을 설명하세요.
bind() 메소드는 호출될 때 그 this 키워드를 제공된 값으로 설정하고 새로운 함수가 호출될 때 제공되는 주어진 순서의 선행 인수가 있는 새로운 함수를 생성합니다.
document.write()는 언제 사용하나요?
디버깅이나 화면에 출력해야하는 상황에 사용합니다.
UA 문자열을 이용하여 기능 검출(feature detection)과 기능 추론(feature inference)의 차이점을 설명하세요.
기능 검출은 브라우저에게 기능 X가 존재하는지 묻습니다.
예를 들어 웹 어플리케이션에서 localStorage를 사용한다고 가정하였을때
if('localStorage' in window)
위와 같이 localStorage가 존재하는지 묻습니다.
반면에 기능 추론은 기능 ‘localStorage’가 존재한다면 ‘sessionStorage’도 존재한다고 추론해 내는 것입니다.
1 | if('localStorage' in window){ |
이 방식은 오래된 방식이고 UA String은 단순히 문자열일 뿐이기 때문에 기능 검증을 위한 방법으로 사용하지 않는 것이 좋습니다.
AJAX에 관해 가능한 한 자세히 설명하세요.
AJAX란 비동기 자바스크립트와 XML (Asynchronous JavaScript And XML)을 말합니다.
간단히 말하면, 서버와 통신하기 위해 XMLHttpRequest 객체를 사용하는 것을 말합니다.
JSON, XML, HTML 그리고 일반 텍스트 형식 등을 포함한 다양한 포맷을 주고 받을 수 있습니다.
AJAX의 강력한 특징은 페이지 전체를 리프레쉬 하지 않고서도 수행 되는 “비동기성”입니다.
이러한 비동기성을 통해 사용자의 Event가 있으면 전체 페이지가 아닌 일부분만을 업데이트 할 수 있게 해줍니다.
대부분의 Morden Front-End Framework은 AJAX를 기반으로한 모듈로 서버와 통신합니다.
AJAX를 사용했을 때의 장단점에 대해 설명해주세요.
장점
- 웹페이지 전체를 다시 로딩하지 않아도 됩니다. 원하는 데이터만 서버로부터 가져와 바인딩합니다.
- 서버처리를 기다리지 않고 비동기 요청이 가능합니다.
- 수신하는 데이터의 양을 줄일 수 있고, 클라이언트에게 처리를 위임 할 수 있습니다.
단점
- Ajax를 사용할 수 없는 브라우저에 대한 문제가 있습니다.(요즘에는 잘 못 본듯…)
- Http클라이언트의 기능이 한정되어 있습니다.
- 페이지의 이동없는 통신으로 인한 보안상의 문제가 있습니다.
- 지원하는 Charset이 한정되어 있습니다.
- 요청을 남발하면 서버의 부하가 늘어날 수 있습니다.
- 동일 출처 정책(CORS issue)로 인해 다른 도메인과 통신이 불가능합니다.
JSONP가 어떻게 동작 되는지 설명하세요. (그리고 AJAX와 어떻게 다른지 설명하세요.)
JSONP는 AJAX와는 다르게 데이터를 요청하는 것이 아닌 <script>
를 호출하는 방식으로 구현됩니다.
AJAX의 통신 방식은 동일 출처 원칙(Same Origin Policy)에 의해 동일한 도메인에서만 호출이 가능한데,
다른 도메인에서 호출할 경우 이 동일 출처 원칙에 의해 데이터를 가져올 수 없게 되어있습니다.
그러나 <script>
태그의 경우 동일 출처 원칙을 따르지 않아도 되기 때문에 이 원리를 바탕으로 JSONP방식을 사용하는 것입니다.
동작 방식은 데이터를 요청할 페이지에, 데이터를 받아 처리할 콜백 함수를 먼저 준비해놓습니다.
그 후에 <script>
요소를 생성하여, 데이터 요청을 합니다.
데이터 요청을 받은 페이지에서는 콜백 함수를 실행하는 스크립트를 출력합니다.
이 때 callback 함수의 인자에는 요청받은 데이터가 들어가게 됩니다.
여기서 주의 할 점은 JSONP 방식의 경우 GET 메서드만 호출 가능하다는 점이다.
“호이스팅(Hoisting)”에 대해서 설명하세요.
Hoisting이란 사전적 의미로 끌어올려지다
라는 뜻이며 범위(scope)에 따라 변수의 선언과 할당이 분리 되는 것을 의미합니다.
즉 변수가 함수 내에서 선언되었을 경우 함수의 최상위로, 함수 바깥에서 선언되었을 경우 전역 Context의 최상위로 변경됩니다.
호이스팅에서 주의할 점은 호이스트 되었을 때 함수선언은 변수선언을 덮어씁니다.
- javascript
1 | var myName; |
위 예제 처럼 변수와 함수의 이름이 같은경우 함수의 우선순위가 높기 때문에 함수선언이 변수선언을 덮어씁니다.
반면에 아래와 같이 변수에 값이 할당 된 경우 변수선언이 함수선언을 덮어씁니다.
- javascript
1 | var myName = 'sungwooKIM'; |
이벤트 버블링(Event Bubbling)에 대해서 설명하세요.
하위에서 상위 요소로 이벤트를 전파하는 방식을 이벤트 버블링(Event Bubbling)이라고 합니다.
“속성(Attribute)”와 “요소(property)”의 차이가 무엇인가요?
attribute :
Attributes는 HTML 요소의 추가적인 정보를 전달하고 이름=”값” 이렇게 쌍으로서 표현됩니다.
예를 들어 <div class="my-class"></div>
를 보면 class
라는 attribute에 ‘my-class’라는 값이 할당 됩니다.
property :
Property는 attribute에 대한 HTML DOM 트리 내부에서의 표현입니다.
DOM안에서의 표현이기 때문에 위 예제에서 property는 className
이며 값으로 ‘my-class’를 가지게 됩니다.
둘을 비교하였을 때 Attributes는 HTML 텍스트 문서에 있는 것이고 properties는 HTML DOM 트리에 있는 것입니다. attribute는 변하지 않고 초기 (default)값을 전달한다는 것은 의미하며 반면에 HTML properties는 변할 수 있습니다. 예를 들어 사용자가 체크박스를 체크했거나 input 박스에 텍스트를 넣었거나 JavaScript로 값을 변경하면 property의 값은 변하게 됩니다.
내장된 JavaScript 객체를 확장하는 것이 좋지 않은 이유는 무엇인가요?
내장객체를 확장하는 방식은 객체의 prototype에 속성 또는 함수를 추가하는 것을 의미합니다. 이는 겉으로는 편리해 보일지 몰라도 실제로는 위험한 방법입니다.
만약 Array 내장 객체를 확장 한 후, Array.prototype을 확장하는 라이브러리를 사용하였을 때 예기치 못한 결과를 초래 할 수도 있습니다.
document load event와 DOMContentLoaded event의 차이점은 무엇인가요?
DOMContentLoaded event :
HTML 이 모두 로드되고, DOM 트리가 완성되었지만, 외부 리소스(img etc) 가 아직 로드되어지지 않았을 때 DOM이 준비 상태이기 때문에, DOM 노드를 제어할 수 있습니다.
document load event :
브라우저에 모든 리소스(img, style, script, etc) 가 로드되었을 때
모든 리소스가 로드된 시점이기에, image 사이즈와 같은 것들을 얻을 수 있습니다.
1 | DOMContentLoaded == window.onDomReady() |
==와 ===의 차이점은 무엇인가요?
==
은 비교 구문에서 두 변수의 값만을 비교합니다. javascript의 변수는 타 언어에 비해 유연해서 1 == '1'
도 true를 반환합니다.
이러한 유연함 때문에 값과 더불어 타입까지 비교할때 ===
를 사용합니다.
JavaScript의 “동일출처정책(the same-origin policy)”에 대해서 설명하세요.
same origin policy는 한 출처(origin 또는 도메인)에서 로드된 문서나 다른 출처 자원과 상호작용하지 못하도록 제약합니다. 이 정책으로 CORS 크로스 도메인 이슈 (No ‘Access-Control-Allow-Origin’ header is present on the requested resource) 발생하게되는데, 주로 프론트 코드에서 AJAX요청시 자주 발생합니다. BackEnd와 FrontEnd의 출처(Domain)이 다르기 때문입니다.
여러가지 해결 방법이 있지만 대표적으로는 Front에서 JSONP를 사용하거나 BackEnd에서 모든 요청을 허용하도록 설정 한 후 인증을 거쳐 사용하도록 하는 방법이 있습니다.
다음 코드를 동작하게 만드세요.
- duplicate([1,2,3,4,5]); // [1,2,3,4,5,1,2,3,4,5]
- javascript
1 | function duplicate(arr) { |
삼항식(Ternary statement)을 사용하는 이유는 무엇이고, 그것을 표현하기 위한 연산자 단어는 무엇인가요?
if의 축약형으로 사용하며 코드가 직관적이고 간결해지는 이점이 있습니다.
주로 아래와 같이 사용합니다.
condition ? expr1 : expr2
use strict;
은 무엇이고, 사용했을 때 장단점에 관해서 설명해주세요.
use strict;
은 ECMAScript 버전 5에서 새로 추가되었습니다.
이전 버전의 JavaScript에서는 무시되며 strict mode를 사용하기위해 표시합니다.
strict mode에서는 선언되지 않은 변수를 사용할 수 없습니다.
예를 들어 아래의 예제에서는 에러가 발생합니다.
- javascript
1 | ; |
100번 반복되는 반복문이 있습니다. 3의 배수일 때는 fizz, 5의 배수일 때는 buzz, 3과 5의 공배수일 때는 fizzbuzz가 출력되는 코드를 작성해보세요.
- javascript
1 | function fizzbuzz() { |
전역 scope를 사용했을 때 장단점에 관해 설명해주세요.
전역 scope를 사용하였을 때 변수의 scope를 생각하지 않고 빠르게 코딩할 수 있는 장점이 있지만 이렇게 사용하지 않는 편이 좋습니다.
전역 scope를 남발할 경우 변수 또는 함수와 네임스페이스로 인한 충돌이 발생할 수 있기 때문에 로컬 scope을 사용하여 모듈화하고 의존성을 최소화 해야 합니다.
때때로 load event를 사용하는 이유에 관해 설명해주세요. 또 단점이 있다면 대안에 대해서도 설명해주세요.
- load event는 외부 리소스까지 모두 로드한 시점에 동작 할 코드가 들어갑니다.
예를 들면 로드한 이미지의 사이즈를 가져오는 경우가 있습니다. - load event의 단점은 한번만 실행되기 때문에 다른 JS라이브러리에서 load event가 구현되어있을 경우 코드가 복잡해 질 수 있다는 점 과
모든 리소스를 다운 받은 후 동작하기 때문에 사용자 입장에서 느릴 수 있다는 점 입니다.
이에 대한 대안으로 jquery의 ready함수나 FE Framework의 라이프사이클 훅(lifecycle hook)을 활용 할 수 있습니다.
SPA에서 SEO에 유리하도록 만들기 위한 방법에 대해 설명해주세요.
최근 SPA로 제작되는 웹 어플리케이션이 많아짐에 따라 SEO 최적화가 화두가 되었습니다.
검색엔진마다 다르겠지만 구글을 기준으로 SEO를 최적화 할 경우 각각 구현한 SPA마다 최적화의 방식이 다릅니다.
Angular 4는 Angular Universal을 사용하여 서버에서 HTML을 미리 렌더링하여 클라이언트에 전송합니다.
서버 측 렌더링을 통해 검색봇이 페이지를 크롤링 할 때 구식 HTML이 수신되도록 처리합니다.
Promise를 사용해 본 경험이 있나요?
네, 자주 사용합니다.
최근에는 Promise와 더불어 async/await를 사용합니다.
Promise가 콜백 대비 장/단점은 무엇인지 설명해주세요.
장점
- 콜백 헬을 벗어날 수 있다는점.
- 체이닝을 통한 연속적인 코드 작성 가능
- Promise.all과 같은 병렬 비동기 코드 작성 가능
- 라이브러리를 추가(bluebird)하여 .spread(), .finally()와 같은 코드도 사용할 수 있다는 점
단점
- ES2015를 지원하지 않는 이전 브라우저에서 이를 사용하기 위해서는 polyfill을 로드해야 합니다.
JavaScript의 작동방식의 장단점에 관해 설명해주세요.
장점
- 페이지 리로드 없이 바로 화면에 적용이 가능합니다. 이로 인해 사용자에게 더 빠른 속도감을 제공 할 수 있습니다.
- 싱글 스레드/비동기로 동작하기 때문에 페이지 로드를 기다리지 않아도 됩니다.
단점
- 싱글스레드/비동기로 동작하기 때문에 완료시점에 대한 Timeing을 catch하기 어렵습니다.
(그래서 Promise나 RxJS, async/await를 주로 사용합니다)
JavaScript를 디버깅할 때 사용하는 도구가 있으면 설명해주세요.
- Chrome DevTools
- Safari Developer Mode
- vue-devtools
- WebStorm Debugger
- console.log()
- window.alert() –> debugger를 사용하지 못할 때, console.log()를 사용하지 못할때 사용합니다.
객체 안의 속성과 배열의 아이템을 순회할 때 사용하는 문법에 관해 설명해주세요.
오브젝트의 경우:
- for 반복문 - for (var property in obj) { console.log(property); }. 그러나 이것은 상속된 속성도 반복되며, 사용하기전에 obj.hasOwnProperty(property) 체크를 추가해야 합니다.
- Object.keys() - Object.keys(obj).forEach(function (property) { … }). Object.keys ()는 전달하는 객체의 열거 가능한 모든 속성을 나열하는 정적 메서드입니다.
- Object.getOwnPropertyNames() - Object.getOwnPropertyNames(obj).forEach(function (property) { … }). Object.getOwnPropertyNames()는 전달하는 객체의 열거 가능한 속성과 열거되지 않는 모든 속성을 나열하는 정적 메서드입니다.
배열의 경우:
- for 반복문 - for (var i = 0; i < arr.length; i++). 여기에 있는 일반적인 함정은 ‘var’이 함수 범위에 있고 블록 범위가 아니며 대부분 블록 범위의 반복자 변수를 원할 것이라는 점입니다. ES2015에는 블록 범위가 있는 let을 도입하고 대신 사용할 것을 권장합니다. 그래서 다음과 같이 됩니다. for (let i = 0; i < arr.length; i++).
- forEach - arr.forEach(function (el, index) { … }). 필요한 모든 것이 배열 요소라면 index를 사용할 필요가 없기 때문에 이 구조가 더 편리 할 수 있습니다. 또한 every과 some 메서드를 이용하여 반복을 일찍 끝낼 수 있습니다.
최근에는 주로 lodash 라이브러리를 사용합니다. 위 케이스의 대부분의 반복을 제공하며 속도 또한 빠릅니다.
참고 : 프론트엔드 인터뷰 핸드북mutable object와 immutable object에 관해 설명해주세요.
Javascript의 기본 자료형(primitive data type)은 변경 불가능한 값(immutable value) 입니다.
- Boolean
- null
- undefined
- Number
- String
- Symbol (New in ECMAScript 6)
기본 자료형 이외의 모든 값은 객체(Object) 타입이며 객체 타입은 변경 가능한 값(mutable value) 입니다. 즉, 객체는 새로운 값을 다시 만들 필요없이 직접 변경이 가능합니다.
C 언어와는 다르게 Javascript의 문자열은 변경 불가능한 값(immutable value) 입니다. 이런 값을 “primitive values” 라 합니다.
(변경이 불가능하다는 뜻은 메모리 영역에서의 변경이 불가능하다는 의미이며 재할당은 가능합니다)
동기방식과 비동기 방식 함수의 차이에 관해서 설명해주세요.
동기방식은 현재의 명령문이 컴파일되고 에러없이 실행되기 전까지 다음 명령문을 실행하지 않습니다.
반면 비동기 방식은 현재 명령문의 완료와 상관 없이 다음 명령문을 실행합니다.
비동기 방식은 일반적으로 명령문이 완료되고 호출스택이 비어있을 때 콜백을 호출합니다.
event loop이란 무엇인가요?
- call stack과 task queue에 관해 설명해주세요.
브라우저는 단일 쓰레드(single-thread)에서 이벤트 드리븐(event-driven) 방식으로 동작합니다.
단일 쓰레드는 쓰레드가 하나뿐이라는 의미이며 이말은 곧 하나의 작업(task)만을 처리할 수 있다는 것을 의미합니다.
하지만 실제로 동작하는 웹 애플리케이션은 많은 task가 동시에 처리되는 것처럼 느껴집니다.
이처럼 자바스크립트의 동시성(Concurrency)을 지원하는 것이 바로 이벤트 루프(Event Loop)입니다.
브라우저의 환경을 그림으로 표현하면 아래와 같습니다.
구글의 V8을 비롯한 대부분의 자바스크립트 엔진은 크게 2개의 영역으로 나뉩니다.
Call Stack(호출 스택)
작업이 요청되면(함수가 호출되면) 요청된 작업은 순차적으로 Call Stack에 쌓이게 되고 순차적으로 실행됩니다. 자바스크립트는 단 하나의 Call Stack을 사용하기 때문에 해당 task가 종료하기 전까지는 다른 어떤 task도 수행될 수 없습니다.
Heap
동적으로 생성된 객체 인스턴스가 할당되는 영역입니다.
이와 같이 자바스크립트 엔진은 단순히 작업이 요청되면 Call Stack을 사용하여 요청된 작업을 순차적으로 실행할 뿐입니다. 앞에서 언급한 동시성(Concurrency)을 지원하기 위해 필요한 비동기 요청(이벤트를 포함) 처리는 자바스크립트 엔진을 구동하는 환경 즉 브라우저(또는 Node.js)가 담당합니다.
Event Queue(Task Queue)
비동기 처리 함수의 콜백 함수, 비동기식 이벤트 핸들러, Timer 함수(setTimeout(), setInterval())의 콜백 함수가 보관되는 영역으로 이벤트 루프(Event Loop)에 의해 특정 시점(Call Stack이 비어졌을 때)에 순차적으로 Call Stack으로 이동되어 실행됩니다.
Event Loop(이벤트 루프)
Call Stack 내에서 현재 실행중인 task가 있는지 그리고 Event Queue에 task가 있는지 반복하여 확인합니다. 만약 Call Stack이 비어있다면 Event Queue 내의 task가 Call Stack으로 이동하고 실행됩니다.
function foo() {}와 var foo = function() {}에서 foo 의 차이가 무엇인지 설명해보세요.
전자는 함수선언(Function Declarations)이며 후자는 함수표현(Function Expressions)입니다.
함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않습니다.
함수 선언식은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려집니다.
예를 들어, 아래의 코드를 실행할 때
- javascript
1 | // 실행 전 |
호이스팅에 의해 자바스크립트 해석기는 코드를 아래와 같이 인식합니다.
- javascript
1 | // 실행 시 |
함수 표현식 sumNumbers 에서 var 도 호이스팅이 적용되어 위치가 상단으로 끌어올려졌습니다.
하지만 실제 sumNumbers 에 할당될 function 로직은 호출된 이후에 선언되므로, sumNumbers 는 함수로 인식하지 않고 변수로 인식합니다.
let, var, const의 차이점에 관해서 설명해주세요.
var 키워드를 사용하여 선언된 변수는 해당 변수의 함수 스코프 또는 전역 스코프를 가집니다.
반면에 let과 const 블록 범위입니다. 즉, 가장 가까운 중괄호(function, if-else 블록 또는 for-loop) 내에서만 접근할 수 있습니다.
- javascript
1 | function foo() { |
- javascript
1 | if (true) { |
var는 변수가 올라가도록 허용합니다. 즉, 변수가 선언되기 전에 코드에서 참조 될 수 있습니다. let과 const는 이것을 허락하지 않고 대신 에러를 던집니다.
- javascript
1 | console.log(foo); // undefined |
var을 사용하여 변수를 다시 선언해도 오류는 발생하지 않지만 ‘let’과 ‘const’는 오류를 발생시킵니다.
- javascript
1 | var foo = 'foo'; |
let은 변수의 값을 재할당 할 수 있지만 const는 재할당 할 수 없다는 점이 다릅니다.
- javascript
1 | // 괜찮습니다 |