기술 면접(JS)

유요한·2024년 3월 13일
0

기술면접

목록 보기
20/27
post-thumbnail

자바스크립트란?

타입을 명시할 필요가 없는인터프리터 언어라고 하며 객체 지향과 함수형 모두 가능하기 때문에 객체 기반이라고 부른다. 자바스크립트는 HTML을 동적으로 처리할 때 사용합니다.


변수란?

변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다. 변수 이름을 식별자라고도 한다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말합니다. 값은 메모리 공간에 저장되어 있다. 따라서 식별자는 메모리 공간에 저장되어 있는 어떤 값을 구별해서 식별해 낼 수 있어야 한다. 이를 위해 식별자는 어떤 값이 저장되어 있는 메모리 주소를 기억해야 한다.

변수 이름은 어디에 등록되나?

변수 이름을 비록한 모든 식별자는 실행 컨텍스트에 등록된다. 실행 컨텍스트는 자바스크립트 엔진이 소스 코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. 자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.


호이스팅

변수나 함수의 선언이 어디에 있든 상관없이 다른 코드들 보다 가장 먼저 끌어올려져서 실행되는 특징


가비지 콜렉터

애플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리를 해제하는 기능을 말합니다. 더 이상 사용되지 않는 메모리는 어떤 식별자도 참조하지 않는 메모리 공간을 의미합니다. 자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어로서 가비지 콜렉터를 통해 메모리 누수를 방지한다.


언매니지드 언어 & 매니지드 언어

프로그래밍 언어는 메모리 관리 방식에 따라 언매니지드 언어매니지드 언어로 분류할 수 있다. 자바스크립트 같은 매니지드 언어는 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당하고 개발자의 직접적인 메모리 제어를 허용하지 않는다. 즉, 개발자가 명시적으로 메모리를 할당하고 해제할 수 없다.


DOM

  • HTML코드라는 설계도가 브라우저라는 공장으로 가고 공장에서는 이 설계도를 해석하는 과정을 거치는데 이것을 파싱이라고 부른다. 이 결과물로 DOM이라는 기계가 만들어진다.

  • HTML 주문서에 작성한 그 전체 구조에 맞춰서 이 제품들이 배치되고, 이것들에 내가 추가적으로 명령을 보내서 속성이나 디자인, 배치 등을 조작할 수 있도록 된 상태 즉, HTML이란 코드로 설계된 웹페이지가 브라우저 안에서 화면에 나타나고 이벤트에 반응하고 값을 입력받는 등 기능들을 수행할 객체들로 실체화된 형태

  • HTML이나 XML문서를 실체로 나타내는 API

  • 문서 객체 모델(DOM, Document Object Model)은 XML이나 HTML 문서에 접근하기 위한 인터페이스 입니다. 이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공합니다.이러한 DOM은 W3C의 표준 객체 모델이며, 다음과 같이 계층 구조로 표현됩니다. 이것은 HTML 요소들의 구조가 트리 형식으로 반영이 되는 것이다. 브라우저가 HTML 코드를 해석해서 요소들을 트리 형태로 구조화해 표현하는 문서(데이터)를 생성한다. 이를 DOM이라 하며 DOM은 이 트리전체를 말하는 것이고 이것을 구성하는 부품들이 Node라고 부른다. 브라우저는 DOM을 통해 화면에 웹 콘텐츠들을 렌더링한다.

DOM의 목적

자바스크립트를 사용해서 이 문서에 대한 스크립트를 작성하는데 목적이 있고 DOM은 자바스크립트를 웹 콘텐츠 추가, 수정, 삭제, 그리고 마우스 클릭, 키보드 치기 등이벤트 처리에 대한 정의할 수 있도록 한 프로그래밍 인터페이스다.


document 객체

  • 웹 페이지 그 자체를 의미한다.

  • 웹페이지에 존재하는 HTML 요소에 접근하고자 할 때에는 반드시 document 객체부터 시작한다.

  • 웹 페이지에 존재하는 모든 HTML 요소에 접근할 수 있도록 하는 js의 내장 객체

