[면접] 자바스크립트

jm4293·2024년 10월 10일
0

컴파일 언어, 스크립트 언어

1. 컴파일 언어

  • 컴파일 언어는 소스 코드를 기계어로 번역하는 과정을 거친다.
  • 컴파일 언어는 소스 코드를 실행하기 전에 컴파일러를 통해 기계어로 번역한다.
  • 컴파일 언어는 실행 속도가 빠르다.
  • 컴파일 언어는 실행 파일을 만들어야 하기 때문에, 실행 파일을 만드는 시간이 필요하다.

2. 스크립트 언어

  • 스크립트 언어는 소스 코드를 실행하는 과정을 거친다.
  • 스크립트 언어는 소스 코드를 실행하기 전에 인터프리터를 통해 기계어로 번역한다.
  • 스크립트 언어는 실행 속도가 느리다.
  • 스크립트 언어는 실행 파일을 만들지 않기 때문에, 실행 파일을 만드는 시간이 필요하지 않다.

Node.JS

1. V8

  • 자바스크립트엔진으로 빌드된 자바스크립트 런타임 환경

2. Single Thread

3. Non-blocking I/O


ECMAScript

1. JavaScript는 ECMAScript 사양을 준수하는 범용 스크립팅 언어

2. JavaScript는 1996년에 만들어졌고, 그 다음에 JavaScript의 표준화를 위해 1997년에 ECMAScript가 만들어졌다.

3. ECMAScript는 JavaScript를 기반으로 하는 동시에, JavaScript 역시 ECMAScript를 기반으로 한다.

JavaScript

1. 데이터 타입

  1. 원시 타입
    1. 숫자
    2. 문자열
    3. boolen
      1. Truthy
      2. Falsy
        • false / undefined / null / 0, -0 / NaN / ''(빈 문자열)
    4. undefined
      • 자바스크립트 엔진이 변수를 초기화하는 데 사용
    5. null
      • 개발자가 의도적으로 변수에 값이 없다는 것을 명시하고 싶을 때 사용
    6. symbol
    7. bigint
  2. 객체 타입
    • 원시 타입 이외 모든 것(함수, 배열 등)

2. 변수

  • 변수 종류
    1. var
      • 중복 선언 허용
      • 재할당 가능
    2. let, const
      • 중복 선언 금지
      1. let
        • 재할당 가능
      2. const
        • 재할당 불가능
  • 변수 생성 단계
    1. 선언(Declaration)
      • 스코프와 변수가 생성
    2. 초기화(Initialization)
      • var는 undefined 할당
      • let, const는 (Temporal Dead Zone)때문에 할당 불가능
    3. 할당(Assignment)
      • 변수에 값을 할당

3. 함수

  1. 함수 선언문
    function add(x, y) {
      return x + y;
    }
  2. 함수 표현식
    var add = function(x, y) {
        return x + y;
    }
  3. new Function()
    var add = new Function('x', 'y', 'return x+y');
  4. 화살표 함수
    var add = (x, y) => x + y;

4. 스코프

  • 식별자(변수)나 함수에 접근 가능한 유효 범위를 의미한다.
  • 특정 변수나 함수를 어느 위치에서 참소할 수 있는 지를 나타내며 만약 스코프에서 벗어난 위치에서 참조할 경우 Reference Error가 발생한다.
  1. 스코프의 종류
    1. 전역 스코프
    2. 지역 스코프
      • 함수 레벨 스코프
        • 함수 코드 블록 내에서만 참조(접근) 가능한 범위를 말한다.
        • var
      • 블록 레벨 스코프
        • 코드 블록 ({}) 내에서만 참조(접근)가능한 범위를 말한다.
        • let, const, if, for, while, try/catch ...
  2. 스코프 방식
    1. 동적 스코프(Dynamic scope)
      • 함수를 어디서 호출했는지에 따라 함수의 상위 스코프를 결정한다.
    2. 정적 스코프(Static scope), 렉시컬 스코프(Lexical scope)
      • 함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정한다.
      • 코드가 작성된 위치에 따라 변수의 유효 범위가 결정된다.
      • JavaScript는 렉시컬 스코프를 따른다.
  3. 스코프 체이닝
    • scope.js

