20230330 JavaScript 면접 스터디

HYEON17·2023년 3월 28일

TIL

목록 보기
12/17
post-thumbnail

1. 코드를 어떻게 구성하나요? (모듈 패턴, 고전적인 상속?)

모듈패턴을 쓰는 이유와 특징

자바스크립트는 private 등의 접근 제한자가 없기때문에 클로저를 모듈패턴을 활용하여 이러한 특징들을 흉내내는 것

캡슐화

캡슐화, 즉 정보은닉을 구현하기 위해서 모듈패턴을 사용합니다.
따라서 이에 따른 오류로부터 보다 안전하게 값을 보호할 수 있습니다. 클로저를 통해 불필요한 전역 변수 사용을 줄이고, 스코프를 이용해 값을 보다 안전하게 다룰 수 있습니다.
또한 모든 관련 코드를 단일 논리 블록에 캡슐화할 수 있으므로 유지 관리가 더 쉬워집니다.

전역변수의 억제

전역 변수가 좋지 않은 이유는, 전역 변수는 다른 함수 혹은 로직 등에 의해 의도되지 않은 변경을 초래하는 side effect때문인데 side effect를 최소화하면, 의도되지 않은 변경을 줄일 수 있습니다.
특정 속성과 기능을 공개로 노출하고 개체 자체 내에서 속성과 기능의 범위를 제한하여 private로 만들 수도 있습니다.
그렇기 때문에 해당 변수는 함수 범위 외부에서 액세스할 수 없습니다. 이를 통해서 전역 스코프의 변수들과 이름이 충돌하는 문제를 줄일 수 있습니다.

재사용성

단일 코드 단위를 전체 애플리케이션에서 재사용할 수 있습니다. 모듈로 묶인 기능은 재사용할 수 있으며 여러 지점에서 동일한 기능을 정의할 필요가 없습니다.

예제

var Counter = (function () { //즉시실행함수로 감싼다
  // private 변수
  var num = 0;

  // 클로저
  //외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환한다.
    return {
    increase() {
      return ++num;
    },
    decrease() {
      return --num;
    }
  };
}());

// private 변수는 외부로 노출되지 않는다.
console.log(Counter.num); // undefined

console.log(Counter.increase()); // 1
console.log(Counter.increase()); // 2
console.log(Counter.decrease()); // 1
console.log(Counter.decrease()); // 0

Counter는 값으로 담고 있는 프로퍼티들을 담은 객체를 반환하고 있습니다. Counter의 스코프 밖에서 바라볼 때 Counter의 그 어떠한 프로퍼티에도 접근을 할 수 없습니다.

즉시실행함수는 한 번만 실행되므로 Counter가 호출될 때마다 num 변수가 초기화될 일은 없습니다.

즉시실행함수가 반환한 클로저는 Counter 변수에 할당되어 호출됩니다.

이 때 이 클로저는 자신이 정의된 위치에 의해 결정된 상위 스코프인 즉시실행 함수의 렉시컬 스코프를 기억하고 있어서 카운트 상태를 유지하기 위해 변수 num을 참조하고 변경할 수 있습니다.

결국 num은 클로저로 인해서 외부에서 접근할 수 없고 메서드들을 통해서 접근해야만 합니다.

2. 호스트 객체와 내장 객체의 차이점은 무엇인가요?

내장 객체

내장 객체는 ECMAScript 사양에 정의된 JavaScript 언어의 일부인 객체(예: String, Math, RegExp, Object, Function 등)

호스트 객체

브라우저 환경에서 제공하는 window, XmlHttpRequest, HTMLElement 등의 DOM 노드 객체와 같이 호스트 환경에 정의된 객체
브라우저에서 동작하는 환경의 호스트 객체는 전역 객체인 window, BOM(Browser Object Model)과 DOM(Document Object Model) 및 XMLHttpRequest 객체 등을 제공

  • window
  • document
  • location
  • XMLHttpRequest
  • querySelectorAll ...

3. function Person(){}var person = Person()var person = new Person()의 차이점은 무엇인가요?

function Person(){}

function Person(){}은 정상적인 함수 선언

var person = Person()

var person = Person()은 생성자가 아니며 Person을 함수로 호출

  • 함수를 생성자로 사용하려는 경우에 이렇게 호출하는 것은 일반적인 실수입니다. 일반적으로 생성자는 아무것도 반환하지 않으므로 일반 함수처럼 생성자를 호출하면 undefined가 반환되고 지정된 변수에 할당

var person = new Person()