DOM selector

다양한 html 요소 중 내가 선택하고자 하는 요소에 접근할 수 있도록 하는 document 객체의 함수

DOM에 접근하기 위해서는 반드시 document라는 객체로 시작한다.


동기와 비동기 차이

동기는 요청을 보낸 후 결과를 받아야만 다음 동작이 이루어는 것이다. 비동기는 효율성을 위해 요청을 보낸 후 결과를 받지 않아도 다음 동작이 이루어지는 것이다. 자바스크립트는 멀티 스레드가 아닌 싱글 스레드이기 때문에 한번에 한가지 일만 처리할 수 있다.

따라서, 시간이 소요되는 작업을 할 때는 해당 작업을 진행한 후 실행을 해야 하는데 이러한 작업들을 비동기를 통해 효율적으로 운용할 수 있습니다. 비동기는 자바스크립트가 실행될 때 이벤트 루프를 통해 실행되며 비동기 처리가 끝난 후 실행되어야 할 함수들은 이벤트큐(태스크 큐)에 저장해두었다가 비동기가 끝난 후 차례대로 실행한다. 즉, 이벤트 루프에서는 이벤트 발생 시 호출되는 콜백 함수들을 테스크 큐에 전달하고, 테스트 큐에 담겨 있는 콜백함수들을 콜스택에 넘겨준다.

이벤트큐

이벤트 큐에서는 비동기 작업들이 실행된 후 호출되는 콜백함수들을 기다리는 공간이다. 이벤트 루프가 정해진 순서대로 줄을 서 있으며, FIFO선입선출이다. 하나의 큐로 이루어져 있지 않으며 여러개의 큐로 이루어져 있다.


콜백지옥

콜백 함수를 중첩하여 사용할 때 코드가 복잡해지고 가독성이 저하되는 현상


Promise

비동기 통신 처리를 위하여 악명 높은 콜백지옥을 탈출시켰다는 점에서 굉장히 높은 평가를 받고 있다.

promise는 대기상태(pending), 성공상태(resolve), 실패상태(reject)

promise를 선언하는 순간 대기 상태에서 실행되어 있지만 나중에 어떠한 조건을 만족했을 때 결과 값을 받는 객체

  • promise는 항상 promise 타입의 객체를 return(반환)
  • 객체 안의 then(성공) catch(실패)

단, promise 또한 callback 함수에 기반을 두고 있다는 점에서 한계가 있다. 로직이 또 길어진다. 따라서 자바스크립트에서는 이러한 promise의 한계점을 해결하기 위해서 async await를 도입

       <script>
            // 비동기 흐름 뒤에 써야만 하는 로직
            // 내부 함수는 중요하지 않다.
            const callback = (number) => {
                setTimeout(() => {
                    number = number + 1;
                    console.log(number); // 7
                }, 1000);
                return number;
            };

            let a = 5;
            // pr이라는 상수를 만들고 Promise라는 객체를 담아주었고
            // 성공했을때와 실패했을 때 이 두가지 값을 리턴받는다.
            const pr = new Promise((resolve, reject) => {
                setTimeout(() => {
                    a = a + 1;
                    // 1. resolve는 성공상태이고 reject는 실패상태이다.
                    // 만약에 if문을 setTimeout 밖에 있다면 실패가 뜬다.
                    // 그 이유는 setTimeout은 비동기 이기 때문에
                    // 따로 빼서 이벤트루프로 보내주고 이벤트 큐에 넣어주는데
                    // 큐는 FIFO(선입선출)이다. 그렇기때문에 따로 있으면
                    // if문이 먼저 실행이 되서 실패한다.
                    if (a === 6) {
                        resolve(a); // 6
                    } else {
                        reject("실패");
                    }
                }, 1000);
            });

            // 위에 있는 Promise 값을 then과 catch를 통해서 받아올 수 있다.
            pr.then((result) => {
                console.log(result); // 6
                return callback(result); // 7
                // reject(실패)를 받아온다.
            }).catch((err) => {
                console.error(err); // 실패
            });
        </script>

