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의 차이점은 무엇인가?
- 56. NaN이란 무엇인가? 값이 NaN인지 확인하는 방법은 무엇인가?
- 57. 어떻게 값이 Array인지 확인하는가?
- 58. % 또는 모듈로 연산자를 사용하지 않고 number가 짝수인지 확인하는 방법은 무엇인가?
- 59. 객체에 특정 속성이 있는지는 어떻게 확안하는가?
- 60. AJAX 란 무엇인가?
- 61. JavaScript로 객체를 만드는 방법은 무엇인가?
- 62. Object.seal과 Object.freeze 메서드의 차이점은 무엇인가?
- 63. 객체에서 in 연산자와 hasOwnProperty 메서드의 차이점은 무엇인가?
- 64. JavasScript에서 어떻게 비동기 코드를 처리하는가?
- 65. 함수 표현식과 함수 선언의 차이점은 무엇인가?
- 66. 함수는 몇 가지 방법으로 호출 할 수 있는가?
- 67. Memoization란 무엇이며 용도는 무엇인가?
- 68. Memoization helper 함수를 구현하시오.
- 69. typeof null은 왜 객체를 리턴하며 어떻게 값이 null인지 확인하는가?
- 70. new 키워드는 무엇을 하는가?
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
입니다.
반면에 **명시적 강제변환(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입니다.
등등…
a | b | a & b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
따라서 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
를 리턴합니다.