Person.prototype을 상속받은 new 연산자를 사용하여 Person 객체의 인스턴스를 생성합니다. 또 다른 방법은 Object.create를 사용하는 것입니다: Object.create(Person.prototype).

function Person(name) {
  this.name = name;
}

var person = Person('John');
console.log(person); // undefined
console.log(person.name); // Uncaught TypeError: Cannot read property 'name' of undefined

var person = new Person('John');
console.log(person); // Person { name: "John" }
console.log(person.name); // "john"

4. .call과 .apply의 차이점은 무엇인가요?

.call과 .apply는 모두 함수를 호출하는데 사용
apply()와 call() 메소드는 콜백 함수의 this를 위해서 사용되기도 한다
call()는 여러 인자를 나열해서 받고 apply()는 여러 인자를 한 배열에 받는다.

function add(a, b) {
  return a + b;
}

console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3

.call

  • call()은 모든 함수에서 사용가능하며, this를 특정 객체로 지정할 수 있다.
  • 호출함수.call(this로지정할대상)을 하면 함수에서 특정 객체를 this로 지정할 수 있다.
const dog = {
  age: 12 
}
function printDogAge() {
  console.log(this.age)
}
printDogAge.call(dog)    // 12

매개변수를 전달하고 싶으면 call은 어떻게 써야할까?

call()의 첫 번째 인자가 this로 지정할 객체라면, 두 번째 인자부터는 함수에 넘겨줄 매개변수를 지정할 수 있다.

const dog = {
  age: 12 
}
function printDogAge(name, location) {
  console.log(this.age, name, location)
}
printDogAge.call(dog, 'mike', 'seoul')    // 12, mike, seoul

.apply

apply()는 두번째 인자에서 배열 형태로 넘긴 것을 각각 하나의 인자로 넘긴다.

const dog = {
  age: 12 
}
function printDogAge(name, location) {
  console.log(this.age, name, location)
}
printDogAge.apply(dog, ['mike', 'seoul'])   // 12, mike, seoul

5. Function.prototype.bind에 대해 설명하세요.

함수에 인자로 전달한 this가 바인딩된 새로운 함수를 리턴한다
즉, .bind.apply, .call 메소드와 같이 함수를 실행하지 않기 때문에 명시적으로 함수를 호출할 필요가 있다

function getThisBinding() {
  return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };

// bind 메서드는 첫 번째 인수로 전달한 thisArg로 this 바인딩이 교체된
// getThisBinding 함수를 새롭게 생성해 반환한다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisArg)()); // {a: 1}

메서드의 this와 메서드 내부의 중첩 함수 또는 콜백 함수의 this가 불일치 하는 문제를 해결하기 위해 유용하게 사용

const person = {
  name: 'Lee',
  foo(callback) {
    // bind 메서드로 callback 함수 내부의 this 바인딩을 전달
    setTimeout(callback.bind(this), 100);
  }
};

person.foo(function () {
  console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});

따라서 bind 메서드를 사용하면 함수의 this 값을 변경하고, 새로운 함수를 생성할 수 있다. 이를 이용하면 함수를 이전에 바인딩된 this 값으로 호출하지 않고도 원하는 객체를 this 값으로 사용할 수 있다.

6. 언제 document.write()를 사용하나요?

JavaScript에서 document.write()는 현재 문서에 새로운 HTML 콘텐츠를 동적으로 삽입하기 위해 사용됩니다. 이 함수는 다음과 같은 경우에 사용될 수 있습니다.

  • 초기 로딩시 HTML 콘텐츠를 삽입해야 할 때
  • 이벤트 처리 루틴에서 HTML 콘텐츠를 삽입해야 할 때
  • 간단한 테스트나 디버깅 목적으로 코드를 작성할 때

document.write() 함수는 자바스크립트가 로딩되는 시점에 실행되므로, 해당 스크립트가 HTML 문서의 로딩 시점 이후에 실행될 경우에는 적용되지 않습니다. 또한, document.write() 함수는 무분별한 사용으로 인해 페이지 구조가 복잡해질 우려가 있으므로, 가능한 경우에는 DOM 조작 메서드를 사용하는 것이 좋습니다.

7. Feature detection, Feature inference, UA String의 차이점은 무엇인가요?

Feature Detection

브라우저가 특정 코드 블록을 지원하는지에 따라 다른 코드를 실행하도록 하여, 일부 브라우저에서 항상 오류 대신 무언가 작동하도록 합니다

Feature inference

