logo BLOG

70 자바스크립트 인터뷰 질문 - 4부(번역)

70 JavaScript Interview Questions

javascript, interview, translation


출처

70 JavaScript Interview Questions

시작하며

글이 긴 관계로 4부로 나눠서 진행하며 1부는 1-17번 질문, 2부는 18-36번, 3부는 37-54번, 4부는 55-70번 질문으로 구성되어 있다.

Hi Guys Good Day and a Happy New Year 🎆🎆🎆!

이 글은 긴 내용이므로 한두 시환간 동안 나와 함께하시길 바랍니다. 모든 질문에 대한 답변에는 질문 목록으로 돌아가는 화살표 ↑ 링크가 있어서 스크롤 하는 시간을 낭비하지 않아도 됩니다.

질문

55. 암묵적(Implicit) 과 명시적(Explicit) 강제변환(Coercion)의 차이점은 무엇인가?

↑ **암묵적 강제변환(Implicit Coercion)**는 프로그래머가 직접 또는 손으로 하지 않고도 값을 다른 타입으로 변환하는 방법입니다.

아래에 예제가 있다고 가정해봅시다.

console.log(1 + '6'); // string
console.log(false + true); // number
console.log(6 * '2'); // number

첫번째 console.log문은 16을 로그로 기록합니다. 다른 언어에서는 컴파일 타임 에러를 던집니다. 하지만 JavaScript에서 1은 문자열로 변환된 뒤 + 연산자와 연결됩니다. 우리는 아무것도하지 않았지만 JavaScript를 통해 자동으로 변환되었습니다.

두번째 console.log문은 1을 로그로 기록하는데 false는 0이 되고 true는 1이 되는 boolean값이라 결과가 1이 됩니다.

세번째 console.log문은 12를 로그로 기록하고 6 * 2를 곱하기 전에 '2'를 숫자로 변환하므로 결과는 12입니다.

JavaScript Coercion Rules

반면에 **명시적 강제변환(Explicit Coercion)**은 값을 프로그래머가 다른 타입으로 변환하는 명시적(직접) 실행 방법입니다.

console.log(1 + parseInt('6'));

이 예제에서 parseInt 함수를 사용하여 '6'을 number로 변환한 후 +연산자를 써서 1과 6을 더합니다.

56. NaN이란 무엇인가? 값이 NaN인지 확인하는 방법은 무엇인가?

↑ NaN은 “숫자가 아님” 이라는 뜻으로 number를 number가 아닌 값으로 변환이나 수행하는 작업을 통해 NaN 결과 값을 받는데 이러한 JavaScript의 값을 의미합니다.

let a;

console.log(parseInt('abc')); // NaN
console.log(parseInt(null)); // NaN
console.log(parseInt(undefined)); // NaN
console.log(parseInt(++a)); // NaN
console.log(parseInt({} * 10)); // NaN
console.log(parseInt('abc' - 2)); // NaN
console.log(parseInt(0 / 0)); // NaN
console.log(parseInt('10a' * 10)); // NaN

JavaScript는 값이 isNaN값인지 테스트하는 내장 메서드 isNaN이 있습니다. 그렇지만 이 함수에는 이상한 동작이 있습니다.

console.log(isNaN()); //logs true
console.log(isNaN(undefined)); //logs true
console.log(isNaN({})); //logs true
console.log(isNaN(String('a'))); //logs true
console.log(isNaN(() => { })); //logs true

전달하는 값이 NaN이 아니더라도 모든 console.log 문은 true를 리턴합니다.

ES6 또는 ECMAScript 2015에서 Number.isNaN 메서드를 사용하는 것을 권장합니다. 왜냐하면 실제로 이것은 정말 NaN인지 값을 확인합니다. 또는 JavaScript에서 NaN은 그 자체와 같지 않은 유일한 값이기 때문에 이 문제를 확인하는 helper 함수를 만들 수도 있습니다.

function checkIfNaN(value) {
  return value !== value;
}

57. 어떻게 값이 Array인지 확인하는가?

↑ Array 글로벌 객체에서 사용 가능한 Array.isArray 메서드를 사용해서 값이 Array인지 확인할 수 있습니다. 이 메서드는 매개 변수가 Array 인 경우 true를, 그렇지 않으면 false를 리턴합니다.

console.log(Array.isArray(5));  //logs false
console.log(Array.isArray("")); //logs false
console.log(Array.isArray()); //logs false
console.log(Array.isArray(null)); //logs false
console.log(Array.isArray({ length: 5 })); //logs false

console.log(Array.isArray([])); //logs true