async await

결국에 콜백에 기반을 두고 있는 promise는 then catch의 반복으로 코드가 길어지는 현상이 생긴다는 것은 다를 것이 없다. 따라서 이러한 promise의 한계를 해결하기 위해 등장했다.

  • async
    async가 사용된 함수를 promise형태로 만들어주며 하위에 await이란 객체

  • await
    await 앞의 함수가 실행될 때까지 promise를 잠시 대기 시켜놓습니다.

        <script>

            // await을 활용함으로써
            // 비동기를 동기적 흐름으로 만들어주고
            // 콜백이나 then이 없어도 해당 비동기 함수 실행 후
            // 다음 함수를 실행시킬 수 있다.
            const asynEx = async (number) => {
                try {
                    console.log(number);
                    // await가 위에서 실행하는 비동기를 기다렸다가 아래께 실행한다.
                    // 비동기 → 동기처럼 실행하는 것이다.
                    let result = await callback(number);
                    console.log(result);
                } catch (error) {
                    console.log(err);
                }
            };

            /*
                콘솔값
                5
                6
                7
            */
            let a = 5;
            asynEx(a);
        </script>
   <script>
            // function 앞에 async를 붙여줍니다.
            // promise 객체 앞에 await를 붙여줍니다.
            // async가 붙은 함수는 promise 객체를 반환합니다. 따라서 .then((a) => {})를 이용할 수 있다.
            function delay() {
                return new Promise((resolve) => {
                    setTimeout(() => resolve(), 1000);
                });
            }

            async function getApple() {
                await delay();
                return "apple";
            }
            async function getBanana() {
                await delay();
                return "banana";
            }

            function getFruites() {
                // 리턴값이 promise의 resolve()이므로 then가능
                getApple().then((a) => {
                    getBanana().then((b) => console.log(`${a} and ${b}`));
                });
            }

            getFruites();
        </script>

콜스택

흐름
1. 비어있는 컨텍스트
2. 전역 컨텍스트 생성, 전역 스코프에 변수, 함수가 평가
3. 다른 함수가 실행되면서 함수 컨텍스트가 생성(이때 함수 컨텍스트 평가)
4. 함수 안에서 또 다른 함수 실행
5. 실행이 다 되면 컨텍스트 제거
6. 모든 실행 컨텍스트가 종료되면 컨텍스트 스택에서 제거


this

this의 값은 선언이 아닌 호출에 따라 달라질 수 밖에 없음

this 해당 메서드를 호출한 객체로 바인딩

전역 함수 호출 했을 시 해당 함수의 this는 window가 됩니다. this는 기본적으로는 window지만, 객체나 메서드, bind call, apply, new 일 때 this는 유동적으로 변경됩니다.


전역 실행 컨텍스트

자바스크립트 코드가 실행되면서 먼저 전역 객체가 생성
전역 객체에는 자바스크립트에서 기본적으로 포함되어 있는 빌트인 객체, 함수, 객체를 포함한다. 이러한 전역 객체가 평가되면서 전역 실행 컨텍스트가 생성

전역 실행 컨텍스트 두가지의 프로퍼티를 가지고 있음

  • decleartive Enviroment Recorde

    • let과 const고 선언한 변수를 따로 관리
    • 여기에서 저장된 식별자들은 선언과 초기화가 분리되어 실행
    • 따라서 var로 선언한 변수와 함수선언과는 다르게 초기화전까지는 접근 불가능(참조 에러)
  • Object Enviroment Record
    그 외 영역을 관리(표준 빌트인 객체, 전역 함수, var, ...)


클로저

클로저는 자바스크립트만의 개념은 함수를 일급객체로 사용하는 모든 언어에서 사용되는 특성이고 클로저는 자신의 생성될 때의 환경을 기억하고, 그를 사용하는 함수이다.

일급객체

함수를 선언하고 컴파일 및 런타임(실행) 할 수 있는 언어

profile
발전하기 위한 공부

0개의 댓글