Feature detection과 마찬가지로 기능을 확인하지만 다른 함수도 존재한다고 가정하고 사용

UA String

네트워크 프로토콜 피어가 요청하는 소프트웨어 유저 에이전트의 응용 프로그램 유형, 운영 체제, 소프트웨어 공급 업체 또는 소프트웨어 버전을 식별할 수 있도록 해주는 browser-reported String입니다

8. Ajax에 대해 가능한 한 자세히 설명하세요.

자바스크립트를 이용해서 비동기적(Asynchronous)으로 서버와 브라우저가 데이터를 교환할 수 있는 통신 방식
Ajax는 브라우저에서 제공하는 Web API인 XMLHttpRequest 객체를 기반으로 동작

Ajax의 동작방식

  1. 사용자가 웹 페이지의 Ajax 요청을 트리거합니다.
  2. JavaScript는 XMLHttpRequest 객체를 사용하여 서버로 데이터 요청을 보냅니다.
  3. 서버는 요청을 처리하고, 필요한 데이터를 XML, JSON 또는 HTML 형태로 반환합니다.
  4. JavaScript는 반환된 데이터를 처리하여 웹 페이지의 특정 부분을 업데이트합니다.
  5. 이러한 업데이트는 페이지를 다시 로드하지 않고 비동기적으로 수행됩니다.

9. 익명 함수의 일반적인 사용 사례는 무엇인가요?

콜백 함수

콜백 함수는 다른 함수의 인수로 전달되는 함수입니다. 예를 들어, 웹 애플리케이션에서 비동기식 요청을 보낼 때, 요청이 완료될 때 실행할 함수를 콜백 함수로 전달할 수 있습니다. 이때 콜백 함수는 일반적으로 익명 함수로 작성됩니다.

이벤트 핸들러

웹 페이지나 애플리케이션에서 발생하는 이벤트에 대한 처리를 위해 이벤트 핸들러를 사용합니다. 이 때, 익명 함수를 이벤트 핸들러로 사용하여 이벤트가 발생했을 때 실행할 코드를 정의할 수 있습니다.

함수 리턴값으로 사용

함수 내부에서 동적으로 함수를 생성해야 할 때, 익명 함수를 사용할 수 있습니다. 예를 들어, 정렬 알고리즘을 구현하는 함수를 작성할 때, 사용자가 정렬 기준을 지정할 수 있도록 함수를 작성해야 할 경우, 익명 함수를 반환값으로 사용하여 동적으로 사용자 정의 함수를 생성할 수 있습니다.

즉시 실행 함수

즉시 실행 함수는 함수를 정의하자마자 즉시 호출하여 실행하는 함수입니다. 이 함수는 전역 네임스페이스를 오염시키지 않고 지역 변수를 사용할 수 있는 장점이 있으며, 일반적으로 익명 함수로 작성됩니다.

함수 매개변수로 사용

함수 내부에서 익명 함수를 선언하여 다른 함수에 전달하는 경우도 있습니다. 이때, 익명 함수는 함수의 매개변수로 사용됩니다. 이를 통해 함수의 기능을 확장하거나 다른 함수에서 처리해야 할 작업을 구현할 수 있습니다.


질문

질문1

모듈패턴을 쓰는 이유를 설명해주세요

답변

  • 정보은닉을 구현하기 위해
  • 전역변수의 억제
  • 재사용성

질문2

Function.prototype.bind를 사용하는 상황을 설명해주세요

답변

메서드의 this와 메서드 내부의 중첩 함수 또는 콜백 함수의 this가 불일치 하는 문제를 해결하기 위해 유용하게 사용

질문3

Ajax의 동작방식을 설명해주세요

답변

  1. 사용자가 웹 페이지의 Ajax 요청을 트리거합니다.
  2. JavaScript는 XMLHttpRequest 객체를 사용하여 서버로 데이터 요청을 보냅니다.
  3. 서버는 요청을 처리하고, 필요한 데이터를 XML, JSON 또는 HTML 형태로 반환합니다.
  4. JavaScript는 반환된 데이터를 처리하여 웹 페이지의 특정 부분을 업데이트합니다.
  5. 이러한 업데이트는 페이지를 다시 로드하지 않고 비동기적으로 수행됩니다.

질문4

익명 함수의 일반적인 사용 사례를 설명해주세요

답변

  • 콜백 함수
  • 이벤트 핸들러
  • 함수 리턴값으로 사용
  • 즉시 실행 함수
  • 함수 매개변수로 사용
profile
프론트엔드 개발자

0개의 댓글