5. 호이스팅

  1. 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다.
  2. 소스코드 실행을 위한 준비 단계인 소스코드의 평가 과정에서 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아내 먼저 실행한다.
  3. 소스코드의 평가 과정이 끝나면 비로소 변수 선언을 포함한 모든 선언문을 제외하고 소스코드 한 줄씩 실행한다
  • 모든 식별자(변수, 함수, 클래스 등)는 호이스팅된다.
  • 변수 호이스팅
    1. var
      • 함수 단위 스코프(function-level scope)
      • 호이스팅 발생
      • 선언 단계와 초기화 단계가 한번에 진행
    2. let, const
      • 블록 단위 스코프(block-level scope)
      • 호이스팅 발생 그러나 변수 선언 이전에 발수 참조 불가능, TDZ(Temporal Dead Zone)
      • 선언 단계와 초기화 단계가 분리되어 진행, 초기화 단계는 코드 런타임일 때 초기화 진행
  • 함수 호이스팅
    • 함수 선언문은 함수 객체로 할당하여 호출 가능
    • 함수 표현식은 변수 호이스팅으로 발생
  • 클래스 호이스팅
    • 호이스팅 발생 그러나 변수의 let, const와 같이 TDZ가 존재하여 런타임 이전에 실행 불가능

6. this

  • 객체 자신의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이다.
  • this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
  • this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
  1. 일반 함수 호출
    • 기본적으로 this에는 전역 객체가 바인딩
    • 일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수) 내부의 this에는 전역 객체에 바인딩
    • this_1.js
  2. 메서드 호출
    • 매서드 내부의 this는 메서드를 호출한 객체에 바인딩
    • this_2.js
  3. 생성자 함수 호출
    • 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스 바인딩
    • this_3.js
  4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출

7. 프로토타입(prototype)

  • 자바스크립트는 프로토타입 객체지향 프로그래밍
  • 자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불피요한 중복을 제거한다.
  1. 프로토타입이 아닌 인스턴스 생성일 때

    • 동일한 메서드가 중복으로 생성되는 현상
    function Circle(radius) {
      this.radius = radius;
      this.getArea = function () {
        return Math.PI * this.radius ** 2; 
      }
    } 
    
    const circle1 = new Circle(1);
    const circle2 = new Circle(2);
    
    console.log(circle1.getArea === circle2.getArea); //false 

  2. 프로토타입을 사용한 인스턴스 생성일 때

    • 프로토타입으로 동일한 메서드 중복 방지
    function Circle(radius) {
      this.radius = radius;
    }
     
    Circle.prototype.getArea = function() {
      return Math.PI * this.radius ** 2;
    };
     
    const circle1 = new Circle(1);
    const circle2 = new Circle(2);
     
    console.log(circle1.getArea === circle2.getArea); //true

8. 프로토타입 체이닝

9. 생성자 함수

  • ES6 이전에는 자바스크립트에 클래스 문법이 없었고 객체 지향 프로그래밍을 구현하려면 생성자 함수와 프로토타입을 사용해야 했다.
  • 생성자 함수는 프로토타입을 직접 사용해 메서드를 정의하기 때문에, 클래스처럼 extends나 super 같은 키워드를 사용할 수는 없으나 객체 생성 시 메모리를 효율적으로 관리할 수 있습니다.
  1. 함수 정의: 일반 함수처럼 정의하나 관례적으로 첫 글자를 대문자로 작성한다.
  2. this 키워드: 생성자 함수 내에서 this 키워드는 새로 생성될 객체를 참조한다.
  3. 속성 및 메서드 추가: this를 사용하여 객체의 속성과 메서드를 정의한다.
  4. new 키워드 사용: 생성자 함수를 호출할 때는 항상 new 키워드를 사용해야 합니다. 그렇지 않으면 this는 전역 객체를 가리킨다.
// 생성자 함수 정의
function Person(name, age) {
    this.name = name; // 속성
    this.age = age;   // 속성

    // 메서드 추가
    this.sayHello = function() {
        console.log(`이름: ${this.name}, 나이: ${this.age}`);
    };
}

// 생성자 함수 사용
const person1 = new Person('가', 30);
const person2 = new Person('나', 40);

// 메서드 호출
person1.sayHello(); // 이름: 가, 나이: 30
person2.sayHello(); // 이름: 나, 나이: 40.