개발 환경이 이 메서드를 지원하지 않으면 polyfill 구현해서 사용할 수 있습니다.

function isArray(value){
  return Object.prototype.toString.call(value) === "[object Array]"
}

58. % 또는 모듈로 연산자를 사용하지 않고 number가 짝수인지 확인하는 방법은 무엇인가?

↑ 이 문제에 비트 AND & 연산자를 사용할 수 있습니다. &는 피연산자에서 작동하여 이진수(binary values)로 처리하고 AND 연산을 수행합니다.

function isEven(num) {
  if (num & 1) {
    return false;
  } else {
    return true;
  }
};

이진수에서 0은 000입니다. 이진수에서 1은 001입니다. 이진수에서 2은 010입니다. 이진수에서 3은 011입니다. 이진수에서 4은 100입니다. 이진수에서 5은 101입니다. 이진수에서 6은 110입니다. 이진수에서 7은 111입니다. 등등…

aba & b
000
010
100
111

따라서 console.log를 확인하면 5 & 1 표현식은 1을 리턴합니다. 먼저, & 연산자는 두 숫자를 이진수로 변환합니다. 그래서 5는 101로, 1은 001로 바뀝니다.

그런 다음 비트 AND 연산자를 사용해서 모든 비트 (0과 1) 를 비교합니다. 101 & 001. 표에서 볼 수 있듯이 a AND b가 1인 경우 결과는 1일 것입니다.

101 & 001
101
001
001
  • 먼저 가장 왼쪽의 1 & 0을 비교하고 결과는 0이 됩니다.
  • 그 다음 중간 비트 0 & 0을 비교하고 결과는 0이 됩니다.
  • 그 다음 마지막 비트 1 & 1을 비교하고 결과는 1이 됩니다.
  • 그 다음 이진 결과 001은 10 진수로 변환되어 1이 됩니다.

우리가 console.log를 확인하면 4 & 1 표현식은 0을 리턴 할 것입니다. 4의 마지막 비트를 아는 것은 0이고 0 & 1은 0이 됩니다. 이해하기 어려울때는 재귀 함수를 사용하여 이 문제를 해결할 수 있습니다.

function isEven(num) {
  if (num < 0 || num === 1) return false;
  if (num == 0) return true;
  return isEven(num - 2);
}

59. 객체에 특정 속성이 있는지는 어떻게 확안하는가?

↑ 속성이 객체에 존재하는지 확인하는 세 가지 방법이 있습니다.

첫번째로 in 연산자를 사용하는 것입니다. in 연산자를 사용하는 문법은 propertyname in object와 같습니다. 속성이 존재하면 true를, 그렇지 않으면 false를 리턴합니다.

const o = {
  "prop" : "bwahahah",
  "prop2" : "hweasa"
};

// true. "prop"속성이 "o"객체에 있음을 나타냄
console.log("prop" in o);

// false. "prop"속성이 "o"객체에 없음을 나타냄
console.log("prop1" in o);

두번째로, 객체에서 hasOwnProperty 메서드를 사용하는 것입니다. 이 방법은 JavaScript의 모든 객체에서 사용할 수 있습니다. 속성이 존재하면 true를, 그렇지 않으면 false를 리턴합니다.

// 첫 번째 예제의 o 객체를 사용합니다.
console.log(o.hasOwnProperty("prop2")); // true
console.log(o.hasOwnProperty("prop1")); // false

세번째로, 대괄호 표기법 obj["prop"]를 사용하는 것입니다. 속성이 존재하면 해당 속성의 값을 리턴하고 그렇지 않으면 undefined를 리턴합니다.

// 첫 번째 예제의 o 객체를 사용합니다.
console.log(o["prop"]); // "bwahahah"
console.log(o["prop1"]); // undefined

60. AJAX 란 무엇인가?

↑ AJAX는 비동기 JavaScript 및 XML을 말합니다. 비동기식으로 데이터를 표시하는데 사용되는 관련 기술 그룹입니다. 이말은 즉, 웹 페이지를 다시 로드하지 않고도 서버로 데이터를 보내고 서버에서 데이터를 가져올 수 있다는 것입니다.

AJAX에 대한 기술 사용

  • HTML - 웹 페이지 구조
  • CSS - 웹 페이지 스타일
  • JavaScript - 웹 페이지의 동작 및 DOM 업데이트
  • XMLHttpRequest API - 서버에서 데이터를 보내고 되찾아오는데 사용
  • PHP, Python, Nodejs - 일부 서버 사이드 언어

61. JavaScript로 객체를 만드는 방법은 무엇인가?

↑ 객체 리터럴 사용

  const o = {
    name: "Mark",
    greeting() {
      return `Hi, I'm ${this.name}`;
    }
  };

  o.greeting(); // returns "Hi, I'm Mark"

Constructor 함수 사용

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

Person.prototype.greeting = function () {
  return `Hi, I'm ${this.name}`;
}

const mark = new Person("Mark");

mark.greeting(); // returns "Hi, I'm Mark"

Object.create 메서드 사용

const n = {
  greeting() {
    return `Hi, I'm ${this.name}`;
  }
};

// "o"의 프로토 타입을 "n"으로 설정
const o = Object.create(n);

o.name = "Mark";

console.log(o.greeting()); // logs "Hi, I'm Mark"

62. Object.seal과 Object.freeze 메서드의 차이점은 무엇인가?

↑ 두 메서드의 차이점은 Object.freeze를 객체에 사용할 때, 객체 속성은 불변이 됩니다. 즉, 해당되는 속성 값을 변경하거나 수정할 수 없습니다. 반면에 Object.seal 메서드에서 기존 속성을 변경할 수 있습니다.

63. 객체에서 in 연산자와 hasOwnProperty 메서드의 차이점은 무엇인가?

↑ 이 두 기능을 모두 알고 있으므로 객체에 속성이 있는지 확인하십시오. 이것은 true false를 리턴합니다. 두 기능의 차이점으로는 in 연산자는 현재 객체에서 속성을 못 찾을 경우 객체의 프로토 타입 체인을 검사합니다. 반면에 hasOwnProperty 메서드는 프로토 타입 체인을 무시하고 현재 객체에 속성이 존재하는지만 확인합니다.

// 이전 질문의 객체를 사용
console.log("prop" in o); // true
console.log("toString" in o); // true. 이 객체의 프로토 타입인 Object.prototype에서 toString 메서드를 사용할 수 있음

console.log(o.hasOwnProperty("prop")); // true
console.log(o.hasOwnProperty("toString")); // false. 객체의 프로토 타입을 확인하지 않음

64. JavasScript에서 어떻게 비동기 코드를 처리하는가?

↑

65. 함수 표현식(function expression)과 함수 선언(function declaration)의 차이점은 무엇인가?

↑ 아래와 같은 예제가 있다고 가정해봅시다.

hoistedFunc();
notHoistedFunc();

function hoistedFunc(){
  console.log("I am hoisted");
}

var notHoistedFunc = function(){
  console.log("I will not be hoisted!");
}

notHoistedFunc 호출은 에러를 던지지만 hoistedFunc 호출은 그렇지 않습니다. hoistedFunc은 호이스팅되고 반면에 notHoistedFunc은 호이스팅 되지 않기 때문입니다. 호이스팅에 관한 질문

66. 함수는 몇 가지 방법으로 호출 할 수 있는가?

↑ JavaScript에서 함수를 호출하는 방법에는 4가지가 있습니다. 호출은 this 또는 해당 함수의 “소유자” 객체 값을 결정합니다.

  • 함수로 호출 - 함수가 메서드, constructor 또는 apply, call 메서드와 함께 호출되지 않은 경우 함수로 호출됩니다. 이 함수의 “owner” 객체는 window 객체가 됩니다.
//Global 스코프
function add(a,b){
  console.log(this);
  return a + b;
}

add(1, 5); // 로그는 "window" 객체와 6을 리턴

const o = {
  method(callback){
    callback();
  }
}

o.method(function () {
  console.log(this); // 로그는 "window" 객체
});
  • 메서드로 호출 - 객체의 속성에 함수 값이 있으면 이를 메서드라고 합니다. 해당 메서드가 호출되면 this 값이 해당 객체가 됩니다.
const details = {
  name : "Marko",
  getName() {
    return this.name;
  }
}

details.getName(); // Marko 리턴
// "getName"메서드 내의 "this"값은 "details"객체
  • constructor로 호출 - 함수가 new 키워드로 호출된 경우 이를 함수 생성자(constructor)라고 합니다. 빈 객체가 만들어지고 this는 해당 객체를 가리킵니다.
function Employee(name, position, yearHired) {
  // 빈 객체를 만듭니다 {}
  // 그런 다음 빈 객체를 "this"키워드에 할당합니다.
  // this = {};
  this.name = name;
  this.position = position;
  this.yearHired = yearHired;
  // Employee.prototype에서 상속
  // 명시적인 return 문이 지정되지 않은 경우 "this"값을 암시적으로 리턴합니다.
};