10. 클래스

  • ES6(ECMAScript 2015)에서 클래스 문법이 도입되었지만, 사실 이 클래스 문법도 생성자 함수와 프로토타입 기반 상속을 단순화한 문법적 설탕(syntactic sugar)일 뿐, 자바스크립트의 근본적인 동작 방식은 여전히 프로토타입 기반이다.
  • constructor 메서드를 사용해 객체를 초기화하고, extends로 상속을 구현.
  • 사실상 생성자 함수 위에 얹어진 문법적 설탕으로, 클래스도 내부적으로는 생성자 함수처럼 동작함.
  1. 프로퍼티, 메소드
  2. constructor, super, extent
  3. public, private, protect, static

11. 생성자 함수와 클래스 차이

  • 클래스 문법을 도입하기 전에는 객체를 생성하고 상속을 구현하기 위해 생성자 함수와 프로토타입을 사용해야 했다.
  • 클래스는 이러한 생성자 함수의 복잡성을 숨기고, 개발자에게 좀 더 직관적이고 익숙한 방식으로 객체를 생성하는 방법을 제공한다.

12. 실행 컨텍스트

  • 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.
  • 실행 컨텍스트는 식별자(변수, 함수, 클래스 드으이 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 매커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
  • 식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다.
  • JavaScript는 함수가 실행될 때마다 메모리 상에 실행 컨텍스트를 생성합니다.
var x= 1;
const y = 2;

function foo (a) {
  var x = 3;
  const y = 4;

  function bar(b) {
    const z = 5;
    console.log(a + b + x + y + z);
  }
  bar(10);
}

foo(20);

13. 클로저

  • 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 경우 중첩 함수를 클로저라고 한다.
  • 외부 함수보다 더 오래 생존한 중첩 함수는 외부 함수의 생존 여부(실행 컨텍스트의 생존 여부)와 상관없이 자신이 정의된 위치에 의해 결정된 상위 스코르픞 기억한다.
  • 중첩 함수 inner의 내부에서는 상위 스코프를 참조할 수 있으므로 상위 스코프의 식별자를 참조할 수 있고 식별자의 값을 변경할 수도 있다.
const x = 10;

function outer() {
  const x = 20;

  const inner = function () {
    console.log(x);
  };

  return inner;
}

const innerFunc = outer();
innerFunc(); // 20

  • 클로저 활용
    1. 상태를 안전하게 변경하고 유지하기 위해 사용
      • 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용

14. 비동기 프로그래밍

  • Ajax
  • API
    • API(Application Programming Interface)
    • 애플리케이션이 어떤 프로그램이 제공하는 기능을 사용할 수 있게 만든 매개체
  • REST API
    • REST(Representational State Transfer)
    • URI로 자원을 표현하는 데에 집중하고, 자원의 상태(행위)에 대한 정의는 HTTP METHOD로 하는 것이 REST한 API를 설계하는 중심 규칙이다.
    • URI로 자원(리소스)을 표현해야 한다.
    • 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현된다.

15. 프로미스

  • callback hell
    // callback hell
    getData (function (x) {
      getMoreData (x, function (y) {
        getMoreData (y, function (z) {
          getMoreData (z, function (z) {
          	...
        	});
        });
      });
    });
  • Promise
    1. Pending(대기)
      • 처리가 완료되지 않은 상태
    2. Fulfilled(이행)
      • 성공적으로 처리가 완료된 상태
    3. Rejected(거부)
      • 처리가 실패로 끝난 상태
    4. Promise Handler
      1. then
        • Promise 상태가 Fulfilled로 변경되었을 때 실행할 콜백 함수
      2. catch
        • Promise 상태가 Rejected로 변경되었을 때 실행할 콜백 함수
      3. finally
        • Promise 상태 변경에 상관없이 무조건 실행할 콜백 함수
    5. Promise 체이닝

16. async, await

  1. Promise 체이닝에 따른 Promise hell에 따른 로직을 간결화
// Promise hell
fetch('https://example.com/api')
  .then(response => response.json())
  .then(data => fetch(`https://example.com/api/${data.id}`))
  .then(response => response.json())
  .then(data => fetch(`https://example.com/api/${data.id}/details`))
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));
profile
무언가 만드는 것을 좋아합니다

0개의 댓글

관련 채용 정보