const emp = new Employee("Marko Polo", "Software Developer", 2017);
  • apply 및 call 메서드를 사용한 호출 - this 값이나 함수의 “owner”객체를 명시적으로 지정하려면 이런 메서드들을 사용할 수 있습니다. 이러한 방법은 모든 함수에 사용할 수 있습니다.
const obj1 = {
  result: 0
};

const obj2 = {
  result: 0
};

function reduceAdd() {
  let result = 0;
  for(let i = 0, len = arguments.length; i < len; i++) {
    result += arguments[i];
  }
  this.result = result;
}

reduceAdd.apply(obj1, [1, 2, 3, 4, 5]);  // "reduceAdd"함수 내의 "this"객체는 "obj1"
reduceAdd.call(obj2, 1, 2, 3, 4, 5);  // "reduceAdd"함수 내의 "this"객체는 "obj2"

67. Memoization란 무엇이며 용도는 무엇인가?

↑ Memoization은 이전에 계산된 결과 또는 값을 기억할 수 있는 함수를 만드는 프로세스입니다. Memoization 함수를 사용하는 것은 같은 인수로 마지막 계산에서 이미 수행된 경우 해당 함수의 계산을 피하는 것입니다. 이렇게하면 시간이 절약되지만 이전 결과를 저장하기 위해 더 많은 메모리를 소비한다는 단점이 있습니다.

68. Memoization helper 함수를 구현하시오.

↑

function memoize(fn) {
  const cache = {};
  return function (param) {
    if (cache[param]) {
      console.log('cached');
      return cache[param];
    } else {
      let result = fn(param);
      cache[param] = result;
      console.log(`not cached`);
      return result;
    }
  }
}

const toUpper = (str = "") => str.toUpperCase();

const toUpperMemoized = memoize(toUpper);

toUpperMemoized("abcdef");
toUpperMemoized("abcdef");

이 memoize helper 함수는 하나의 인수를 허용하는 함수에서만 작동합니다. 여러 인수를 허용하는 memoize helper 기능을 만들어야합니다.

const slice = Array.prototype.slice;
function memoize(fn) {
  const cache = {};
  return (...args) => {
    const params = slice.call(args);
    console.log(params);
    if (cache[params]) {
      console.log('cached');
      return cache[params];
    } else {
      let result = fn(...args);
      cache[params] = result;
      console.log(`not cached`);
      return result;
    }
  }
}
const makeFullName = (fName, lName) => `${fName} ${lName}`;
const reduceAdd = (numbers, startingValue = 0) => numbers.reduce((total, cur) => total + cur, startingValue);

const memoizedMakeFullName = memoize(makeFullName);
const memoizedReduceAdd = memoize(reduceAdd);

memoizedMakeFullName("Marko", "Polo");
memoizedMakeFullName("Marko", "Polo");

memoizedReduceAdd([1, 2, 3, 4, 5], 5);
memoizedReduceAdd([1, 2, 3, 4, 5], 5);

69. typeof null은 왜 객체를 리턴하며 어떻게 값이 null인지 확인하는가?

↑ typeof null == 'object'는 항상 true를 리턴합니다. 왜냐하면 이것은 JavaScript가 탄생 한 이후로 null을 구현했기 때문입니다. typeof null == 'object'를 typeof null == 'null'로 변경하는 수정이 제안되었습니다. 그러나 더 많은 버그로 이어질 수 있기 때문에 거부되었습니다.

=== 또는 엄격한 항등 연산자를 사용하여 값이 null인지 확인할 수 있습니다.

  function isNull(value) {
    return value === null;
  }

70. new 키워드는 무엇을 하는가?

↑ new 키워드는 constructor 함수와 함께 사용되어 JavaScript로 객체를 만듭니다.

아래에 예제 코드가 있다고 가정합시다.

function Employee(name, position, yearHired) {
  this.name = name;
  this.position = position;
  this.yearHired = yearHired;
};

const emp = new Employee("Marko Polo", "Software Developer", 2017);

new 키워드는 4개의 일을 합니다.

  • 빈 객체를 만듭니다.
  • 빈 객체를 this 값에 할당합니다.
  • 함수는 functionName.prototype에서 상속됩니다.
  • 명시적인 return 문이 사용되지 않으면 this를 리턴합니다.

위 코드에서, 먼저 빈 객체 {}를 만듭니다. 그런 다음 this값은 빈 객체 this = {}가 됩니다. 그리고 this 객체에 속성을 추가합니다. 명시적인 return 서술문이 없기 때문에 자동으로 this를 리턴합니다.

Thanks guys for reading this post.