Skip to content

Latest commit

 

History

History
5103 lines (3434 loc) · 148 KB

README-ko_KR.md

File metadata and controls

5103 lines (3434 loc) · 148 KB

JavaScript 질문


JavaScript에 관한 객관식 질문을 Instagram 스토리에 올리고 있어요, 물론 여기에도 게시할 거예요! 마지막 업데이트: 6월 12일

기초부터 심화까지: JavaScript를 얼마나 잘 알고 있는지 테스트하거나, 지식을 조금 더 새롭게 하거나, 코딩 면접을 준비하세요! 💪 🚀 이 저장소를 새로운 질문과 함께 주기적으로 업데이트해요. 질문 아래 접힌 부분에 답을 추가했어요, 답을 클릭하면 간단하게 펼쳐져요. 그냥 재미로 하는 거예요, 행운을 빌어요! ❤️

내게 편하게 연락하세요! 😊
Instagram || Twitter || LinkedIn || Blog

프로젝트에 자유롭게 사용하세요! 😃 이 저장소를 참고해 준다면 정말 감사할 거예요, 저는 질문과 해설을 만들고(네 슬퍼요 하하), 커뮤니티는 제가 레포를 유지하고 개선하는 데 많은 도움을 줘요! 💪🏼 고맙고 좋은 시간 보내요!

사용 가능한 번역 20개 🇸🇦🇪🇬🇧🇦🇬🇧🇩🇪🇪🇸🇫🇷🇮🇩🇯🇵🇳🇱🇧🇷🇷🇺🇹🇭🇹🇷🇺🇦🇻🇳🇨🇳🇹🇼🇽🇰


1. 무엇이 출력 될까요?
function sayHi() {
  console.log(name);
  console.log(age);
  var name = 'Lydia';
  let age = 21;
}

sayHi();
  • A: Lydia 그리고 undefined
  • B: Lydia 그리고 ReferenceError
  • C: ReferenceError 그리고 21
  • D: undefined 그리고 ReferenceError

답: D

함수 안에서, 우선 var 키워드를 사용해 name 변수를 선언해요. 이것은 변수를 정의한 줄에 실제로 도달할 때까지, 기본값 undefined으로 호이스팅 되는 것(생성단계에 메모리 공간이 설정)을 의미해요. name 변수를 출력하려는 줄에서 아직 변수를 정의하지 않았기 때문에, undefined 값을 유지해요.

var와는 다르게 let 키워드(그리고 const)를 가진 변수는 호이스팅 되지만, 초기화 되지 않아요. 변수를 선언(초기화)하는 줄 전에는 접근할 수 없어요. 이건 "일시적 사각지대"라고 불려요. 변수가 선언되기 전 변수에 접근하려고 하면, JavaScript는 ReferenceError를 던져요.


2. 무엇이 출력 될까요?
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}
  • A: 0 1 2 그리고 0 1 2
  • B: 0 1 2 그리고 3 3 3
  • C: 3 3 3 그리고 0 1 2

답: C

JavaScript의 이벤트 큐 때문에, setTimeout의 콜백 함수는 루프가 실행된 후에 호출돼요. 첫 번째의 루프의 변수 ivar 키워드를 사용해 선언되어 전역 값이 돼요. 루프 동안, 단항 연산자 ++를 사용해 매번 i의 값을 1씩 증가시켰어요. setTimeout콜백 함수가 호출되기까지, 첫 번째 예시에서의 i3이에요.

두 번째 루프에서, 변수 ilet 키워드를 사용해 선언되었어요: let(그리고 const) 키워드로 선언된 변수는 블록-스코프예요(블록은 { } 사이의 모든 것). 각각을 반복하는 동안, i는 새로운 값을 갖게 되고, 각각의 값은 루프 스코프 안에 있어요.


3. 무엇이 출력 될까요?
const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius,
};

console.log(shape.diameter());
console.log(shape.perimeter());
  • A: 20 그리고 62.83185307179586
  • B: 20 그리고 NaN
  • C: 20 그리고 63
  • D: NaN 그리고 63

답: B

diameter의 값은 일반 함수지만, perimeter의 값은 화살표 함수라는 점을 유의하세요.

화살표 함수에서 this 키워드는 일반 함수와는 다르게 현재 주변 스코프를 참조해요! 이것은 perimeter를 부를 때 shape 객체가 아닌 그것을 둘러싼 스코프(예를 들면 window)를 참조하는 것을 의미해요.

그 객체에는 radius라는 값은 없기 때문에 undefined를 반환해요.


4. 무엇이 출력 될까요?
+true;
!'Lydia';
  • A: 1 그리고 false
  • B: false 그리고 NaN
  • C: false 그리고 false

답: A

단항 더하기는 피연산자를 숫자로 변환하려 해요. true1이고, false0이에요.

문자열 'Lydia'는 참 같은 값이에요. 사실 우리가 물어본 건 "참 같은 이 값은 거짓인가?"예요. 이건 false를 반환해요.


5. 답은 어느 것일까요?
const bird = {
  size: 'small',
};

const mouse = {
  name: 'Mickey',
  small: true,
};
  • A: mouse.bird.size 는 유효하지 않아요
  • B: mouse[bird.size] 는 유효하지 않아요
  • C: mouse[bird['size']] 는 유효하지 않아요
  • D: 이 모든 것은 유효해요.

답: A

JavaScript에서 모든 객체의 키는 문자열이에요(심볼이 아닌 한). 객체의 키를 문자열 으로 입력하지 않더라도, 항상 내부적으로 문자열로 변환돼요.

JavaScript는 문장을 해석(또는 분)해요. 대괄호 표기를 사용하면 첫 번째 열린 대괄호 [를 보고 닫힌 대괄호 ]를 찾을 때까지 진행해요. 다 찾은 후에만 문장을 평가할 거예요.

mouse[bird.size]: 먼저 'small'bird.size를 평가해요. mouse['small']true를 반환해요.

그러나 이것은 점 표기법에서 발생하지 않아요. mousebird라고 불리는 키를 가지고 있지 않기 때문에, mouse.birdundefined임을 의미해요. 그다음에, 점 표기법을 사용해 size를 물어봐요: mouse.bird.size. mouse.birdundefined이기 때문에, 사실 우리가 물어보는 건 undefined.size에요. 이건 유효하지 않아요, 그리고 Cannot read property 'size' of undefined와 비슷한 오류를 던질 거예요.


6. 무엇이 출력 될까요?
let c = { greeting: 'Hey!' };
let d;

d = c;
c.greeting = 'Hello';
console.log(d.greeting);
  • A: Hello
  • B: Hey!
  • C: undefined
  • D: ReferenceError
  • E: TypeError

답: A

JavaScript에서 모든 객체는 서로를 동일하게 설정하면 _참조_로 상호작용해요.

우선, 변수 c는 객체에 대한 값을 갖고 있어요. 그 후 c가 객체에 가지고 있는 것과 동일한 참조를 d에 할당해요.

하나의 객체를 변경하면, 모든 객체가 변해요.


7. 무엇이 출력 될까요?
let a = 3;
let b = new Number(3);
let c = 3;

console.log(a == b);
console.log(a === b);
console.log(b === c);
  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true

답: C

new Number()는, 내장 함수 생성자예요. 숫자처럼 보이지만, 사실 숫자가 아니에요: 많은 추가 특성이 있고 그것은 객체예요.

==연산자를 사용할 때는, 같은 을 가졌는지 여부만 확인해요. 모두3의 값을 가지고 있음으로 true를 반환해요.

그러나, ===연산자를 사용할 때는, 값 그리고 형 둘 다 같아야 해요. 이건 아니에요: new Number()는 숫자가 아니에요. 객체에요. 그래서 둘 다 false를 반환해요.


8. 무엇이 출력 될까요?
class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor;
    return this.newColor;
  }

  constructor({ newColor = 'green' } = {}) {
    this.newColor = newColor;
  }
}

const freddie = new Chameleon({ newColor: 'purple' });
console.log(freddie.colorChange('orange'));
  • A: orange
  • B: purple
  • C: green
  • D: TypeError

답: D

colorChange함수는 정적이에요. 정적 메소드는 그것이 만들어지는 생성자에서만 살아있도록 설계되어, 어떤 자식들도 상속받을 수 없어요. freddie는 자식이기 때문에, 이 함수는 상속되지 않아 freddie인스턴스에서는 이용할 수 없어요: TypeError가 던져져요.


9. 무엇이 출력 될까요?
let greeting;
greetign = {}; // Typo!
console.log(greetign);
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined

답: A

방금 전역 객체에 빈 객체를 만들었기 때문에, 객체는 출력돼요. greetinggreettign으로 잘못 입력했을 때, JS 인터프리터는 global.greettign = {} (또는 브라우저의 window.greetign = {})라고 간주해요.

이것을 피하려면, "use strict"를 사용해요. 이렇게 하면 변수를 어떤 것과 동일하게 설정하기 전에 변수를 선언했는지 확인할 수 있어요.


10. 이렇게 하면 무슨 일이 생길까요?
function bark() {
  console.log('Woof!');
}

bark.animal = 'dog';
  • A: 별일 없어요, 이건 완전히 괜찮아요!
  • B: SyntaxError 이 방법으로 함수에 속성을 추가할 수 없어요.
  • C: "Woof"이 출력돼요.
  • D: ReferenceError

답: A

JavaScript에서는 가능한데, 함수는 객체이기 때문이에요! (원시형 이외는 모두 객체)

함수는 특별한 종류의 객체예요. 당신이 쓴 코드는 실제 함수가 아니에요. 함수는 속성을 가진 객체예요. 이 속성은 호출이 가능해요.


11. 무엇이 출력 될까요?
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person('Lydia', 'Hallie');
Person.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

console.log(member.getFullName());
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined

답: A

JavaScript에서, 함수는 객체이고 그렇기 때문에 메소드 getFullName은 생성자 함수 객체 자체에 추가돼요. 이런 이유로, 우리는 Person.getFullName()을 부를 수 있지만 member.getFullName()TypeError를 던져요.

모든 객체 인스턴스에서 메소드를 사용할 수 있게 하려면, 메소드를 프로토타입 속성에 추가하세요.

Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};


12. 무엇이 출력 될까요?
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const lydia = new Person('Lydia', 'Hallie');
const sarah = Person('Sarah', 'Smith');

console.log(lydia);
console.log(sarah);
  • A: Person {firstName: "Lydia", lastName: "Hallie"} 그리고 undefined
  • B: Person {firstName: "Lydia", lastName: "Hallie"} 그리고 Person {firstName: "Sarah", lastName: "Smith"}
  • C: Person {firstName: "Lydia", lastName: "Hallie"} 그리고 {}
  • D:Person {firstName: "Lydia", lastName: "Hallie"} 그리고 ReferenceError

답: A

sarah에게 new 키워드를 사용하지 않았어요. new를 사용한 경우, this는 우리가 만든 새로운 빈 객체를 참조해요. 그러나, new를 추가하지 않으면 전역 변수를 참조해요!

this.firstName"Sarah"이고, this.lastName"Smith"라고 말했었어요. (그렇지만)실제로는, global.firstName = 'Sarah' 그리고 global.lastName = 'Smith'를 정의한 거예요. sarah 자체는 undefined로 남아있어요, 그렇기 때문에 Person함수의 값을 반환하지 않아요.


13. 이벤트 전달의 3단계는 무엇일까요?
  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling

답: D

capturing 단계 동안에, 이벤트는 조상 요소를 거쳐 target 요소까지 내려가요. 그런 다음 target 요소에 도달하고, bubbling이 시작돼요.


14. 모든 객체는 프로토 타입을 가져요.
  • A: true
  • B: false

답: B

기본 객체를 제외한, 모든 객체는 프로토타입을 가져요. 기본 객체는 사용자가 만든 객체이거나 new 키워드를 사용해 만들어진 객체예요. 기본 객체는 .toString과 같은 몇 개의 메소드와 속성에 접근할 수 있어요. 이것이 내장 JavaScript 메소드를 사용할 수 있는 이유죠! 이러한 모든 메소드는 프로토타입에서 사용할 수 있어요. JavaScript가 당신의 객체를 바로 찾을 수 없더라도, 당신이 접근할 수 있도록 프로토타입 체인으로 내려가 찾을 거예요.


15. 무엇이 출력 될까요?
function sum(a, b) {
  return a + b;
}

sum(1, '2');
  • A: NaN
  • B: TypeError
  • C: '12'
  • D: 3

답: C

JavaScript는 동적으로 유형화된 언어에요: 특정 변수가 어떤 유형인지 명시하지 않아요. 변수는 당신이 모르는 사이에 자동으로 다른 유형으로 변환될 수 있는데, 이걸 암묵적 형 변환 이라고 불러요. Coercion은 하나의 유형을 다른 유형으로 변환해요.

이 예제에서, JavaScript는 함수가 이해하고 값을 반환하도록 숫자 1을 문자열로 변환해요. 숫자 유형 (1)과 문자열 유형 ('2')을 추가하는 동안, 숫자는 문자열로 취급돼요. "Hello" + "World"처럼 문자열을 연결해요, 따라서 여기서 일어나는 일은 "1" + "2""12"에요.


16. 무엇이 출력 될까요?
let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2

답: C

접미사 단항 연산자 ++:

  1. 값 반환 (0을 반환해요)
  2. 값 증가 (지금 number는 1이에요)

접두사 단항 연산자 ++:

  1. 값 증가 (지금 number는 2이에요)
  2. 값 반환 (2를 반환해요)

0 2 2를 반환해요.


17. 무엇이 출력 될까요?
function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}

const person = 'Lydia';
const age = 21;

getPersonInfo`${person} is ${age} years old`;
  • A: "Lydia" 21 ["", " is ", " years old"]
  • B: ["", " is ", " years old"] "Lydia" 21
  • C: "Lydia" ["", " is ", " years old"] 21

답: B

태그가 지정된 템플릿 리터럴을 사용한다면, 첫 번째 인수의 값은 항상 문자열 값의 배열이에요. 나머지 인수는 표현식을 통과한 값을 가져요.


18. 무엇이 출력 될까요?
function checkAge(data) {
  if (data === { age: 18 }) {
    console.log('You are an adult!');
  } else if (data == { age: 18 }) {
    console.log('You are still an adult.');
  } else {
    console.log(`Hmm.. You don't have an age I guess`);
  }
}

checkAge({ age: 18 });
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess

답: C

동등성을 테스트할 때, 원시형은 으로 비교되고, 객체는 참조 로 비교돼요. JavaScript는 객체가 메모리 내의 같은 장소를 참조하고 있는지를 확인해요.

비교하고 있는 두 개의 객체는 그것이 없어요: 파라미터로 전달된 객체와 동등성을 확인하기 위해 사용한 객체는 메모리 내의 다른 장소를 참조해요.

{ age: 18 } === { age: 18 } 그리고 { age: 18 } == { age: 18 } 두 개 다 false를 반환하는 이유예요.


19. 무엇이 출력 될까요?
function getAge(...args) {
  console.log(typeof args);
}

getAge(21);
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"

답: C

rest 파라미터 (...args)는 남아있는 모든 인수을 하나의 배열로 "집합" 해요. 배열은 객체이니까 typeof args"object"를 반환해요.


20. 무엇이 출력 될까요?
function getAge() {
  'use strict';
  age = 21;
  console.log(age);
}

getAge();
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError

답: C

"use strict"을 사용하면, 실수로 전역 변수를 선언하지 않게 해줘요. age라는 변수를 선언한 적이 전혀 없고, "use strict"을 사용하고 있으니, reference error를 던지게 될 거예요. 만약 "use strict"을 사용하지 않았다면 동작할 거예요, age 속성이 전역 객체에 추가된 것이기 때문이죠.


21. sum의 값은 무엇일까요?
const sum = eval('10*10+5');
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"

답: A

eval 문자열로 통과된 코드를 평가해요. 만약 그것이 이 경우처럼 표현 식이라면, 표현 식을 평가해요. 표현식은 10 * 10 + 5이에요. 이것은 숫자 105를 반환해요.


22. cool_secret에 몇 시간이나 접근이 가능할까요?
sessionStorage.setItem('cool_secret', 123);
  • A: 영원히, 데이터는 사라지지 않아요.
  • B: 사용자가 탭을 닫을 때.
  • C: 사용자가 탭뿐만 아니라, 브라우저 전체를 닫을 때.
  • D: 사용자가 자신의 컴퓨터를 종료시켰을 때.

답: B

sessionStorage에 저장된 데이터는 을 닫은 후에 삭제돼요.

만약 localStorage를 사용했다면, 예를 들어 localStorage.clear()를 호출하지 않는 한, 데이터는 영원할 거예요.


23. 무엇이 출력 될까요?
var num = 8;
var num = 10;

console.log(num);
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError

답: B

var 키워드를 사용하면, 같은 이름으로 복수의 변수를 선언할 수 있어요. 변수는 최신의 값을 가져요.

블록 스코프의 let 또는 const에서는 할 수 없어요.


24. 무엇이 출력 될까요?
const obj = { 1: 'a', 2: 'b', 3: 'c' };
const set = new Set([1, 2, 3, 4, 5]);

obj.hasOwnProperty('1');
obj.hasOwnProperty(1);
set.has('1');
set.has(1);
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true

답: C

모든 객체의 키는(심볼 제외) 문자열로 직접 입력하지 않았다고 해도 내부적으로는 문자열이에요. 이것이 obj.hasOwnProperty('1')도 true를 반환하는 이유예요.

set에서는 동작하지 않아요. set에는 '1'이 없어요: set.has('1')false를 반환해요. 숫자 유형인 1을 가지고 있어, set.has(1)true를 반환해요.


25. 무엇이 출력 될까요?
const obj = { a: 'one', b: 'two', a: 'three' };
console.log(obj);
  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError

답: C

같은 이름의 키를 두 개 갖고 있다면, 키는 대체 될 거예요. 여전히 첫 번째 위치에 있지만, 마지막으로 지정된 값을 가져요.


26. JavaScript의 전역 실행 컨텍스트는 두가지를 만들어요: 전역객체와 "this" 키워드에요.
  • A: true
  • B: false
  • C: 경우에 따라 달라요

답: A

기본적인 실행 콘텍스트는 전역 실행 문장이에요: 당신의 코드 모든 곳에서 접근할 수 있어요.


27. 무엇이 출력 될까요?
for (let i = 1; i < 5; i++) {
  if (i === 3) continue;
  console.log(i);
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4

답: C

continue 표현 식은 특정 조건이 true를 반환하면 반복 처리를 건너뛰어요.


28. 무엇이 출력 될까요?
String.prototype.giveLydiaPizza = () => {
  return 'Just give Lydia pizza already!';
};

const name = 'Lydia';

console.log(name.giveLydiaPizza())
  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined

답: A

String은 내장 생성자로 속성을 추가할 수 있어요. 그냥 문자열 프로토타입에 메소드를 추가한거예요. 원시형 문자열은 문자열 프로토타입 함수가 생성한 문자열 객체로 자동 변환돼요. 그래서, 모든 문자열(문자열 객체)은 그 메소드에 접근할 수 있어요!


29. 무엇이 출력 될까요?
const a = {};
const b = { key: 'b' };
const c = { key: 'c' };

a[b] = 123;
a[c] = 456;

console.log(a[b]);
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError

답: B

객체 키는 자동으로 문자열로 변환돼요. 객체 a에 키는 객체(b), 값은 123으로 설정하려고 해요.

그러나, 객체를 문자열화 하면 "[object Object]"가 돼요. 그래서 여기서 말하고자 하는 건 a["object Object"] = 123이라는 거예요. 그 후, 같은 일을 다시 시도해요. c는 암묵적으로 문자열화 한 다른 객체에요. 그래서 a["object Object"] = 456이 돼요.

그 후, a[b]를 출력하면 실제로는 a["object Object"]예요. 그냥 456을 설정했기 때문에, 456을 반환해요.


30. 무엇이 출력 될까요?
const foo = () => console.log('First');
const bar = () => setTimeout(() => console.log('Second'));
const baz = () => console.log('Third');

bar();
foo();
baz();
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First

답: B

처음에 setTimeout함수를 호출했어요. 그러나 그것은 마지막에 출력돼요.

브라우저에는 런타임 엔진뿐만 아니라 WebAPI라고 불리는 것도 존재해요. WebAPIsetTimeout함수를 최초에 부여하는데, DOM을 예로 들 수 있어요.

callback 이 WebAPI에 푸시된 후, setTimeout함수 자체(callback이 아니에요!)는 stack에 사라졌어요.

지금, foo 는 호출되었고, "First"는 출력되었어요.

foo는 stack에 사라지고, baz가 호출되었어요. "Third"가 출력되었어요.

WebAPI는 준비가 될 때마다 stack에 항목을 추가할 수 없어요. 대신에, queue 라고 불리는 것에 callback 함수를 푸시해요.

여기서 event loop가 작동하기 시작해요. event loop는 stack과 task queue를 봐요. stack이 비어있다면, queue에 첫 번째의 것을 가져다가 stack 위로 푸시해요.

bar가 호출되었고, "Second"가 출력되었으며, stack에서 사라졌어요.


31. 버튼을 클릭했을때 event.target은 무엇일까요?
<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">Click!</button>
  </div>
</div>
  • A: 외부의 div
  • B: 내부의 div
  • C: button
  • D: 중첩된 모든 요소의 배열

답: C

가장 깊이 중첩된 요소가 이벤트를 발생시킬 이벤트 대상이예요. event.stopPropagation을 통해서 버블링을 중단할 수 있어요.


32. p태그를 클릭하면 출력된 로그는 무엇일까요?
<div onclick="console.log('div')">
  <p onclick="console.log('p')">Click here!</p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div

답: A

p를 클릭하면, 2개의 로그를 볼 수 있어요: p 그리고 div. 이벤트의 전파 중에는 3단계가 있어요: 캡처링, 타겟, 버블링. 기본적으로, 이벤트 핸들러는 버블링 단계에서 시작돼요. (useCapturetrue로 설정하지 않는 한). 가장 깊게 중첩된 요소에서 바깥쪽으로 가요.


33. 무엇이 출력 될까요?
const person = { name: 'Lydia' };

function sayHi(age) {
  console.log(`${this.name} is ${age}`);
}

sayHi.call(person, 21);
sayHi.bind(person, 21);
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function

답: D

두 개 모두, this 키워드를 참조하고자 하는 객체로 보낼 수 있어요. 그렇지만, .call즉시 실행돼요!

.bind.는 함수의 복사본 을 반환하지만, 바인딩된 콘텍스트죠! 즉시 실행되지 않아요.


34. 무엇이 출력 될까요?
function sayHi() {
  return (() => 0)();
}

console.log(typeof sayHi());
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"

답: B

sayHi함수는 즉시 호출 함수 표현식(IIFE)으로서 반환된 값을 반환해요. 이 함수는 0을 반환하고, 형은 "number"이에요.

참고: 내장된 형은 7개만 있어요: null, undefined, boolean, number, string, object 그리고 symbol. 함수는 객체이기 때문에 "function"은 형이 아니라 "object"형이에요.


35. 이 값 중 어느 것이 거짓 같은 값일까요?
0;
new Number(0);
('');
(' ');
new Boolean(false);
undefined;
  • A: 0, '', undefined
  • B: 0, new Number(0), '', new Boolean(false), undefined
  • C: 0, '', new Boolean(false), undefined
  • D: 모든 값은 거짓

답: A

8개의 거짓 같은 값이 있어요:

  • undefined
  • null
  • NaN
  • false
  • '' (빈 문자열)
  • 0
  • -0
  • -0n (BigInt(0))

new Number 그리고 new Boolean과 같은 생성자 함수는 참 같은 값이에요.


36. 무엇이 출력 될까요?
console.log(typeof typeof 1);
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"

답: B

typeof 1"number"를 반환해요. typeof "number""string"을 반환해요.


37. 무엇이 출력 될까요?
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError

답: C

배열의 길이를 초과한 값을 배열의 요소로 설정하고자 할 때, JavaScript는 "empty slots"라고 불리는 것을 생성해요. 이것은 사실 undefined의 값을 가지고 있지만, 다음과 같은 것을 보게 될 거예요:

[1, 2, 3, 7 x empty, 11]

실행 위치에 따라 달라요 (브라우저, node 등마다 달라요.)


38. 무엇이 출력 될까요?
(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();
  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined

답: A

catch블록은 인수x를 받아요. 이것은 인수를 전달할 때 변수로서의 x와는 달라요. 이 x 변수는 블록-스코프예요.

후에, 블록-스코프 변수는 1로 설정하고, 변수 y의 값을 설정해요. 여기서, 블록-스코프의 변수 x를 출력하는데, 이것은 1이에요.

catch 블록 밖에서, x는 여전히 undefined이고 y2이에요. catch 블록 밖에서 console.log(x)를 출력하면, undefined를 반환하고. 그리고 y2를 반환해요.


39. JavaScript의 모든 것은...
  • A: primitive 또는 object
  • B: function 또는 object
  • C: 함정 문제! objects만
  • D: number 또는 object

답: A

JavaScript는 원시형과 객체만 가지고 있어요.

원시형은 boolean, null, undefined, bigint, number, string 그리고 symbol이 있어요.

원시형과 객체를 구별하는 법은 원시형에는 속성이나 메소드가 없어요. 그렇지만 'foo'.toUpperCase()'FOO'로 평가되어, 결과적으로 TypeError가 되지 않아요. 문자열과 같은 원시형이 속성 또는 메소드에 접근하려고 할 때, JavaScript는 래퍼 클래스 중 하나인 String을 사용하여 암묵적으로 감싸고, 표현 식이 평가된 후 즉시 래퍼를 폐기하기 때문이에요. null 그리고 undefined를 제외한 모든 원시형은 이러한 행동을 합니다.


40. 무엇이 출력 될까요?
[
  [0, 1],
  [2, 3],
].reduce(
  (acc, cur) => {
    return acc.concat(cur);
  },
  [1, 2]
);
  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]

답: C

[1, 2]은 초기값이에요. 이것은 시작하는 최초의 값이고, acc의 제일 처음 값이에요. 처음 라운드 동안에 acc[1,2]이며, cur[0, 1]이에요. 그것을 연결하면 결과적으로 [1, 2, 0, 1]이 돼요.

그 후, [1, 2, 0, 1]acc이고, [2, 3]cur이에요. 그것을 연결하면 [1, 2, 0, 1, 2, 3]을 얻게 돼요.


41. 무엇이 출력 될까요?
!!null;
!!'';
!!1;
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false

답: B

null은 거짓 같은 값이에요. !nulltrue를 반환해요. !truefalse를 반환해요.

"" 은 거짓 같은 값이에요. !""true를 반환해요. !truefalse를 반환해요.

1은 참 같은 값이에요. !1false를 반환해요. !falsetrue를 반환해요.


42. setInterval 메소드는 브라우저에게 무엇을 반환 할까요?
setInterval(() => console.log('Hi'), 1000);
  • A: 유니크한 id
  • B: 지정된 밀리초
  • C: 통과된 함수
  • D: undefined

답: A

이것은 유니크한 id를 반환해요. 이 id는 clearInterval() 함수의 간격을 없애기 위해 사용될 수 있어요.


43. 이것은 무엇을 반환할까요?
[...'Lydia'];
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]

답: A

문자열은 반복 가능한 객체예요. spread 연산자는 반복 가능한 객체의 모든 문자를 하나의 요소로 매핑해요.


44. 무엇이 출력 될까요?
function* generator(i) {
  yield i;
  yield i * 2;
}

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
  • A: [0, 10], [10, 20]
  • B: 20, 20
  • C: 10, 20
  • D: 0, 10 그리고 10, 20

답: C

일반 함수는 호출 한 뒤 중간에 멈출 수 없어요. 하지만, 제너레이터 함수는 중간에 "멈췄다가", 나중에 중단된 부분부터 계속할 수 있어요. 제너레이터 함수는 yield 키워드를 만날 때마다, yield 뒤에 명시된 값을 넘겨줘요. 제너레이터 함수에서는 값을 반환 하지 않고, 값을 넘겨진다 는 것을 유의하세요.

우선, 제너레이터 함수에서 i10으로 초기화해요. next() 메소드를 사용해 제너레이터 함수를 호출해요. 처음에 제너레이터 함수를 호출하면, i10이에요. 첫 번째 yield 키워드를 만났어요: 그것은 i의 값을 넘겨줘요. 이제 제너레이터는 "멈추고", 10을 출력해요.

그 후, next() 메소드를 사용해 함수를 다시 호출해요. 이전에 멈춘 부분에서부터 다시 시작하고, i는 여전히 10이에요. 이제, 다음 yield 키워드를 만나 i * 2를 넘겨줘요. i10이므로, 10 * 2, 즉 20을 반환해요. 결과는 10, 20이에요.


45. 이것은 무엇을 반환할까요?
const firstPromise = new Promise((res, rej) => {
  setTimeout(res, 500, 'one');
});

const secondPromise = new Promise((res, rej) => {
  setTimeout(res, 100, 'two');
});

Promise.race([firstPromise, secondPromise]).then((res) => console.log(res));
  • A: "one"
  • B: "two"
  • C: "two" "one"
  • D: "one" "two"

답: B

복수의 프로미스를 Promise.race 메소드에 넘겨주면, 최초 의 프로미스를 해결/거부해요. setTimeout 메소드에 타이머를 전달해요: 첫 번째 프로미스(firstPromise)에는 500ms, 두 번째 프로미스(secondPromise)에는 100ms. 이것은 'two'의 값을 가진 secondPromise를 최초로 해결한다는 것을 의미해요. 이제 res'two'의 값을 갖고 출력돼요.


46. 무엇이 출력 될까요?
let person = { name: 'Lydia' };
const members = [person];
person = null;

console.log(members);
  • A: null
  • B: [null]
  • C: [{}]
  • D: [{ name: "Lydia" }]

답: D

우선, 변수 person의 값을 name 속성을 가진 객체로 선언해요.

그 후, members라는 변수를 선언해요. 배열의 첫 번째 요소에 person 변수의 값을 대입해요. 서로를 같게 설정하면 _참조_로 상호작용해요. 어떤 변수에서 다른 변수로 참조를 할당하면, 그 참조의 복사본 을 만들어요. (그들은 같은 참조를 가지고 있지 않다는 것을 유의하세요!)

그리고, 변수 personnull로 설정해요.

person 변수의 값만 변경할 수 있고, 배열의 첫 번째 요소는 객체에 대한 다른 (복사된) 참조를 가지고 있기 때문에 변경할 수 없어요. members의 첫 번째 요소는 여전히 원본 객체에 대한 참조를 유지하고 있어요. members 배열을 출력할 때, 첫 번째 요소는 여전히 객체의 값을 갖고 있어 로그가 출력돼요.


47. 무엇이 출력 될까요?
const person = {
  name: 'Lydia',
  age: 21,
};

for (const item in person) {
  console.log(item);
}
  • A: { name: "Lydia" }, { age: 21 }
  • B: "name", "age"
  • C: "Lydia", 21
  • D: ["name", "Lydia"], ["age", 21]

답: B

for-in 루프를 사용하면, 객체의 키를 통해서 반복할 수 있는데, 이 경우에서는 name 그리고 age에요. 내부적으로, 객체의 키는 문자열이에요 (심볼이 아니라면 말이죠). 모든 루프에서, item의 값은 반복 중인 현재의 키 값으로 동일하게 설정해요. 우선, itemname으로 출력돼요. 그 후, itemage로 출력돼요.


48. 무엇이 출력 될까요?
console.log(3 + 4 + '5');
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"

답: B

연산자 결합성은 왼쪽에서 오른쪽 또는 오른쪽에서 왼쪽으로 컴파일러가 표현 식을 평가하는 순서가 돼요. 이것은 연산자가 같은 우선순위를 가진 경우에만 해당돼요. 한 유형의 연산자만 있어요: +. 게다가, 결합성은 왼쪽에서 오른쪽이에요.

처음으로 3 + 4가 평가돼요. 결과는 숫자 7이에요.

7 + '5'의 결과는 강제성 때문에 "75"가 돼요. JavaScript는 숫자 7을 문자열로 변환하고, (관련된 자세한 설명은) 질문 15를 보세요. + 연산자를 사용해서 두 개의 문자열을 연결할 수 있어요. "7" + "5"의 결과는 "75"이에요.


49. num의 값은 무엇일까요?
const num = parseInt('7*6', 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN

답: C

문자열의 첫 번째 숫자만 반환돼요. 진법 에 근거해(파싱하고자 하는 숫자의 기준을 명시하기 위한 두 번째 인수: 기본 10진수, 6진수, 8진수, 2진수 등), parseInt는 문자열 내의 문자가 타당한지 여부를 확인해요. 진수에 유효한 숫자가 아닌 문자를 만나면, 파싱을 멈추고, 다음 문자를 무시해요.

*은 유효한 숫자가 아니에요. "7"만 십진수의 7로 파싱 돼요. 이제 num7의 값을 가져요.


50. 무엇이 출력 될까요?
[1, 2, 3].map((num) => {
  if (typeof num === 'number') return;
  return num * 2;
});
  • A: []
  • B: [null, null, null]
  • C: [undefined, undefined, undefined]
  • D: [ 3 x empty ]

답: C

배열을 매핑할 때, num의 값은 헌재 순환하고 있는 요소예요. 이 경우 요소는 숫자이기 때문에, if 문의 조건 typeof num === "number"true를 반환해요. map 함수는 새로운 배열을 만들고 함수에서 반환된 값을 삽입해요.

그러나, 우리는 값을 반환하지 않아요. 함수는 값을 반환하지 않을 때 undefined를 반환해요. 배열에서의 모든 요소에 대해 함수 블록이 호출되므로, 각 요소에 대해 undefined를 반환해요.


51. 무엇이 출력 될까요?
function getInfo(member, year) {
  member.name = 'Lydia';
  year = '1998';
}

const person = { name: 'Sarah' };
const birthYear = '1997';

getInfo(person, birthYear);

console.log(person, birthYear);
  • A: { name: "Lydia" }, "1997"
  • B: { name: "Sarah" }, "1998"
  • C: { name: "Lydia" }, "1998"
  • D: { name: "Sarah" }, "1997"

답: A

인수는 값이 객체가 아니면 으로 전달되고, 그렇지 않으면(값이 객체면) 참조 로 전달돼요. birthYear는 객체가 아니라 문자열이기 때문에 값으로 전달돼요. 값으로 전달하면 값의 복사본 이 만들어져요(질문 46을 보세요).

변수 birthYear"1997"값에 대한 참조를 가져요. 인수 year 또한 "1997"에 대한 참조를 가지지만, birthYear가 가진 참조 값과는 달라요. year"1998"을 대입하여 year의 값을 업데이트할 때, year의 값만 업데이트해요. birthYear는 여전히 "1997"이에요.

person의 값은 객체예요. 인수 member같은 객체의 (복사된) 참조를 가져요. 참조를 가진 member객체의 속성을 변경하면, 두 개 모두 같은 객체의 참조를 가지고 있기 때문에, person도 변경돼요. 이제 person'의 name 속성의 값은 "Lydia"예요.


52. 무엇이 출력 될까요?
function greeting() {
  throw 'Hello world!';
}

function sayHi() {
  try {
    const data = greeting();
    console.log('It worked!', data);
  } catch (e) {
    console.log('Oh no an error:', e);
  }
}

sayHi();
  • A: "It worked! Hello world!"
  • B: "Oh no an error: undefined"
  • C: SyntaxError: can only throw Error objects
  • D: "Oh no an error: Hello world!"

답: D

throw문을 사용해, 사용자 지정 오류를 만들 수 있어요. 이 표현 식을 사용해, 예외를 던질 수 있어요. 예외는 문자열, 숫자, 불린 또는 객체가 될 수 있어요. 이 경우, 예외는 'Hello world' 문자열이에요.

catch 문을 사용해, try 블록에서 예외를 던진 경우 무엇을 할지 명시할 수 있어요. 예외가 던져졌어요: 문자열 'Hello world'. 이제 e는 문자열이고, 그것을 출력해요. 결과는 'Oh an error: Hello world'예요.


53. 무엇이 출력 될까요?
function Car() {
  this.make = 'Lamborghini';
  return { make: 'Maserati' };
}

const myCar = new Car();
console.log(myCar.make);
  • A: "Lamborghini"
  • B: "Maserati"
  • C: ReferenceError
  • D: TypeError

답: B

속성을 반환할 때, 속성값은 생성자에 설정한 값이 아닌, 반환된 값과 같아요. "Maserati" 문자열을 반환하기 때문에, myCar.make"Maserati"예요.


54. 무엇이 출력 될까요?
(() => {
  let x = (y = 10);
})();

console.log(typeof x);
console.log(typeof y);
  • A: "undefined", "number"
  • B: "number", "number"
  • C: "object", "number"
  • D: "number", "undefined"

답: A

let x = y = 10;은 다음의 단축형이에요:

y = 10;
let x = y;

y10을 대입하면, 전역 객체에 속성 y를 추가해요(브라우저에서는 window, Node에서는 global). 브라우저에서, window.y는 이제 10이에요.

그 후, 변수 x10y를 값으로 선언해요. let키워드로 선언된 변수는 블록 스코프 로, 선언된 블록 내에서만 정의돼요: 이 경우에선 즉시 호출 함수예요(IIFE). typeof연산자를 사용할 때, 피연산자 x는 정의되지 않았어요: 우리는 선언된 블록 밖에서 접근하려 했어요. 이것은 x가 정의되지 않았음을 의미해요. 값을 할당하지 않거나 선언하지 않은 변수는 "undefined" 형이에요. console.log(typeof x)"undefined"를 반환해요.

그러나, y10으로 설정할 때 전역 변수 y를 만들었어요. 이 값은 코드 내 어디에서나 접근할 수 있어요. y는 정의되어있고, "number"형의 값을 유지해요. console.log(typeof y)"number"을 반환해요.


55. 무엇이 출력 될까요?
class Dog {
  constructor(name) {
    this.name = name;
  }
}

Dog.prototype.bark = function () {
  console.log(`Woof I am ${this.name}`);
};

const pet = new Dog('Mara');

pet.bark();

delete Dog.prototype.bark;

pet.bark();
  • A: "Woof I am Mara", TypeError
  • B: "Woof I am Mara", "Woof I am Mara"
  • C: "Woof I am Mara", undefined
  • D: TypeError, TypeError

답: A

프로토타입에서도 delete키워드를 사용해 객체의 속성을 삭제할 수 있어요. 프로토타입에서 속성을 삭제하면, 프로토타입 체인에서 더는 사용할 수 없어요. 이 경우, bark 함수는 delete Dog.prototype.bark 후에는 프로토타입에서 더는 사용할 수 없게 되었어요, 그러나 우리는 여전히 그것에 접근하려고 해요.

함수가 아닌 것을 호출하려고 할 때, TypeError가 던져져요. 이 경우 pet.barkundefined이기 때문에, TypeError: pet.bark is not a function예요.


56. 무엇이 출력 될까요?
const set = new Set([1, 1, 2, 3, 4]);

console.log(set);
  • A: [1, 1, 2, 3, 4]
  • B: [1, 2, 3, 4]
  • C: {1, 1, 2, 3, 4}
  • D: {1, 2, 3, 4}

답: D

Setunique 값의 집합 객체예요: 값은 set 내에서 단 한 번만 발생해요.

중복 값 1을 가진 반복 가능한 [1, 1, 2, 3, 4]을 전달하기 때문에, 그 중 하나는 삭제돼요. 이것은 결과적으로 {1, 2, 3, 4}돼요.


57. 무엇이 출력 될까요?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from './counter';

myCounter += 1;

console.log(myCounter);
  • A: 10
  • B: 11
  • C: Error
  • D: NaN

답: C

import 된 모듈은 read-only 예요 : import 된 모듈은 수정할 수 없어요. export 한 모듈에서만 값을 변경할 수 있어요.

myCounter의 값을 증가시키려고 할 때, 오류를 던져요: myCounter는 read-only이고 수정할 수 없어요.


58. 무엇이 출력 될까요?
const name = "Lydia";
age = 21;

console.log(delete name);
console.log(delete age);
  • A: false, true
  • B: "Lydia", 21
  • C: true, true
  • D: undefined, undefined

답: A

delete연산자는 불린 값을 반환해요: 성공적으로 삭제를 한 경우 true를, 그렇지 않다면 false를 반환해요. 그러나, var, const 또는 let 키워드로 선언된 변수은 delete연산자를 사용해서 삭제될 수 없어요.

name 변수는 const키워드로 선언되었기 때문에, 삭제에 실패해요: false가 반환돼요. age21로 설정할 때, 사실은 age라는 속성을 전역 객체에 추가한 거죠. 이 방법으로 객체, 전역 객체의 속성을 성공적으로 삭제할 수 있어요, 그래서 delete agetrue를 반환해요.


59. 무엇이 출력 될까요?
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;

console.log(y);
  • A: [[1, 2, 3, 4, 5]]
  • B: [1, 2, 3, 4, 5]
  • C: 1
  • D: [1]

답: C

구조 분해 할당을 통해 객체의 배열 또는 속성으로부터 변수를 해체할 수 있어요. 예를 들어:

[a, b] = [1, 2];

a의 값은 이제 1이고, b의 값은 이제 2예요. 사실 이 질문에서 한 건 다음과 같아요:

[y] = [1, 2, 3, 4, 5];

이것은 y의 값은 숫자 1인 배열의 첫 번째 값과 같다는 것을 의미해요. y를 출력하면 1이 반환돼요.


60. 무엇이 출력 될까요?
const user = { name: 'Lydia', age: 21 };
const admin = { admin: true, ...user };

console.log(admin);
  • A: { admin: true, user: { name: "Lydia", age: 21 } }
  • B: { admin: true, name: "Lydia", age: 21 }
  • C: { admin: true, user: ["Lydia", 21] }
  • D: { admin: true }

답: B

spread 연산자 ... 를 사용해 객체를 결합할 수 있어요. 이것은 한 객체의 키/값 쌍을 복사본으로 만들어, 다른 객체에 추가해요. 이 경우, user 객체의 복사본을 만들어, admin 객체에 추가해요. admin 객체는 이제 복사된 키/값 쌍이 들어있고, 결과는 { admin: true, name: "Lydia", age: 21 } 예요.


61. 무엇이 출력 될까요?
const person = { name: 'Lydia' };

Object.defineProperty(person, 'age', { value: 21 });

console.log(person);
console.log(Object.keys(person));
  • A: { name: "Lydia", age: 21 }, ["name", "age"]
  • B: { name: "Lydia", age: 21 }, ["name"]
  • C: { name: "Lydia"}, ["name", "age"]
  • D: { name: "Lydia"}, ["age"]

답: B

defineProperty메소드를 사용해, 객체에 새로운 속성을 추가하거나 기존 속성을 수정할 수 있어요. defineProperty 메소드를 사용해 객체의 속성을 추가할 때, 객체의 속성은 기본적으로 비 열거자 예요. Object.keys메소드는 모든 열거자 객체의 속성 이름을 반환하는데, 이 경우는 "name" 뿐이에요.

defineProperty를 사용해 추가된 속성은 기본적으로 변경할 수 없어요. writable, configurable 그리고 enumerable 속성을 사용해 덮어쓸 수 있어요. defineProperty메소드를 사용하는 방법은 객체에 추가하는 속성을 훨씬 더 많이 제어할 수 있어요.


62. 무엇이 출력 될까요?
const settings = {
  username: 'lydiahallie',
  level: 19,
  health: 90,
};

const data = JSON.stringify(settings, ['level', 'health']);
console.log(data);
  • A: "{"level":19, "health":90}"
  • B: "{"username": "lydiahallie"}"
  • C: "["level", "health"]"
  • D: "{"username": "lydiahallie", "level":19, "health":90}"

답: A

JSON.stringify 두 번째 인수는 replacer 예요. replacer는 함수 또는 배열일 수 있고, 문자열로 변환 할 대상과 방법을 제어할 수 있게 해줘요.

replacer가 배열 이라면, 배열에 포함된 속성의 이름만 JSON 문자열에 추가될 거에요. 이 경우, 이름을 가진 "level" 그리고 "health"속성만 포함되고, "username"은 제외 돼요. data 은 이제 "{"level":19, "health":90}"에요.

replacer가 함수 라면, 문자열로 변환 할 객체의 모든 속성에 호출돼요. 이 함수로부터 반환된 값은 JSON 문자열에 추가될 때 속성의 값이 될 거예요. 만약 값이 undefined라면, 이 속성은 JSON 문자열에서 제외돼요.


63. 무엇이 출력 될까요?
let num = 10;

const increaseNumber = () => num++;
const increasePassedNumber = number => number++;

const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);

console.log(num1);
console.log(num2);
  • A: 10, 10
  • B: 10, 11
  • C: 11, 11
  • D: 11, 12

답: A

단항 연산자 ++우선 피연산자의 값을 반환하고, 그 후 피연산자의 값을 증가시켜요. increaseNumber 함수가 처음으로 반환 한 num의 값은 10 이기 때문에, num1의 값은 10이고, 그 후엔 num의 값만 증가해요.

num1increasePassedNumber로 전달했기 때문에, num210이에요. number10이에요(num1의 값. 다시, 단항 연산자가 ++우선 피연산자의 값을 반환하고, 그 후 피연산자의 값을 증가해요. number의 값은 10이에요 즉, num210이죠.


64. 무엇이 출력 될까요?
const value = { number: 10 };

const multiply = (x = { ...value }) => {
  console.log((x.number *= 2));
};

multiply();
multiply();
multiply(value);
multiply(value);
  • A: 20, 40, 80, 160
  • B: 20, 40, 20, 40
  • C: 20, 20, 20, 40
  • D: NaN, NaN, 20, 40

답: C

ES6에서, 기본값으로 파라미터를 초기화할 수 있어요. 함수에 값이 없이 전달되거나, 파라미터의 값이 "undefined"라면, 파라미터의 값은 기본값이 될 거예요. 이 경우, value 객체의 속성을 새로운 객체 안에 전개했어요. 따라서 x{ number: 10 }을 기본값으로 가져요.

기본 인수는 호출 시점 에 평가돼요! 함수를 부를 때마다, 새로운 객체를 만들어요. 처음 두 번은 값을 전달하지 않고, multiply 함수를 호출해요: x{ number: 10 }의 기본값을 가져요. 그다음 해당 숫자를 곱한 값인 20을 출력해요.

세 번째로 곱셈을 호출할 때, 인수를 전달해요: 그 객체는 value라고 불려요. *= 연산자는 사실 x.number = x.number * 2의 줄임말이에요: x.number의 값을 변경하고, 곱셈한 값 20을 출력해요

네 번째엔, value 객체를 다시 한번 전달해요. x.number는 이전에 20으로 바뀌었기 때문에, x.number *= 240을 출력해요.


65. 무엇이 출력 될까요?
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
  • A: 1 2 그리고 3 3 그리고 6 4
  • B: 1 2 그리고 2 3 그리고 3 4
  • C: 1 undefined 그리고 2 undefined 그리고 3 undefined 그리고 4 undefined
  • D: 1 2 그리고 undefined 3 그리고 undefined 4

답: D

reduce 메소드가 받은 첫 번째 인수는 누산기 예요, 이 경우엔 x죠. 두 번째 인수 y현재 값 이에요. reduce 메소드에서, 배열에 있는 모든 요소에 콜백 함수를 실행하므로 궁극적으로는 하나의 값을 얻어요.

이 예제에서는, 값을 반환하지 않고, 단지 누적된 값과 현재 값을 출력해요.

누산기의 값은 콜백 함수가 이전에 반환한 값이에요. 만약 추가적인 초기값 인수를 reduce 메소드에 전달하지 않았다면, 누산기는 첫번째 부른 첫 번째 요소와 동일해요.

첫 번째로 부를 땐, 누산기 (x)는 1 이에요, 그리고 현재 값인 (y)는 2예요. 콜백 함수로부터 반환되지 않았고, 누산기와 현재 값을 출력해요: 1 그리고 2가 출력돼요.

함수에서 값을 반환하지 않았다면, undefined를 반환해요. 다음번에 부를 때, 누산기는 undefined고, 그리고 현재 값은 3이에요. undefined 그리고 3이 출력돼요.

네 번째 부를 땐, 또 콜백 함수에서 반환받지 않았어요. 누산기는 다시 undefined고, 현재 값은 4예요. undefined 그리고 4가 출력돼요.


66. Dog 클래스를 성공적으로 확장할 수 있는 생성자는 어느 것일까요?
class Dog {
  constructor(name) {
    this.name = name;
  }
};

class Labrador extends Dog {
  // 1
  constructor(name, size) {
    this.size = size;
  }
  // 2
  constructor(name, size) {
    super(name);
    this.size = size;
  }
  // 3
  constructor(size) {
    super(name);
    this.size = size;
  }
  // 4
  constructor(name, size) {
    this.name = name;
    this.size = size;
  }

};
  • A: 1
  • B: 2
  • C: 3
  • D: 4

답: B

파생 클래스에서, super를 부르기 전에는 this 키워드에 접근할 수 없어요. 그렇게 하려고 한다면, ReferenceError를 던질 거에요: 1과 4는 reference error를 던져요

super 키워드를 가지고, 부모 클래스 생성자에 주어진 인수를 부를 수 있어요. 부모 생성자는 name 인수를 받아요, 그래서 namesuper로 전달해야 해요.

Labrador 클래스는 2개의 인수를 받는데, Dog로 부터 확장된 nameLabrador 클래스의 추가 속성인 size예요. 그 두 개는 Labrador 생성자 함수에 전달되어야 하는데, 올바르게 사용된 건 2번째 생성자예요.


67. 무엇이 출력 될까요?
// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));

// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;
  • A: running index.js, running sum.js, 3
  • B: running sum.js, running index.js, 3
  • C: running sum.js, 3, running index.js
  • D: running index.js, undefined, running sum.js

답: B

import 키워드를 사용하면, 모든 import된 modules은 우선-파싱 되어요. import된 모듈은 처음에 실행되는 것을 의미하고, import한 파일 안에 있는 코드는 나중에 실행돼요.

이것은 CommonJSd의 require()import의 차이예요! require()을 사용하면, 런타임 중 코드에서 필요한 시점에 의존성 모듈을 로드 할 수 있어요. 만약 import 대신에 require을 사용하면, running index.js, running sum.js, 3으로 콘솔에 출력될 거에요.


68. 무엇이 출력 될까요?
console.log(Number(2) === Number(2));
console.log(Boolean(false) === Boolean(false));
console.log(Symbol('foo') === Symbol('foo'));
  • A: true, true, false
  • B: false, true, false
  • C: true, false, true
  • D: true, true, true

답: A

모든 심볼은 완전히 유니크해요. 심볼에 전달된 인수의 목적은 심볼에 설명을 제공하는 거에요. 심볼의 값은 전달된 인수에 따라 달라지지 않아요. 동등성을 테스트할 때, 완전히 새로운 두 개의 심볼을 만들어요: 첫번째 Symbol('foo')와 두번째 Symbol('foo'). 이 두개의 값은 유니크하고, 서로 같지 않아요, Symbol('foo') === Symbol('foo')false를 반환해요.


69. 무엇이 출력 될까요?
const name = 'Lydia Hallie';
console.log(name.padStart(13));
console.log(name.padStart(2));
  • A: "Lydia Hallie", "Lydia Hallie"
  • B: " Lydia Hallie", " Lydia Hallie" ("[13x whitespace]Lydia Hallie", "[2x whitespace]Lydia Hallie")
  • C: " Lydia Hallie", "Lydia Hallie" ("[1x whitespace]Lydia Hallie", "Lydia Hallie")
  • D: "Lydia Hallie", "Lyd",

답: C

padStart 메소드를 사용해, 문자열의 시작 부분에 패딩을 추가해 줄 수 있어요. 이 메소드에 전달된 값은 패딩을 포함한 문자열의 전체 길이예요. 문자열 "Lydia Hallie"의 길이는 12예요. name.padStart(13)은 문자열의 시작점에 1 스페이스를 삽입해요, 따라서 12 + 1 은 13이죠.

padStart 메소드에 전달된 인수가 배열의 길이보다 작다면, 패딩은 추가되지 않을 거예요.


70. 무엇이 출력 될까요?
console.log('🥑' + '💻');
  • A: "🥑💻"
  • B: 257548
  • C: 해당 코드 주소를 포함하는 문자열
  • D: 오류

답: A

+ 연산자를 사용해, 문자열을 연결 시킬 수 있어요. 이 경우에는, 문자열 "🥑"과 문자열 "💻"을 연결해, 결과 "🥑💻"를 얻었어요.


71. console.log 표현식 뒤에 언급된 값을 어떻게 출력할 수 있을까요?
function* startGame() {
  const answer = yield 'Do you love JavaScript?';
  if (answer !== 'Yes') {
    return "Oh wow... Guess we're gone here";
  }
  return 'JavaScript loves you back ❤️';
}

const game = startGame();
console.log(/* 1 */); // Do you love JavaScript?
console.log(/* 2 */); // JavaScript loves you back ❤️
  • A: game.next("Yes").value 그리고 game.next().value
  • B: game.next.value("Yes") 그리고 game.next.value()
  • C: game.next().value 그리고 game.next("Yes").value
  • D: game.next.value() 그리고 game.next.value("Yes")

답: C

제너레이터 함수는 yield 키워드를 보면 실행을 "멈춰"요. 첫 번째로, game.next().value를 불러, 함수가 "Do you love JavaScript?" 문자열을 넘겨주도록 할 수 있어요.

yield 키워드를 처음으로 찾기 전까지, 모든 줄이 실행되요. 함수 안 첫 번째 줄에 yield 키워드가 있어요: 첫 번째 yield으로 실행을 멈춰요! 이것은 answer 변수가 아직 정의되지 않았는 뜻이에요!

game.next("Yes").value을 부를 때, 이전 yieldnext() 함수가 전달한 파라미터의 값으로 대체 되는데, 이 경우에는 "Yes"로 대체 돼요. answer 변수의 값은 이제 "Yes"예요. if문의 조건은 false를 반환해, JavaScript loves you back ❤️이 출력돼요.


72. 무엇이 출력 될까요?
console.log(String.raw`Hello\nworld`);
  • A: Hello world!
  • B: Hello
         world
  • C: Hello\nworld
  • D: Hello\n
         world

답: C

String.raw는 escapes(\n, \v, \t 등.)가 무시되는 문자열을 반환해요! 백슬래시는 다음과 같이 끝나면 문제가 될 수 있어요:

const path = `C:\Documents\Projects\table.html`

이렇게 될 거예요:

"C:DocumentsProjects able.html"

String.raw을 사용하면, 간단하게 escape를 무시하고 출력해요:

C:\Documents\Projects\table.html

이 경우, 문자열 Hello\nworld이 출력되요.


73. 무엇이 출력 될까요?
async function getData() {
  return await Promise.resolve('I made it!');
}

const data = getData();
console.log(data);
  • A: "I made it!"
  • B: Promise {<resolved>: "I made it!"}
  • C: Promise {<pending>}
  • D: undefined

답: C

async 함수는 항상 promise를 반환해요. await는 promise가 resolve 할 때까지 기다려야 해요: pending promise는 data를 설정하기 위해 부른 getData()가 반환한 것을 가져요.

resolve된 값 "I made it"에 접근하고 싶다면, data.then() 메소드를 사용해야해요.

data.then(res => console.log(res))

이건 "I made it!"을 출력할 거예요.


74. 무엇이 출력 될까요?
function addToList(item, list) {
  return list.push(item);
}

const result = addToList('apple', ['banana']);
console.log(result);
  • A: ['banana', 'apple']
  • B: 2
  • C: true
  • D: undefined

답: B

.push()메소드는 새로운 배열의 길이 를 반환해요! 이전에, 배열은 한 개의 요소(문자열 "banana")를 포함하고 길이는 1예요. 배열에 문자열 "apple"을 추가한 후, 배열은 두 개 요소를 포함하고, 길이 2를 가져요. addToList 함수로부터 반환 받은거예요.

push 메소드는 원본 배열을 수정해요. 만약 함수로부터 배열의 길이 대신에 배열 을 반환하고 싶다면, item을 푸시한 후 list를 반환해야해요.


75. 무엇이 출력 될까요?
const box = { x: 10, y: 20 };

Object.freeze(box);

const shape = box;
shape.x = 100;

console.log(shape);
  • A: { x: 100, y: 20 }
  • B: { x: 10, y: 20 }
  • C: { x: 100 }
  • D: ReferenceError

답: B

Object.freeze는 객체의 속성을 추가, 삭제 혹은 수정하지 못하게 만들어요(다른 객체 속성의 값이 아닌 한).

변수 shape을 생성할 때, 동결 객체 box와 동일하게 설정했고, shape 역시 동결 객체를 참조해요. Object.isFrozen을 사용해 객체의 동결 여부를 확인할 수 있어요. 이 경우, Object.isFrozen(shape)은 true를 반환하고, 따라서 변수 shape는 동결 객체 참조를 가져요.

shape가 동결 상태이므로, x의 값은 객체가 아니며, x의 속성을 수정할 수 없어요. x는 여전히 10이고, { x: 10, y: 20 }가 출력돼요.


76. 무엇이 출력 될까요?
const { name: myName } = { name: 'Lydia' };

console.log(name);
  • A: "Lydia"
  • B: "myName"
  • C: undefined
  • D: ReferenceError

답: D

오른쪽에 있는 객체로부터 속성 name을 분해할 때, myName라는 이름을 가진 변수에 값 "Lydia"을 할당해요.

{ name: myName }은, JavaScript에게 오른쪽에 있는 name속성의 값을 가진 myName이라고 불리는 새로운 변수를 만든다고 말하는 거예요.

name을 출력하려고 하면, 변수는 정의되지 않아 ReferenceError를 던질거예요.


77. 이것은 순수 함수일까요?
function sum(a, b) {
  return a + b;
}
  • A: Yes
  • B: No

답: A

순수 함수는 항상 같은 결과를 반환하는 함수예요, 만약 같은 인수가 전달 된다면 말이죠.

sum 함수는 항상 같은 결과를 반환해요. 만약 12를 전달하면, 부작용 없이 항상 3을 반환할 거예요. 510을 전달하면, 항상 15를 반환할 거예요. 이게 순수 함수의 정의예요.


78. 무엇이 출력 될까요?
const add = () => {
  const cache = {};
  return (num) => {
    if (num in cache) {
      return `From cache! ${cache[num]}`;
    } else {
      const result = num + 10;
      cache[num] = result;
      return `Calculated! ${result}`;
    }
  };
};

const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 * 2));
  • A: Calculated! 20 Calculated! 20 Calculated! 20
  • B: Calculated! 20 From cache! 20 Calculated! 20
  • C: Calculated! 20 From cache! 20 From cache! 20
  • D: Calculated! 20 From cache! 20 Error

답: C

add함수는 memoized 함수예요. memoization 사용하면, 함수 실행 속도를 높이기 위해 함수의 결과를 캐시할 수 있어요. 이 경우, 이전에 반환된 값을 저장한 cache 객체를 만들어요.

같은 인수로 addFunction 함수를 다시 부르면, 우선 cache 안에 값을 갖고 있는지 확인해요. 만약 그렇다면, 캐시값이 반환되어 실행시간이 절약돼요. 캐시되지 않았다면, 값을 계산하고 나중에 저장해요.

같은 값으로 addFunction함수를 세 번 불러요: 첫 번째 호출 때에는, num10일 때 함수의 값은 아직 저장되지 않았어요. if문의 조건 num in cachefalse을 반환하고, else 블록이 실행돼요: Calculated! 20을 출력하고, 결과 값은 cache 객체에 추가돼요. cache는 이제 { 10: 20 } 처럼 보여요.

두 번째엔, cache객체는 10을 위해 반환될 값을 포함하고 있어요. if문의 조건 num in cachetrue를 반환하고, 'From cache! 20'이 출력돼요.

세 번째에는, 5 * 210으로 평가해 함수에 전달해요. cache 객체는 10을 위해 반환될 값을 포함하고 있어요. if문의 조건 num in cachetrue를 반환하고, 'From cache! 20'이 출력돼요.


79. 무엇이 출력 될까요?
const myLifeSummedUp = ['☕', '💻', '🍷', '🍫'];

for (let item in myLifeSummedUp) {
  console.log(item);
}

for (let item of myLifeSummedUp) {
  console.log(item);
}
  • A: 0 1 2 3 그리고 "☕" "💻" "🍷" "🍫"
  • B: "☕" "💻" "🍷" "🍫" 그리고 "☕" "💻" "🍷" "🍫"
  • C: "☕" "💻" "🍷" "🍫" 그리고 0 1 2 3
  • D: 0 1 2 3 그리고 {0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}

답: A

for-in 루프에서는, 열거 가능한 속성에 대해 반복 할 수 있어요. 배열에서, 열거 가능한 속성은 배열 요소의 "키"이고, 사실 그들의 인덱스예요. 배열은 다음과 같이 볼 수 있어요:

{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}

여기서 키는 열거 가능한 속성이에요. 0 1 2 3이 출력되요.

for-of 루프에서는, 반복 가능한 속성을 가진 요소에 대해 반복 할 수 있어요. 배열은 반복 가능해요. 배열을 반복할 때, "item" 변수는 현재 반복중인 요소와 같고, "☕" "💻" "🍷" "🍫"이 출력돼요.


80. 무엇이 출력 될까요?
const list = [1 + 2, 1 * 2, 1 / 2];
console.log(list);
  • A: ["1 + 2", "1 * 2", "1 / 2"]
  • B: ["12", 2, 0.5]
  • C: [3, 2, 0.5]
  • D: [1, 1, 1]

답: C

배열 요소은 모든 값을 가질 수 있어요. 숫자, 문자, 객체, 다른 배열, null, 불리언 값, undefined, 그리고 날짜, 함수, 연산자와 같은 표현식

요소는 반환된 값과 같아질 거예요. 1 + 23을 반환하고, 1 * 22를 반환하고, 1 / 20.5을 반환해요.


81. 무엇이 출력 될까요?
function sayHi(name) {
  return `Hi there, ${name}`;
}

console.log(sayHi());
  • A: Hi there,
  • B: Hi there, undefined
  • C: Hi there, null
  • D: ReferenceError

답: B

기본적으로, 인수는 함수에 값이 전달되지 않으면 undefined 값을 가져요. 이 경우, name 인수를 위한 값을 전달하지 않았어요. nameundefined로 출력돼요.

ES6에서, 기본값 undefined 값을 기본값 매개변수로 덮어쓸 수 있어요. 예를 들면:

function sayHi(name = "Lydia") { ... }

이 경우, 값을 전달하지 않거나 undefined를 전달하면, name은 항상 문자열 Lydia가 될 거예요.


82. 무엇이 출력 될까요?
var status = '😎';

setTimeout(() => {
  const status = '😍';

  const data = {
    status: '🥑',
    getStatus() {
      return this.status;
    },
  };

  console.log(data.getStatus());
  console.log(data.getStatus.call(this));
}, 0);
  • A: "🥑" 그리고 "😍"
  • B: "🥑" 그리고 "😎"
  • C: "😍" 그리고 "😎"
  • D: "😎" 그리고 "😎"

답: B

this키워드의 값은 사용하는 곳에 따라 달라요. getStatus메소드 같은 메소드에서 this키워드는 메소드가 속한 객체 를 참조해요. 이 메소드는 data 객체에 속해 있어, thisdata객체를 참조해요. this.status를 출력할 때, data객체의 status 속성 "🥑"이 출력돼요.

call 메소드를 사용해, this 키워드가 참조하는 객체를 바꿀 수 있어요. 함수에서, this 키워드는 함수가 속한 객체 를 참조해요. setTimeout 함수를 전역 객체 에 선언했어요, 따라서 setTimeout 함수 안에서 this키워드는 전역 객체 를 참조해요. 전역 객체에는 "😎"값을 가진 status 라는 변수가 있어요. this.status를 출력하면, "😎"이 출력돼요.


83. 무엇이 출력 될까요?
const person = {
  name: 'Lydia',
  age: 21,
};

let city = person.city;
city = 'Amsterdam';

console.log(person);
  • A: { name: "Lydia", age: 21 }
  • B: { name: "Lydia", age: 21, city: "Amsterdam" }
  • C: { name: "Lydia", age: 21, city: undefined }
  • D: "Amsterdam"

답: A

city 변수를 person 객체의 city라고 불리는 속성 값으로 설정 했어요. 이 객체에서는 city라고 불리는 속성이 없기 때문에, 변수 city는 값 undefined를 가져요.

person객체 자체를 참조 하지않는다 는 걸 참고해요! 변수 cityperson 객체의 city 속성의 현재 값으로 설정 했을 뿐이에요.

그 뒤, 우리는 city를 문자열 "Amsterdam"로 설정 했어요. 이건 person 객체를 바꾸지 않아요: 여기서 객체를 참조하는 건 없어요.

person객체를 출력할 때, 수정되지 않은 객체를 반환 받아요.


84. 무엇이 출력 될까요?
function checkAge(age) {
  if (age < 18) {
    const message = "Sorry, you're too young.";
  } else {
    const message = "Yay! You're old enough!";
  }

  return message;
}

console.log(checkAge(21));
  • A: "Sorry, you're too young."
  • B: "Yay! You're old enough!"
  • C: ReferenceError
  • D: undefined

답: C

constlet 키워드를 사용한 변수는 블록-스코프 예요. 블록은 중괄호 ({ }) 사이에 있는 모든 것이에요. 이 경우, if/else 표현식의 중괄호를 의미해요. 변수가 선언된 블록 외부에서 참조할 수 없어요, ReferenceError를 던져요.


85. 어떤 종류의 정보가 출력될까요?
fetch('https://www.website.com/api/user/1')
  .then((res) => res.json())
  .then((res) => console.log(res));
  • A: fetch 메소드의 결과
  • B: fetch 메소드의 두번째 호출 결과
  • C: 이전 .then()에서 callback된 결과
  • D: 항상 undefined

답: C

두번째 .then에서의 res의 값은 이전.then에서 반환된 값이에요. 이것 처럼 .then을 계속해서 연결할 수 있고, 값은 계속해서 다음 핸들러로 전달 돼요.


86. true를 인수로 전달 할 수 없도록 주어졌을 때, hasNametrue로 설정할 수 있는 방법은 어느 것일까요?
function getName(name) {
  const hasName = //
}
  • A: !!name
  • B: name
  • C: new Boolean(name)
  • D: name.length

답: A

!!name에서, 우리는 name의 값이 참 같은지 거짓 같은지 여부를 결정해요. 만약 시험 하려는 name이 참 같다면, !namefalse를 반환해요. !false(실제로는 !!name)는 true를 반환해요.

hasNamename으로 설정하면, hasName은 불린 값 true가 아니라, getName 함수에 전달된 값으로 설정해요.

new Boolean(true)은 불린 값 자체가 아닌, 감싼 객체를 반환해요.

name.length은 그것의 true의 여부가 아닌, 전달된 인수의 길이를 반환해요.


87. 무엇이 출력 될까요?
console.log('I want pizza'[0]);
  • A: """
  • B: "I"
  • C: SyntaxError
  • D: undefined

답: B

문자열의 특정 인덱스의 문자를 얻으려면, 대괄호 표기법을 사용하면 돼요. 문자열의 첫 번째 문자는 인덱스 0과 기타등등을 가지고 있어요. 이 경우엔 인덱스가 0이고 문자 "I'가 출력되는 요소를 갖길 원해요.

이 방법은 IE7 이하에서는 지원되지 않는다는 것을 유의하세요. 이 경우, .charAt()를 사용하세요.


88. 무엇이 출력 될까요?
function sum(num1, num2 = num1) {
  console.log(num1 + num2);
}

sum(10);
  • A: NaN
  • B: 20
  • C: ReferenceError
  • D: undefined

답: B

기본값 매개변수를 이전에 정의한 함수의 다른 매개변수로 설정 할 수 있어요. 우리는 sum 함수에 값 10을 전달했어요. 만약 sum 함수에 인수의 값을 하나만 받았다면, num2의 값은 전달되지 않았고, num1은 전달된 값 10과 같다는 의미에요. num2의 기본값은 num1의 값인 10과 같아요. num1 + num220을 반환해요.

만약 기본갑 매개변수가 정의된 (오른쪽에) 기본 파라미터의 값을 설정하려고 시도한다면, 파라미터의 값은 아직 초기화되지 않아, 오류를 던질 거에요.


89. 무엇이 출력 될까요?
// module.js
export default () => 'Hello world';
export const name = 'Lydia';

// index.js
import * as data from './module';

console.log(data);
  • A: { default: [Function (anonymous)], name: "Lydia" }
  • B: { default: [Function (anonymous)] }
  • C: { default: "Hello world", name: "Lydia" }
  • D: Global object of module.js

답: A

import * as name 신택스를 사용해, module.js 파일에 있는 모든 exportsindex.js 파일 안에 data라고 불리는 새로운 객체로 생성해요. module.js 파일에는, 2개의 export가 있어요: default export 와 named export. default export는 문자열 "Hello World"을 반환하는 함수이고, named export는 문자열 "Lydia"의 값을 가진 name이라고 불리는 변수예요.

data 객체는 default export를 위한 default 속성을 가지고, 다른 속성은 named exports의 이름과 그에 해당하는 값을 가져요.


90. 무엇이 출력 될까요?
class Person {
  constructor(name) {
    this.name = name;
  }
}

const member = new Person('John');
console.log(typeof member);
  • A: "class"
  • B: "function"
  • C: "object"
  • D: "string"

답: C

Class는 함수 생성자를 위한 문법적 설탕이에요. 함수 생성자로서 Person 클래스와 동등한 것은 다음과 같아요:

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

new와 함께 불려진 함수 생성자는 Person의 인스턴스를 생성하고, typeof 키워드는 인스턴스의 "object"를 반환해요. typeof member"object"을 반환해요.


91. 무엇이 출력 될까요?
let newList = [1, 2, 3].push(4);

console.log(newList.push(5));
  • A: [1, 2, 3, 4, 5]
  • B: [1, 2, 3, 5]
  • C: [1, 2, 3, 4]
  • D: Error

답: D

.push 메소드는 배열 자체가 아니라, 배열의 새로운 길이 를 반환해요! newList[1, 2, 3].push(4)과 동일하게 설정함으로써, newList를 배열의 새로운 길이와 동일하게 설정했어요: 4.

그리고서, .push 메소드를 newList에 사용하려고 했어요. newList는 숫자 값 4 이기 때문에, .push 메소드를 사용할 수 없어요: TypeError가 던져져요.


92. 무엇이 출력 될까요?
function giveLydiaPizza() {
  return 'Here is pizza!';
}

const giveLydiaChocolate = () =>
  "Here's chocolate... now go hit the gym already.";

console.log(giveLydiaPizza.prototype);
console.log(giveLydiaChocolate.prototype);
  • A: { constructor: ...} { constructor: ...}
  • B: {} { constructor: ...}
  • C: { constructor: ...} {}
  • D: { constructor: ...} undefined

답: D

giveLydiaPizza와 같은 일반 함수는, 생성자 속성을 가진 객체(프로토타입 객체)이고, 프로토타입 속성을 갖고 있어요. 그러나 giveLydiaChocolate 함수와 같은 화살표 함수에서는, prototype 속성을 가지고 있지 않아요. giveLydiaChocolate.prototype을 사용해 prototype 속성에 접근하려고 할 때, undefined이 반환될 거에요.


93. 무엇이 출력 될까요?
const person = {
  name: 'Lydia',
  age: 21,
};

for (const [x, y] of Object.entries(person)) {
  console.log(x, y);
}
  • A: name Lydia 그리고 age 21
  • B: ["name", "Lydia"] 그리고 ["age", 21]
  • C: ["name", "age"] 그리고 undefined
  • D: Error

답: A

Object.entries(person)은 키와 객체를 포함한 중첩 배열의 배열을 반환해요:

[ [ 'name', 'Lydia' ], [ 'age', 21 ] ]

for-of 루프를 사용해서, 배열 안에 각 요소를 반복할 수 있는데, 이 경우엔 하위 배열이에요. 하위 배열을 const [x, y]을 사용해, for-of 루프에서 즉시 분해할 수 있어요. x는 하위 배열의 첫 번째 요소와 같고, y는 하위 배열의 두 번째 요소와 같아요.

첫번째 하위요소는 [ "name", "Lydia" ]로, x"name", y"Lydia"을 출력해요. 두번째 하위요소는 [ "age", 21 ]로, x"age", y21을 출력해요.


94. 무엇이 출력 될까요?
function getItems(fruitList, ...args, favoriteFruit) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")
  • A: ["banana", "apple", "pear", "orange"]
  • B: [["banana", "apple"], "pear", "orange"]
  • C: ["banana", "apple", ["pear"], "orange"]
  • D: SyntaxError

답: D

...args은 rest 파라미터예요. rest 파라미터의 값은 모든 나머지 인수을 포함한 배열이며, 마지막 파라미터만 될 수 있어요! 지금 예시에서는, rest 파라미터는 두번째 파라미터예요. 이것은 불가능하고, syntax error를 던지게 될거에요.

function getItems(fruitList, favoriteFruit, ...args) {
  return [...fruitList, ...args, favoriteFruit];
}

getItems(['banana', 'apple'], 'pear', 'orange');

위의 예시는 동작해요. 배열 [ 'banana', 'apple', 'orange', 'pear' ]을 반환해요.


95. 무엇이 출력 될까요?
function nums(a, b) {
  if (a > b) console.log('a is bigger');
  else console.log('b is bigger');
  return;
  a + b;
}

console.log(nums(4, 2));
console.log(nums(1, 2));
  • A: a is bigger, 6 그리고 b is bigger, 3
  • B: a is bigger, undefined 그리고 b is bigger, undefined
  • C: undefined 그리고 undefined
  • D: SyntaxError

답: B

JavaScript에서, 세미콜론을 (;)을 명시적으로 포함하여 쓰지 않더라도, JavaScript 엔진은 여전히 문 뒤에 그들을 추가해요. 이것은 자동 세미콜론 삽입이라고 불려요. 예를 들어 문은 변수, 또는 throw, return, break 등과 같은 키워드가 될 수도 있어요.

여기, return문을 썼고, 다른 값 a + b새로운 줄 에 쓰였어요. 그러나, 새로운 줄이기 때문에, 엔진은 실제로 그 값이 반환되길 바라는지 알 수 없어요. 대신에, 자동적으로 return 뒤에 세미콜론을 더해요. 이것을 볼 수 있을거에요:

return;
a + b;

return 키워드 뒤에 함수가 실행되는 것이 중단되기 때문에, a + b의 의미는 도달되지 않아요. 여기서처럼, 만약 아무 값도 반환되지 않는다면 함수는 undefined를 반환해요. if/else문 뒤에는 아무것도 자동으로 삽입되지 않는다는 걸 유의해요!


96. 무엇이 출력 될까요?
class Person {
  constructor() {
    this.name = 'Lydia';
  }
}

Person = class AnotherPerson {
  constructor() {
    this.name = 'Sarah';
  }
};

const member = new Person();
console.log(member.name);
  • A: "Lydia"
  • B: "Sarah"
  • C: Error: cannot redeclare Person
  • D: SyntaxError

답: B

클래스를 다른 클래스/함수 생성자로 설정할 수 있어요. 이 경우, PersonAnotherPerson로 설정했어요. 이 생성자의 name은 Sarah예요, 따라서 새로운 Person의 인스턴스 member의 name 속성은 "Sarah"예요.


97. 무엇이 출력 될까요?
const info = {
  [Symbol('a')]: 'b',
};

console.log(info);
console.log(Object.keys(info));
  • A: {Symbol('a'): 'b'} 그리고 ["{Symbol('a')"]
  • B: {} 그리고 []
  • C: { a: "b" } 그리고 ["a"]
  • D: {Symbol('a'): 'b'} 그리고 []

답: D

심볼은 열거 불가능 해요. Object.keys 메소드는 객체의 모든 열거 가능 한 키 속성을 반환해요. 심볼은 보이지 않고, 빈 객체가 반환돼요. 객체 전체를 출력하면, 심지어 열거 불가능한 것이라도 모든 속성을 볼 수 있어요.

이것은 심볼의 많은 특성 중 하나에요: 완전히 고유한 값(예를 들어 작업중인 2개의 라이브러리를 같은 객체의 속성으로 추가하고 싶을 때, 객체의 우연한 이름 충돌을 방지해요)을 나타내는 것 외에, 이 방법으로 객체의 속성을 "숨길" 수 있어요(비록 완전히는 아닐지라도. 여전히 Object.getOwnPropertySymbols() 메소드를 사용해 심볼에 접근 할 수 있어요).


98. 무엇이 출력 될까요?
const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }

const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }

console.log(getList(list))
console.log(getUser(user))
  • A: [1, [2, 3, 4]] 그리고 undefined
  • B: [1, [2, 3, 4]] 그리고 { name: "Lydia", age: 21 }
  • C: [1, 2, 3, 4] 그리고 { name: "Lydia", age: 21 }
  • D: Error 그리고 { name: "Lydia", age: 21 }

답: A

getList함수는 배열을 인수로 받았어요. getList 함수의 괄호 사이에 있는 배열을 즉시 분해 했어요:

[x, ...y] = [1, 2, 3, 4]

rest 파라미터를 사용해 ...y에 모든 "남은" 인수을 배열에 넣었어요. 이 경우에서 남아있는 인수는 2, 3 그리고 4예요. y의 값은 배열이고, 모든 rest 파라미터를 포함하고 있어요. 이 경우 x의 값은 1이기 때문에, [x, y][1, [2, 3, 4]]로 출력돼요.

getUser 함수는 객체를 받았어요. 화살표 함수에서, 우리가 한개의 값을 반환한다면 중괄호를 사용할 필요 가 없어요. 그러나, 만약 화살표 함수에서 객체 를 반환하고 싶다면, 괄호 사이에 반환할 값을 써야해요, 그렇지 않다면 아무 값도 반환받을 수 없어요! 다음 함수에서는 객체가 반환 될 거에요:

const getUser = user => ({ name: user.name, age: user.age })

이 경우 값이 반환되는 값이 없으므로, 함수는 undefined을 반환해요.


99. 무엇이 출력 될까요?
const name = 'Lydia';

console.log(name());
  • A: SyntaxError
  • B: ReferenceError
  • C: TypeError
  • D: undefined

답: C

변수 name은 문자열을 값으로 가지고 있고, 함수가 아니에요, 따라서 호출할 수 없어요.

TypeErrors는 값이 예상된 유형이 아닐 경우 던져져요. JavaScript는 name을 호출하려고 했기 때문에 함수일거라 예상했어요. 그러나 문자열이였기 때문에, TypeError가 던져져요: name은 함수가 아니에요!

SyntaxErrors는 어떤 것을 썼을때 JavaScript에서 유효하지 않을 때 던져져요, 예를들어 returnretrun로 썼을때 말이죠. ReferenceErrors는 JavaScript가 접근하려고 하는 값의 참조를 찾을 수 없을 때 던져져요.


100. output의 값은 무엇일까요?
// 🎉✨ 이번이 내 100번째 질문이에요! ✨🎉

const output = `${[] && 'Im'}possible!
You should${'' && `n't`} see a therapist after so much JavaScript lol`;
  • A: possible! You should see a therapist after so much JavaScript lol
  • B: Impossible! You should see a therapist after so much JavaScript lol
  • C: possible! You shouldn't see a therapist after so much JavaScript lol
  • D: Impossible! You shouldn't see a therapist after so much JavaScript lol

답: B

[]은 참 같은 값이에요. && 연산자를 사용할 때, 왼쪽에 있는 값이 참 같은 값이라면 오른쪽 값은 반환될 거에요. 이 경우, 왼쪽의 값 []은 참 같은 값이에요, 따라서 'Im'은 반환될 거예요.

""은 거짓 같은 값이에요. 만약 왼쪽 값이 거짓 같은 값이라면, 반환되는 것은 없어요. n't은 반환되지 않아요.


101. 무엇이 출력 될까요?
const one = false || {} || null;
const two = null || false || '';
const three = [] || 0 || true;

console.log(one, two, three);
  • A: false null []
  • B: null "" true
  • C: {} "" []
  • D: null null true

답: C

|| 연산자를 사용하면, 첫번째로 참 같은 피연산자를 반환해요. 만약 모든 값이 거짓 같다면, 마지막 피연산자를 반환해요.

(false || {} || null): 빈 객체 {}는 진짜 같은 값이에요. 이것은 최초로(그리고 유일하게) 진짜 같은 값이라 반환돼요. one{}이에요.

(null || false || ""): 모든 피연산자는 가짜 같은 값이에요. 이것은 마지막 피연산자 ""가 반환된다는 것을 의미해요. two""이에요.

([] || 0 || ""): 빈 배열 []은 진짜 같은 값이에요. 이것은 첫번째로 진짜 같은 값이라 반환돼요. three[]이에요.


102. 무엇이 출력 될까요?
const myPromise = () => Promise.resolve('I have resolved!');

function firstFunction() {
  myPromise().then((res) => console.log(res));
  console.log('second');
}

async function secondFunction() {
  console.log(await myPromise());
  console.log('second');
}

firstFunction();
secondFunction();
  • A: I have resolved!, second 그리고 I have resolved!, second
  • B: second, I have resolved! 그리고 second, I have resolved!
  • C: I have resolved!, second 그리고 second, I have resolved!
  • D: second, I have resolved! 그리고 I have resolved!, second

답: D

promise를 사용하면, 기본적으로 이 함수를 실행하고 싶지만, 시간이 좀 걸릴 수 있어 실행 중에 잠시 미뤄둘거에요. 확실한 값이 resoloved(혹은 rejected) 되었을 때와 콜 스택이 비었을 때, 이 값을 사용하고 싶어요 라고 말해요.

async 함수 안에서 .thenawait 두 개의 키워드로 값을 얻을 수 있어요. 비록 .thenawait 모두 프라미스의 값을 얻을 수 있지만, 그들은 약간 다르게 작동해요.

firstFunction에서, (뭐랄까) myPromise 함수가 실행되는 것을 미뤘지만, 다른 코드, 이 경우엔 console.log('second')를 계속해서 실행해요. 그리고서, 함수는 콜스택이 비워져 있는 걸 본 다음 출력된 문자열 I have resolved를 resolved 해요.

secondFunction에서 await 키워드를 사용하면, 말 그대로 다음 라인으로 옮기기 전에 값이 resoloved 될 때 까지 async 함수의 실행을 중단해요.

이것은 myPromise이 값 I have resolved을 resolve 할 때 까지 기다린다는 뜻이고, 단 한 번만 발생한 뒤, 다음라인으로 이동해요: second이 출력돼요.


103. 무엇이 출력 될까요?
const set = new Set();

set.add(1);
set.add('Lydia');
set.add({ name: 'Lydia' });

for (let item of set) {
  console.log(item + 2);
}
  • A: 3, NaN, NaN
  • B: 3, 7, NaN
  • C: 3, Lydia2, [object Object]2
  • D: "12", Lydia2, [object Object]2

답: C

+ 연산자는 숫자로 나타난 값을 더하는데 사용될 뿐만 아니라, 문자열을 연결하는데 사용해요. JavaScript 엔진은 하나 이상의 값이 숫자가 아닌 것을 발견 했을 때, 숫자를 문자열로 강제로 변환해요.

첫번째 1은, 숫자로된 값이에요. 1 + 2는 숫자 3을 반환해요.

그러나, 두번째는 문자열 "Lydia"이에요. "Lydia"은 문자열이고, 2는 숫자에요: 2는 문자열로 강제 변환되어요. "Lydia"그리고 "2"이 연결되어, 문자열 "Lydia2"이 반환되요.

{ name: "Lydia" }은 객체에요. 객체가 아닌 숫자나 객체는 문자열이 아니므로, 둘다 문자화되어요. 일반 객체를 문자화 할때, "[object Object]"가 돼요. "[object Object]""2"와 연결되어 "[object Object]2"가 돼요.


104. 값은 무엇일까요?
Promise.resolve(5);
  • A: 5
  • B: Promise {<pending>: 5}
  • C: Promise {<fulfilled>: 5}
  • D: Error

답: C

promise 또는 non-promise가 아니더라도, 어떤 유형의 값이라도 Promise.resolve으로 전달 할 수 있어요. 메소드 그 자체는 resolved 값을 가진 promise를 반환해요 (<fulfilled>). 일반 함수를 전달한다면, 일반 값을 가진 resolved promise를 얻게 될거에요. 만약 promise를 전달한다면, 전달된 promise의 resolved 값과 resolved promise를 얻게 될거에요.

이 경우, 숫자 값 5를 전달했어요. 이것은 값 5를 가진 resolved promise를 반환해요.


105. 값은 무엇일까요?
function compareMembers(person1, person2 = person) {
  if (person1 !== person2) {
    console.log('Not the same!');
  } else {
    console.log('They are the same!');
  }
}

const person = { name: 'Lydia' };

compareMembers(person);
  • A: Not the same!
  • B: They are the same!
  • C: ReferenceError
  • D: SyntaxError

답: B

객체는 참조로 전달되었어요. 엄격한 동등 비교 (===)로 객체를 검사한다면, 그들의 참조를 비교할거에요.

person2의 기본 값을 person 객체로 설정 하고, person 객체를 person1의 값으로 전달 했어요.

이것은 두개의 값은 메모리의 같은 장소의 참조를 가지고 있다는 걸 의미해요, 그렇기 때문에 그들은 같아요.

else구문 안에 코드블럭이 실행되면, They are the same!을 출력해요.


106. 값은 무엇일까요?
const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
};

const colors = ['pink', 'red', 'blue'];

console.log(colorConfig.colors[1]);
  • A: true
  • B: false
  • C: undefined
  • D: TypeError

답: D

JavaScript에서, 객체의 속성에 접근하는 2가지 방법을 가지고 있어요: 괄호 표기법, 또는 점 표기법. 이 예제에서는, 괄호 표기법 (colorConfig["colors"]) 대신 점 표기법 (colorConfig.colors)을 사용 했어요.

점 표기법에서, JavaScript는 정확히 일치하는 이름을 가진 객체의 속성을 찾으려 해요. 이 예제에서 JavaScript는 colorConfig 객체의 colors라고 불리는 속성을 찾으려고 했어요. 그곳에는 colors라고 불리는 속성이 없어요, 그래서 undefined을 반환해요. 그리고 나서, [1]을 사용해서 첫번째 요소의 값에 접근하려고 했어요. undefined의 값에는 이것을 할 수 없어요, 그래서 TypeError를 던져요: Cannot read property '1' of undefined.

JavaScript 문장을 해석(또는 참조형 변수를 원시 데이터 타입으로 만들어 주도록) 해요. 괄호 표기법을 사용할때, 첫번째로 열린 괄호 [을 보고 닫힌 괄호 ]를 찾을 때 까지 계속 진행되는 것으로 보여요. 그러고 나서야, 문장을 평가할거에요. 만약 colorConfig[colors[1]]을 사용했다면, colorConfig 객체의 속성 red 의 값이 반환될 거에요.


107. 값은 무엇일까요?
console.log('❤️' === '❤️');
  • A: true
  • B: false

답: A

엔진에서, 이모티콘은 유니코드에요. 하트 이모티콘의 유니코드는 "U+2764 U+FE0F"에요. 같은 이모티콘의 유니코드는 항상 같아요, 따라서 각각 다른 두개의 같은 문자열을 비교하는 것이므로 true를 반환해요.


108. 다음 중 원본 배열을 수정하는 method는 무엇일까요?
const emojis = ['✨', '🥑', '😍'];

emojis.map((x) => x + '✨');
emojis.filter((x) => x !== '🥑');
emojis.find((x) => x !== '🥑');
emojis.reduce((acc, cur) => acc + '✨');
emojis.slice(1, 2, '✨');
emojis.splice(1, 2, '✨');
  • A: All of them
  • B: map reduce slice splice
  • C: map slice splice
  • D: splice

답: D

splice method를 사용하면, 요소를 삭제, 대체하거나 추가함으로써 원본 배열을 수정해요. 이 경우에서, 인덱스 1에서 부터 2개의 아이템을 제거했어요. ('🥑''😍'를 삭제했어요) 그리고 ✨ 이모티콘을 대신 추가했어요.

map, filter 그리고 slice 는 새로운 배열을 반환하고, find 는 요소를 반환하며, reduce 는 감소된 값을 반환해요.


109. 무엇이 출력 될까요?
const food = ['🍕', '🍫', '🥑', '🍔'];
const info = { favoriteFood: food[0] };

info.favoriteFood = '🍝';

console.log(food);
  • A: ['🍕', '🍫', '🥑', '🍔']
  • B: ['🍝', '🍫', '🥑', '🍔']
  • C: ['🍝', '🍕', '🍫', '🥑', '🍔']
  • D: ReferenceError

답: A

info 객체의 favoriteFood 속성 값을 피자 이모지 '🍕'으로 설정했어요. 문자는 원시 데이터 형이에요. JavaScript에서 원시 데이터 형은 참조로 상호 작용 하지 않아요.

JavaScript에서, 원시 데이터 형은 (객체가 아닌 모든 것) 으로 상호 작용해요. 이 경우, info 객체의 favoriteFood 속성 값을 food 배열 안의 첫 번째 요소로 설정했어요. 이 경우 ('🍕') 피자 이모지는 문자열이에요. 문자열은 원시 데이터 형이므로 값으로 상호 작용해요. (좀 더 알고싶다면 내 블로그 포스트를 참고하세요.)

그리고나서, info 객체의 favoriteFood 속성 값을 바꿨어요. favoriteFood의 값은 단지 배열의 첫 번째 요소의 값을 복사 했기 때문에 food 배열은 바뀌지 않고, food[0] 요소의 메모리 공간과 같은 참조를 갖지 않아요. food를 출력하면, 여전히 원본 배열 ['🍕', '🍫', '🥑', '🍔'] 이에요.


110. 이 메소드는 무엇을 할까요?
JSON.parse();
  • A: JSON을 JavaScript 값으로 Parses
  • B: JavaScript 객체를 JSON으로 Parses
  • C: 모든 JavaScript 값을 JSON으로 Parses
  • D: JSON을 JavaScript 객체로만 Parses

답: A

JSON.parse()메소드를 사용하면, JSON 문자열의 구문을 분석해 JavaScript 값으로 생성해요.

// 숫자를 유효한 JSON 문자열로 변환해요, 그리고 나서 JSON 문자열의 구문을 분석해 JavaScript 값으로 생성해요.
const jsonNumber = JSON.stringify(4); // '4'
JSON.parse(jsonNumber); // 4

// 배열 값을 유효한 JSON 문자열로 변환해요, 그리고 나서 JSON 문자열의 구문을 분석해 JavaScript 값으로 생성해요.
const jsonArray = JSON.stringify([1, 2, 3]); // '[1, 2, 3]'
JSON.parse(jsonArray); // [1, 2, 3]

// 객체를 유효한 JSON 문자열로 변환해요, 그리고 나서 JSON 문자열의 구문을 분석해 JavaScript 값으로 생성해요.
const jsonArray = JSON.stringify({ name: 'Lydia' }); // '{"name":"Lydia"}'
JSON.parse(jsonArray); // { name: 'Lydia' }


111. 무엇이 출력 될까요?
let name = 'Lydia';

function getName() {
  console.log(name);
  let name = 'Sarah';
}

getName();
  • A: Lydia
  • B: Sarah
  • C: undefined
  • D: ReferenceError

답: D

각 함수는 각자의 실행 컨텍스트 (또는 스코프)가 있어요. getName함수는 먼저 접근하려고 하는 변수 name가 자신의 컨텍스트(스코프) 내 포함하고 있는지 살펴봐요. 이 경우에, getName함수는 자체 name 변수를 포함해요.: let 키워드로 값이 'Sarah'인 변수 name을 선언해요.

let 키워드 (그리고 const)를 사용한 변수는 호이스팅 되지만, var와는 다르게 초기화 되지 않아요. 그들을 선언(초기화)한 줄 전에서는 접근 할 수 없어요. 이것은 "일시적 사각지대"라고 불려요. 변수를 선언하기 전에 접근하려고 한다면, JavaScript는 ReferenceError를 던져요.

getName 함수 안에 name 변수를 선언하지 않았다면, javaScript 엔진은 스코프 체인 을 살펴봤을 거예요. 외부 범위에는 값이 Lydianame이라는 변수가 있어요. 이 경우 Lydia를 출력할 거예요.

let name = 'Lydia';

function getName() {
  console.log(name);
}

getName(); // Lydia


112. 무엇이 출력 될까요?
function* generatorOne() {
  yield ['a', 'b', 'c'];
}

function* generatorTwo() {
  yield* ['a', 'b', 'c'];
}

const one = generatorOne();
const two = generatorTwo();

console.log(one.next().value);
console.log(two.next().value);
  • A: a 그리고 a
  • B: a 그리고 undefined
  • C: ['a', 'b', 'c'] 그리고 a
  • D: a 그리고 ['a', 'b', 'c']

답: C

yield 키워드를 사용해, 제너레이터 함수 안의 값을 yield 해요. yield* 키워드를 사용하면, 다른 제너레이터 함수 또는 반복 가능한 객체(예를 들면 배열)의 값을 yield 할 수 있어요.

generatorOne에서, 전체 배열 ['a', 'b', 'c']yield 키워드를 사용해 넘겨줬어요. one (one.next().value)의 next 메소드가 반환한 객체의 value속성 값은 전체 배열 ['a', 'b', 'c']과 같아요.

console.log(one.next().value); // ['a', 'b', 'c']
console.log(one.next().value); // undefined

generatorTwo에서, yield* 키워드를 사용했어요. two의 첫 번째로 넘겨진 값이 이터레이터의 첫 번째 넘겨진 값과 같다는 의미에요. 이터레이터는 배열 ['a', 'b', 'c'] 이에요. 처음으로 넘겨진 값은 a이고, 따라서 첫 번째 순서에서 two.next().value를 부르면 a를 반환해요.

console.log(two.next().value); // 'a'
console.log(two.next().value); // 'b'
console.log(two.next().value); // 'c'
console.log(two.next().value); // undefined


113. 무엇이 출력 될까요?
console.log(`${((x) => x)('I love')} to program`);
  • A: I love to program
  • B: undefined to program
  • C: ${(x => x)('I love') to program
  • D: TypeError

답: A

템플릿 리터러를 사용한 표현식은 첫번째로 평가돼요. 문자열은 표현식의 반환된 값을 포함하게 된다는 것을 의미하고, 이 경우 함수 (x => x)('I love')는 즉시 호출 돼요. 화살표 함수 x => x의 인수 값으로 I love를 전달 했어요. x'I love'이고 반환 될 거에요. 이 결과는 I love to program 이에요.


114. 무슨일이 발생할까요?
let config = {
  alert: setInterval(() => {
    console.log('Alert!');
  }, 1000),
};

config = null;
  • A: setInterval 콜백은 호출되지 않을거에요
  • B: setInterval 콜백은 한 번만 호출돼요
  • C: setInterval 콜백은 여전히 매 초마다 호출돼요
  • D: 결코 config.alert()를 호출 하지 않고, config 는 null이에요

답: C

일반적으로 객체를 null로 설정했을 때, 객체는 더 이상 참조할 객체가 없어 쓰레기 수집 되어요. 그러나, setInterval을 가진 콜백 함수는 화살표 함수 (config 객체로 감싸진) 이기 때문에, 콜백 함수는 여전히 config 객체를 참조 하고 있어요 참조가 존재하는 한, 객체는 쓰레기 수집 되지 않아요. 이것은 interval이므로, confignull 또는 delete-ing config.alert로 설정하면 interval이 쓰레기 수집되지 않아, interval은 계속 호출됩니다 메모리에서 제거하기 위해서 clearInterval(config.alert)로 지워야 합니다. 지워지지 않았기 때문에, setInterval 콜백 함수는 매 1000ms (1s)마다 계속 호출 될 거에요.


115. 어느 method가 값 'Hello world!'를 반환 할까요?
const myMap = new Map();
const myFunc = () => 'greeting';

myMap.set(myFunc, 'Hello world!');

//1
myMap.get('greeting');
//2
myMap.get(myFunc);
//3
myMap.get(() => 'greeting');
  • A: 1
  • B: 2
  • C: 2 그리고 3
  • D: 모두

답: B

키/값을 쌍으로 추가할 때 set 메소드를 사용하면, 키는 set 함수로 전달 된 첫 번째 인수의 값이 되고, 값은 set 함수로 전달된 두 번째 인수의 값이 될 거에요. 이 경우에 키는 함수 () => 'greeting'이고, 값은 'Hello world'예요. myMap은 이제 { () => 'greeting' => 'Hello world!' } 예요.

1은 틀렸어요, 키는 'greeting'가 아니라 () => 'greeting'이기 때문이에요. 3은 틀렸어요, get메소드에 새로 생성한 함수를 파라미터로 전달 했기 때문이에요. 객체는 참조 로 상호작용해요. 함수는 객체이기 때문에, 두 함수가 같다고 하더라도 절대로 동일하지 않아요: 메모리 안에 다른 장소의 참조를 가지고 있어요.


116. 무엇이 출력 될까요?
const person = {
  name: 'Lydia',
  age: 21,
};

const changeAge = (x = { ...person }) => (x.age += 1);
const changeAgeAndName = (x = { ...person }) => {
  x.age += 1;
  x.name = 'Sarah';
};

changeAge(person);
changeAgeAndName();

console.log(person);
  • A: {name: "Sarah", age: 22}
  • B: {name: "Sarah", age: 23}
  • C: {name: "Lydia", age: 22}
  • D: {name: "Lydia", age: 23}

답: C

changeAgechangeAgeAndName함수 모두 새롭게 만들어진 객체 { ...person }를 기본값 매개변수로 가지고 있어요. 이 객체는 person 객체의 모든 키/값의 복사본을 가지고 있어요.

첫번째로, changeAge함수를 호출 했고, 그것의 인수로 person 객체를 전달 했어요. 이 함수는 age속성의 값을 1 증가 시켜요. person은 이제 { name: "Lydia", age: 22 }예요.

그리고서, changeAgeAndName 함수를 호출 했지만, 파라미터를 전달하지 않았어요. 대신에, x의 값은 새로운 객체와 같아요: { ...person }. 새로운 객체이기 때문에, person객체의 속성의 값에 영향을 주지 않아요. person은 여전히 { name: "Lydia", age: 22 }와 같아요.


117. 다음 선택지 중 어느 것이 6을 반환 할까요?
function sumValues(x, y, z) {
  return x + y + z;
}
  • A: sumValues([...1, 2, 3])
  • B: sumValues([...[1, 2, 3]])
  • C: sumValues(...[1, 2, 3])
  • D: sumValues([1, 2, 3])

답: C

연산자 ...를 사용하면, 반복 가능한 객체를 개별요소로 spread 펼칠 수 있어요. sumValues 함수는 인수 3개를 받았어요: x, y 그리고 z. ...[1, 2, 3]sumValues 함수에 전달하면 1, 2, 3 가 될 거예요.


118. 무엇이 출력 될까요?
let num = 1;
const list = ['🥳', '🤠', '🥰', '🤪'];

console.log(list[(num += 1)]);
  • A: 🤠
  • B: 🥰
  • C: SyntaxError
  • D: ReferenceError

답: B

+= 연산자를 사용하면, num의 값을 1 씩 증가시켜요. num은 초기값 1을 가지고 있어요, 그래서 1 + 12예요.list 배열의 2번째 인덱스 아이템은 🥰 예요, console.log(list[2]) 는 🥰 을 출력해요.


119. 무엇이 출력 될까요?
const person = {
  firstName: 'Lydia',
  lastName: 'Hallie',
  pet: {
    name: 'Mara',
    breed: 'Dutch Tulip Hound',
  },
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  },
};

console.log(person.pet?.name);
console.log(person.pet?.family?.name);
console.log(person.getFullName?.());
console.log(member.getLastName?.());
  • A: undefined undefined undefined undefined
  • B: Mara undefined Lydia Hallie ReferenceError
  • C: Mara null Lydia Hallie null
  • D: null ReferenceError null ReferenceError

답: B

optional chaining 연산자 ?.를 사용하면, 더 깊이 중첩된 값이 유효한지 여부를 더는 분명하게 확인하지 않아도 돼요.undefined 또는 null 값 (nullish) 속성에 접근 하려고 할 때, 표현식을 평가하지 않고 undefined을 반환해요.

person.pet?.name: person은 속성이름 pet을 가지고 있어요: person.pet은 nullish(null 또는 undefined)가 아니에요. name이라는 속성 이름을 가지고 있어, Mara를 반환해요. person.pet?.family?.name: person은 속성이름 pet을 가지고 있어요: person.pet은 nullish가 아니에요. petnot have a property called family라는 속성이 없어요, person.pet.family은 nullish예요. 표현식은 undefined을 반환해요. person.getFullName?.(): person은 속성이름getFullName을 가지고 있어요: person.getFullName() 은 nullish기 아니고 호출 할 수 있어요, 따라서 Lydia Hallie을 반환해요. member.getLastName?.(): member은 정의되지 않았어요: member.getLastName()은 nullish예요. 표현식은 undefined을 반환해요.


120. 무엇이 출력 될까요?
const groceries = ['banana', 'apple', 'peanuts'];

if (groceries.indexOf('banana')) {
  console.log('We have to buy bananas!');
} else {
  console.log(`We don't have to buy bananas!`);
}
  • A: We have to buy bananas!
  • B: We don't have to buy bananas
  • C: undefined
  • D: 1

답: B

if문에 조건 groceries.indexOf("banana")을 전달했어요. groceries.indexOf("banana")0을 반환하고, 이건 거짓 같은 값이에요. if문의 조건이 거짓 같은 값이기 때문에, 코드는 else 블록을 실행하고, We don't have to buy bananas!이 출력돼요.


121. 무엇이 출력 될까요?
const config = {
  languages: [],
  set language(lang) {
    return this.languages.push(lang);
  },
};

console.log(config.language);
  • A: function language(lang) { this.languages.push(lang }
  • B: 0
  • C: []
  • D: undefined

답: D

language 메소드는 setter예요. Setters는 실제 값을 유지하지 않아요, 그들의 목적은 속성을 수정 하는 거예요. setter 메소드를 부르면, undefined가 반환돼요.


122. 무엇이 출력 될까요?
const name = 'Lydia Hallie';

console.log(!typeof name === 'object');
console.log(!typeof name === 'string');
  • A: false true
  • B: true false
  • C: false false
  • D: true true

답: C

typeof name"string"을 반환해요. 문자열 "string"은 진짜 같은 값이고, !typeof name은 불리언 값 false을 반환해요. false === "object" 그리고 false === "string" 둘다 false을 반환해요.

(특정한 형과 같은지(다른지) 알고 싶다면, !typeof 대신 !==을 사용 해야 해요.)


123. 무엇이 출력 될까요?
const add = (x) => (y) => (z) => {
  console.log(x, y, z);
  return x + y + z;
};

add(4)(5)(6);
  • A: 4 5 6
  • B: 6 5 4
  • C: 4 function function
  • D: undefined undefined 6

답: A

add함수는 화살표 함수를 반환하는 함수를 반환하고, 반환한 함수는 화살표 함수를 반환하고, 반환한 함수는 화살표 함수를 반환해요(아직 나와 함께인가요?). 첫 번째 함수는 값이 4인 인수 x를 받아요. 값이 5인 인수 y를 받은 두 번째 함수를 호출해요. 그리고 우리는 값이 6인 인수 z를 받은 세 번째 함수를 호출해요. 값 x, y 그리고 z를 가진 마지막 화살표 함수에 접근하려고 할 때, JS 엔진은 그에 따른 값 x 그리고 y를 찾기 위해 스코프 체인을 올라가요. 이건 4 5 6을 반환해요.


124. 무엇이 출력 될까요?
async function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield Promise.resolve(i);
  }
}

(async () => {
  const gen = range(1, 3);
  for await (const item of gen) {
    console.log(item);
  }
})();
  • A: Promise {1} Promise {2} Promise {3}
  • B: Promise {<pending>} Promise {<pending>} Promise {<pending>}
  • C: 1 2 3
  • D: undefined undefined undefined

답: C

제너레이터 함수 range은 range에 전달한 각각의 아이템에 promise를 가진 async 객체를 반환해요: Promise{1}, Promise{2}, Promise{3}. 변수 gen을 async 객체로 만들고, 그후에 for await ... of 루프를 사용해서 순환해요. 변수 item은 반환된 Promise 값 만들어요: 첫번째는 Promise{1}, 그다음은 Promise{2}, 그다음은 Promise{3}. item의 값인 프로미스를 resolved 하기 위해 기다리고, resolved 된 프로미스의 은 반환돼요: 1, 2, 그리고 3.


125. 무엇이 출력 될까요?
const myFunc = ({ x, y, z }) => {
  console.log(x, y, z);
};

myFunc(1, 2, 3);
  • A: 1 2 3
  • B: {1: 1} {2: 2} {3: 3}
  • C: { 1: undefined } undefined undefined
  • D: undefined undefined undefined

답: D

myFunc는 속성 x, y 그리고 z를 속성으로 가진 객체가 인수라고 예상해요. x, y 그리고 z의 속성을 가진 하나의 객체({x: 1, y: 2, z: 3}) 대신, 분리된 숫자 값 (1, 2, 3)을 전달했기 때문에 x, y 그리고 z는 기본값 undefined을 가져요.


126. 무엇이 출력 될까요?
function getFine(speed, amount) {
  const formattedSpeed = new Intl.NumberFormat('en-US', {
    style: 'unit',
    unit: 'mile-per-hour',
  }).format(speed);

  const formattedAmount = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
  }).format(amount);

  return `The driver drove ${formattedSpeed} and has to pay ${formattedAmount}`;
}

console.log(getFine(130, 300));
  • A: The driver drove 130 and has to pay 300
  • B: The driver drove 130 mph and has to pay $300.00
  • C: The driver drove undefined and has to pay undefined
  • D: The driver drove 130.00 and has to pay 300.00

답: B

Intl.NumberFormat 메소드를 사용하면, 숫자 값을 원하는 로케일로 만들 수 있어요. 숫자 값 130unitmile-per-hour인 로케일 en-US로 만들면, 130 mph가 돼요. 숫자 값 300currencyUSD인 로케일 en-US로 만들면 $300.00가 돼요.


127. 무엇이 출력 될까요?
const spookyItems = ['👻', '🎃', '🕸'];
({ item: spookyItems[3] } = { item: '💀' });

console.log(spookyItems);
  • A: ["👻", "🎃", "🕸"]
  • B: ["👻", "🎃", "🕸", "💀"]
  • C: ["👻", "🎃", "🕸", { item: "💀" }]
  • D: ["👻", "🎃", "🕸", "[object Object]"]

답: B

객체를 분해함으로써, 오른쪽 객체의 값을 꺼내고, 꺼낸 값은 왼쪽 객체에 같은 속성 이름의 값으로 할당 할 수 있어요. 이 경우, 값 "💀"을 spookyItems[3]에 할당했어요. 이건 spookyItems을 수정, 즉 배열에 "💀"을 추가한다는 의미예요. spookyItems을 출력하면, ["👻", "🎃", "🕸", "💀"]이 출력ㅗ대요.


128. 무엇이 출력 될까요?
const name = 'Lydia Hallie';
const age = 21;

console.log(Number.isNaN(name));
console.log(Number.isNaN(age));

console.log(isNaN(name));
console.log(isNaN(age));
  • A: true false true false
  • B: true false false false
  • C: false false true false
  • D: false true false true

답: C

Number.isNaN 메소드를 사용하면, 전달한 값이 숫자 값 그리고 NaN인지 확인 할 수 있어요. name은 숫자 값이 아니에요, 따라서 Number.isNaN(name)false을 반환해요. age는 숫자 값이지만, NaN은 아니에요, 따라서 Number.isNaN(age)false을 반환해요.

isNaN 메소드를 사용하면, 전달한 값이 숫자가 아닌지 확인할 수 있어요. name은 숫자가 아니에요, 따라서 isNaN(name)은 true를 반환해요. age은 숫자이고, 따라서 isNaN(age)false을 반환해요.


129. 무엇이 출력 될까요?
const randomValue = 21;

function getInfo() {
  console.log(typeof randomValue);
  const randomValue = 'Lydia Hallie';
}

getInfo();
  • A: "number"
  • B: "string"
  • C: undefined
  • D: ReferenceError

답: D

const 키워드를 사용해 선언된 변수는 초기화 되기 전에 참조 할 수 없어요: 이건 일시적 사각지대 라고 불려요. getInfo힘수에서, 변수 randomValue는 함수 getInfo의 스코프 안에 있어요. typeof randomValue의 값을 출력하고 싶은 줄에서, 변수 randomValue는 아직 초기화 되지 않았어요: ReferenceError가 던져져요! 변수 randomValue를 함수 getInfo안에 선언했기 때문에 엔진은 스코프 체인 아래로 내려가지 않아요.


130. 무엇이 출력 될까요?
const myPromise = Promise.resolve('Woah some cool data');

(async () => {
  try {
    console.log(await myPromise);
  } catch {
    throw new Error(`Oops didn't work`);
  } finally {
    console.log('Oh finally!');
  }
})();
  • A: Woah some cool data
  • B: Oh finally!
  • C: Woah some cool data Oh finally!
  • D: Oops didn't work Oh finally!

답: C

try 블록에서, myPromise의 awaited 값을 출력하고 있어요: "Woah some cool data". try 블록에서 오류가 없기 때문에, catch 블록 안의 코드는 실행되지 않아요. finally 블록 안의 코드는 항상 실행되고, "Oh finally!"가 출력돼요.


131. 무엇이 출력 될까요?
const emojis = ['🥑', ['✨', '✨', ['🍕', '🍕']]];

console.log(emojis.flat(1));
  • A: ['🥑', ['✨', '✨', ['🍕', '🍕']]]
  • B: ['🥑', '✨', '✨', ['🍕', '🍕']]
  • C: ['🥑', ['✨', '✨', '🍕', '🍕']]
  • D: ['🥑', '✨', '✨', '🍕', '🍕']

답: B

flat를 사용하면, 새로운 평평한 배열을 만들어요. 평평한 배열의 깊이는 전달한 값에 달려있어요. 이 경우, 값 1(기본 값)을 전달했고,, 1번째 깊이에 있는 배열만 연결된다는 뜻이에요. 이 경우에선 ['🥑'] 그리고 ['✨', '✨', ['🍕', '🍕']]. 두 배열을 연결하면 ['🥑', '✨', '✨', ['🍕', '🍕']]가 돼요.


132. 무엇이 출력 될까요?
class Counter {
  constructor() {
    this.count = 0;
  }

  increment() {
    this.count++;
  }
}

const counterOne = new Counter();
counterOne.increment();
counterOne.increment();

const counterTwo = counterOne;
counterTwo.increment();

console.log(counterOne.count);
  • A: 0
  • B: 1
  • C: 2
  • D: 3

답: D

counterOne는 클래스 Counter의 인스턴스예요. counter 클래스는 생성자 안에 속성 countincrement 메소드를 포함해요. 우선, counterOne.increment()를 사용해 increment 메소드를 두 번 호출해요. 현재, counterOne.count2예요.

그리고서, 새로운 변수 counterTwo를 만들고, counterOne과 동일하게 설정해요. 객체는 참조로 상호작용 하므로, counterOne을 가리키는 같은 메모리 영역에 새로운 참조를 만들었어요. 메모리의 같은 장소에 존재 하므로, 참조를 가진 counterTwo 객체의 모든 변화는, counterOne 객체에도 적용돼요. 지금, counterTwo.count2예요.

count3으로 만드는 counterTwo.increment()를 호출해요. 그리고서, counterOne의 count를 출력하고, 3이 출력돼요.


133. 무엇이 출력 될까요?
const myPromise = Promise.resolve(Promise.resolve('Promise!'));

function funcOne() {
  myPromise.then((res) => res).then((res) => console.log(res));
  setTimeout(() => console.log('Timeout!'), 0);
  console.log('Last line!');
}

async function funcTwo() {
  const res = await myPromise;
  console.log(await res);
  setTimeout(() => console.log('Timeout!'), 0);
  console.log('Last line!');
}

funcOne();
funcTwo();
  • A: Promise! Last line! Promise! Last line! Last line! Promise!
  • B: Last line! Timeout! Promise! Last line! Timeout! Promise!
  • C: Promise! Last line! Last line! Promise! Timeout! Timeout!
  • D: Last line! Promise! Promise! Last line! Timeout! Timeout!

답: D

우선, funcOne를 호출했어요. funcOne의 첫 번째 줄에서, 비동기 작업 myPromise 프로미스를 불러요. 엔진이 프로미스를 처리하느라고 바쁜 와중에도, 계속해서 funcOne 함수를 실행해요. 다음 줄은 비동기 setTimeout 함수이고, 콜백을 Web API로 보내요. (내가 작성한 이벤트 루프에 대한 글 보기 여기.)

프라미스와 타임아웃 모두 비동기 작업이고, 함수는 프라미스 함수와 setTimeout 콜백을 처리하느라고 바쁜 와중에도 계속해서 실행해요. 이건 비동기 작업이 아닌 Last line!가 첫 번째로 출력된다는 걸 의미해요. 이건 funcOne 함수의 마지막 줄에 있고, 프라미스가 resolved 되어, Promise!가 출력돼요. 그러나, funcTwo()를 호출 했기 때문에, 콜 스택은 비어있지 않고, setTimeout 콜백 함수는 아직 콜 스택에 추가할 수 없어요.

funcTwo에서, 우선 myPromise 프라미스를 기다려요. await키워드를 사용해서, 프라미스가 resolved (or rejected) 될 때까지 함수의 실행을 멈췄어요. 그리고서, res의 값을 기다렸다가 출력해요. (프라미스 자체가 프라미스를 반환하기 때문에). 이건 Promise!을 출력해요.

다음 줄은 비동기 setTimeout 함수로, 콜백을 Web API로 보내요.

funcTwo의 마지막 줄에서, Last line!가 콘솔에 출력돼요. 지금, funcTwo가 콜 스택에서 제거되었기 때문에, 콜 스택은 비어있어요. 대기열에서 대기 중인 콜백은(funcOne에서의 (() => console.log("Timeout!"), 그리고 funcTwo에서의 () => console.log("Timeout!")) 호출 스택에 하나씩 추가되어요. 첫 번째 콜백은 Timeout!을 출력하고, 스택에서 제거돼요. 그리고서, 두 번째 콜백은 Timeout!을 출력하고, 스택에서 제거돼요. 이건 Last line! Promise! Promise! Last line! Timeout! Timeout!을 출력해요.


134. index.js에서 sum.js 안에 있는 sum을 호출 하려면 어떻게 해야하나요?
// sum.js
export default function sum(x) {
  return x + x;
}

// index.js
import * as sum from './sum';
  • A: sum(4)
  • B: sum.sum(4)
  • C: sum.default(4)
  • D: Default aren't imported with *, only named exports

답: C

별표 *를 사용하면, 파일에서 내보낸 모든 값(기본값과 명명된 것 모두)을 가져와요. 만약 다음 파일을 가지고 있다면:

// info.js
export const name = 'Lydia';
export const age = 21;
export default 'I love JavaScript';

// index.js
import * as info from './info';
console.log(info);

아래와 같이 출력될 거예요:

{
  default: "I love JavaScript",
  name: "Lydia",
  age: 21
}

sum을 예로 들자면, 가져온 sum의 값은 다음처럼 보인다는 의미에요:

{ default: function sum(x) { return x + x } }

sum.default을 불러 함수를 호출 할 수 있어요.


135. 무엇이 출력 될까요?
const handler = {
  set: () => console.log('Added a new property!'),
  get: () => console.log('Accessed a property!'),
};

const person = new Proxy({}, handler);

person.name = 'Lydia';
person.name;
  • A: Added a new property!
  • B: Accessed a property!
  • C: Added a new property! Accessed a property!
  • D: Nothing gets logged

답: C

Proxy 객체를 사용하면, 두번째 인수로 전달 한 객체에 사용자 지정 동작을 추가 할 수 있어요. 이 경우엔, 두 개의 속성을 가진 handler 객체를 전달 했어요: setget 속성 값을 설정 할 때마다 set은 호출되고, get은 속성 값을 얻을 (접근)때 마다 호출되어요.

첫 번째 인수는 빈 객체 {}고, person의 값이에요. 이 객체에 객체 handler의 사용자 지정 동작을 추가했어요. person 객체에 속성을 추가하면, set 이 호출 돼요. person 객체의 속성에 접근하면, get 이 호출 돼요.

우선, 프록시 객체에 새로운 속성 name을 추가했어요(person.name = "Lydia"). set이 호출되고, "Added a new property!"을 출력 해요.

그리고서, 프록시 객체의 속성 값에 접근하고, handler 객체의 속성 get 이 호출 돼요. "Accessed a property!"을 출력 해요.


136. 다음 중 어느 것이 person 객체를 수정 할 수 있을까요?
const person = { name: 'Lydia Hallie' };

Object.seal(person);
  • A: person.name = "Evan Bacon"
  • B: person.age = 21
  • C: delete person.name
  • D: Object.assign(person, { age: 21 })

답: A

Object.seal을 사용하면, 새로운 속성이 추가 되거나, 혹은 존재하는 속성이 제거 되는 것을 막을 수 있어요.

그러나, 여전히 존재하는 속성의 값을 수정 할 수 있어요.


137. 다음 중 어느 것이 person 객체를 수정 할 수 있을까요?
const person = {
  name: 'Lydia Hallie',
  address: {
    street: '100 Main St',
  },
};

Object.freeze(person);
  • A: person.name = "Evan Bacon"
  • B: delete person.address
  • C: person.address.street = "101 Main St"
  • D: person.pet = { name: "Mara" }

답: C

Object.freeze 메소드는 객체를 얼려요 . 속성을 추가, 수정, 제거 할 수 없어요.

하지만, 객체를 얕은 수준으로만 얼리고, 이건 객체의 직접적인 속성만 얼려진다는 의미예요. 속성이 address 와 같은 객체인 경우, 객체의 속성은 얼려지지 않고, 수정될 수 있어요.


138. 무엇이 출력 될까요?
const add = (x) => x + x;

function myFunc(num = 2, value = add(num)) {
  console.log(num, value);
}

myFunc();
myFunc(3);
  • A: 2 4 and 3 6
  • B: 2 NaN and 3 NaN
  • C: 2 Error and 3 6
  • D: 2 4 and 3 Error

답: A

우선, myFunc() 를 어떤 인수도 전달하지 않고 호출했어요. 인수를 전달하지 않았기 때문에, numvalue 는 그들의 기본값을 가져요: num 는 2, value 함수 add에서 반환된 값. add 함수에서, 값이 2num를 인수로 전달했어요. addvalue의 값인 4를 반환해요.

그리고서, myFunc(3)를 호출하고 인수 num의 값으로 값 3을 전달했어요. value 값은 전달하지 않았어요. 인수 value에 값을 전달하지 않았기 때문에, 기본값을 가져요: 함수 add에서 반환된 값. add에서, 값 3을 가진 num을 전달해요. addvalue의 값으로 6을 반환해요.


139. 무엇이 출력 될까요?
class Counter {
  #number = 10;

  increment() {
    this.#number++;
  }

  getNum() {
    return this.#number;
  }
}

const counter = new Counter();
counter.increment();

console.log(counter.#number);
  • A: 10
  • B: 11
  • C: undefined
  • D: SyntaxError

답: D

ES2020에서, #을 사용한 private 변수를 추가 할 수 있어요. 클래스 외부에서 private 변수에 접근 할 수 없어요. counter.#number을 출력하려고 할 때, SyntaxError가 던져져요: Counter 클래스 외부에서 private 변수에 접근 할 수 없어요!


140. 무엇이 빠졌을까요?
const teams = [
  { name: 'Team 1', members: ['Paul', 'Lisa'] },
  { name: 'Team 2', members: ['Laura', 'Tim'] },
];

function* getMembers(members) {
  for (let i = 0; i < members.length; i++) {
    yield members[i];
  }
}

function* getTeams(teams) {
  for (let i = 0; i < teams.length; i++) {
    // ✨ SOMETHING IS MISSING HERE ✨
  }
}

const obj = getTeams(teams);
obj.next(); // { value: "Paul", done: false }
obj.next(); // { value: "Lisa", done: false }
  • A: yield getMembers(teams[i].members)
  • B: yield* getMembers(teams[i].members)
  • C: return getMembers(teams[i].members)
  • D: return yield getMembers(teams[i].members)

답: B

teams 배열의 members의 각 요소를 계속해서 반복하기 위해선, teams[i].members를 제너레이터 함수 getMembers에 전달해야해요. 제너레이터 함수는 제너리에터 객체를 리턴해요. 제너레이터 객체의 각 요소를 계속해서 반복 하기 위해선, yield*를 사용해야 해요.

yield, return yield 또는 return를 쓰면, 모든 제너레이터 함수는 첫번째로 호출한 next 메소드가 반환한 값을 가져요.


141. 무엇이 출력 될까요?
const person = {
  name: 'Lydia Hallie',
  hobbies: ['coding'],
};

function addHobby(hobby, hobbies = person.hobbies) {
  hobbies.push(hobby);
  return hobbies;
}

addHobby('running', []);
addHobby('dancing');
addHobby('baking', person.hobbies);

console.log(person.hobbies);
  • A: ["coding"]
  • B: ["coding", "dancing"]
  • C: ["coding", "dancing", "baking"]
  • D: ["coding", "running", "dancing", "baking"]

답: C

addHobby 함수는 인수 두 개 hobbyperson 객체의 배열 hobbies의 값을 기본값으로 가진 hobbies를 받아요.

우선, addHobby 함수를 호출하고, hobby의 값으로 "running"을 그리고 hobbies의 값으로 빈 배열을 전달해요. hobbies의 값으로 빈 배열을 전달했기 때문에, "running"은 빈 배열에 추가돼요.

그리고서, addHobby 함수를 호출하고, hobby의 값으로 "dancing"를 전달해요. hobbies에 값을 전달하지 않았고, person 객체의 속성 hobbies을 기본값으로 가져요. 배열 person.hobbiesdancing를 추가해요.

마지막으로, addHobby 함수를 호출해, hobby의 값으로 "baking"를 전달하고, hobbies의 값으로 배열 person.hobbies을 전달해요. 배열 person.hobbiesbaking을 추가해요.

dancingbaking을 추가한 후, person.hobbies의 값은 ["coding", "dancing", "baking"]예요.


142. 무엇이 출력 될까요?
class Bird {
  constructor() {
    console.log("I'm a bird. 🦢");
  }
}

class Flamingo extends Bird {
  constructor() {
    console.log("I'm pink. 🌸");
    super();
  }
}

const pet = new Flamingo();
  • A: I'm pink. 🌸
  • B: I'm pink. 🌸 I'm a bird. 🦢
  • C: I'm a bird. 🦢 I'm pink. 🌸
  • D: Nothing, we didn't call any method

답: B

Flamingo 클래스의 인스턴스인 변수 pet 생성했어요. 인스턴스를 인스턴스화 할 때, Flamingoconstructor를 불러요. 우선, "I'm pink. 🌸"가 출력되고, 그 후에 super()를 불러요. super()는 부모 클래스 Bird의 constructor를 불러요. Bird의 constructor 를 불러, "I'm a bird. 🦢"가 출력돼요.


143. 다음 중 어느 것의 결과가 오류일까요?
const emojis = ['🎄', '🎅🏼', '🎁', '⭐'];

/* 1 */ emojis.push('🦌');
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, '🥂'];
/* 4 */ emojis.length = 0;
  • A: 1
  • B: 1 and 2
  • C: 3 and 4
  • D: 3

답: D

const 키워드는 단순히 변수의 값을 재선언 할 수 없고, 읽기만 가능하다는 의미예요. 하지만, 값 자체가 불변하는 건 아니에요. 배열 emojis의 속성을 수정할 수 있는데, 예를 들자면 새로운 값을 추가하거나, 원본 배열 자체를 수정(splice)하거나, 배열의 길이를 0으로 설정 할 수 있어요.


144. person에 무엇을 추가해야 [...person]의 결과로 ["Lydia Hallie", 21]를 얻을 수 있을까요?
const person = {
  name: "Lydia Hallie",
  age: 21
}

[...person] // ["Lydia Hallie", 21]
  • A: 객체는 기본적으로 반복 가능 하므로, 아무것도 하지 않아요.
  • B: *[Symbol.iterator]() { for (let x in this) yield* this[x] }
  • C: *[Symbol.iterator]() { yield* Object.values(this) }
  • D: *[Symbol.iterator]() { for (let x in this) yield this }

답: C

객체는 기본적으로 반복 불가능해요. 반복 가능한 객체는 iterator protocol이 제공되면 반복 가능해요. 제너레이터 함수 *[Symbol.iterator]() {}을 만드는 제너레이터 객체를 반환하는 iterator symbol [Symbol.iterator]을 수동으로 추가 할 수 있어요. 배열 ["Lydia Hallie", 21]을 반환 하려면 제너레이터 함수는 person 객체의 Object.values를 yield 해야해요: yield* Object.values(this).


145. 무엇이 출력 될까요?
let count = 0;
const nums = [0, 1, 2, 3];

nums.forEach((num) => {
  if (num) count += 1;
});

console.log(count);
  • A: 1
  • B: 2
  • C: 3
  • D: 4

답: C

forEach 순환에 포함 된 if 조건문은 num의 값이 진짜 같은 값인지 또는 가짜 같은 값인지 확인해요. nums배열의 첫 번째 값은 거짓 같은 값 0이고, if 조건문의 코드 블럭은 실행되지 않아요. count 는 오직 nums 배열의 다른 숫자 3개에 대해서만 증가해요. 1, 2 그리고 3. count는 3번 동안 1 씩 증가하고, count의 값은 3이에요.


146. 무엇이 출력 될까요?
function getFruit(fruits) {
  console.log(fruits?.[1]?.[1]);
}

getFruit([['🍊', '🍌'], ['🍍']]);
getFruit();
getFruit([['🍍'], ['🍊', '🍌']]);
  • A: null, undefined, 🍌
  • B: [], null, 🍌
  • C: [], [], 🍌
  • D: undefined, undefined, 🍌

답: D

?는 객체 내에서 더 깊이 중첩된 속성에 접근하는 것을 선택적으로 허용해요. fruits배열의 인덱스 1에 있는 하위 배열의 인덱스 1의 아이템을 출력하려해요. fruits배열의 인덱스 1에 하위 배열이 존재하지 않는다면, 간단히 undefined를 반환할 거예요. fruits 배열의 인덱스 1에 하위배열이 있지만, 하위 배열에 인덱스 1 의 아이템이 없다면, 그것 역시 undefined를 반환해요.

우선, [['🍊', '🍌'], ['🍍']]의 하위 배열의 두 번째 아이템 ['🍍']을 출력해요 . 하위 배열은 아이템 하나만 가지고 있고, 이건 인덱스 1에 대한 아이템을 갖고 있지 않다는 의미로 undefined를 반환해요.

그리고서, 인수에 어떤 값도 전달하지 않은 getFruits 함수를 호출 하고, fruits은 기본값으로 값 undefined을 가져요. fruits의 인덱스 1의 아이템을 선택적으로 연결(conditionally chaining)하기 때문에, 인덱스 1에 아이템이 존재하지 않아 undefined를 반환해요.

마지막으로, ['🍍'], ['🍊', '🍌']의 하위 배열 ['🍊', '🍌']의 두번째 아이템을 출력하려고 해요. 하위 배열의 인덱스 1의 아이템인 🍌이 출력돼요.


147. 무엇이 출력 될까요?
class Calc {
	constructor() {
		this.count = 0 
	}

	increase() {
		this.count++
	}
}

const calc = new Calc()
new Calc().increase()

console.log(calc.count)
  • A: 0
  • B: 1
  • C: undefined
  • D: ReferenceError

답: A

변수 calcCalc 클래스의 새로운 인스턴스로 설정 했어요. 그리고서, 새로운 인스턴스 Calc를 인스턴스화 하고, 이 인스턴스의 increase 메소드를 호출 했어요. 속성 count은 Calc 클래스의 생성자 안에 있기 때문에 , 속성 count은 Calc의 프로토타입에 공유될 수 없어요. 인스턴스 calc이 가리키는 count의 값은 업데이트 되지 않고, count는 여전히 0예요.


148. 무엇이 출력 될까요?
const user = {
	email: "e@mail.com",
	password: "12345"
}

const updateUser = ({ email, password }) => {
	if (email) {
		Object.assign(user, { email })
	}

	if (password) {
		user.password = password
	}

	return user
}

const updatedUser = updateUser({ email: "new@email.com" })

console.log(updatedUser === user)
  • A: false
  • B: true
  • C: TypeError
  • D: ReferenceError

답: B

updateUser 함수는 값이 전달 되면 user의 속성 emailpassword의 값을 업데이트 하고, user객체를 반환해요. updateUser 함수의 반환된 값은 객체 user 이고, updateUser의 값은 user가 가리키는 user 객체의 참조와 같다는 의미예요. updatedUser === usertrue예요.


149. 무엇이 출력 될까요?
const fruit = ['🍌', '🍊', '🍎']

fruit.slice(0, 1)
fruit.splice(0, 1)
fruit.unshift('🍇')

console.log(fruit)
  • A: ['🍌', '🍊', '🍎']
  • B: ['🍊', '🍎']
  • C: ['🍇', '🍊', '🍎']
  • D: ['🍇', '🍌', '🍊', '🍎']

답: C

우선, fruit 배열에 slice 메소드를 호출해요. slice 메소드는 원본 배열을 수정하지 않지만, 배열에서 잘라낸(slice) 값을 반환해요: 바나나 이모지. 그리고서, fruit 배열에 splice 메소드를 호출해요. splice 메소드는 원본 배열을 수정하고, 이제 fruit 배열은 ['🍊', '🍎']로 구성돼요. 마지막엔, fruit 배열에 unshift 메소드를 호출하고, 이 경우엔 제공된 값 ‘🍇’을 배열의 첫 번째 요소로 추가해 원본 배열을 수정해요. 이제 fruit 배열은 ['🍇', '🍊', '🍎']로 구성돼요.


150. 무엇이 출력 될까요?
const animals = {};
let dog = { emoji: '🐶' }
let cat = { emoji: '🐈' }

animals[dog] = { ...dog, name: "Mara" }
animals[cat] = { ...cat, name: "Sara" }

console.log(animals[dog])
  • A: { emoji: "🐶", name: "Mara" }
  • B: { emoji: "🐈", name: "Sara" }
  • C: undefined
  • D: ReferenceError

답: B

객체의 키는 문자열로 변환돼요.

dog의 값은 객체 이므로, 사실 animals[dog]는 새로운 객체에 "object Object"라고 불리는 새로운 속성을 만든 걸 의미해요. 이제 animals["object Object"]{ emoji: "🐶", name: "Mara"}예요.

cat도 물론 객체고, 사실 animals[cat]animals[``"``object Object``"``]을 새로운 속성 cat으로 덮어쓰고 있다는 것을 의미해요.

animals[dog] 또는 animals["object Object"](dog 객체를 문자열로 변환한 결과는 "object Object")를 출력하면, { emoji: "🐈", name: "Sara" }를 반환해요.


151. 무엇이 출력 될까요?
const user = {
	email: "my@email.com",
	updateEmail: email => {
		this.email = email
	}
}

user.updateEmail("new@email.com")
console.log(user.email)
  • A: my@email.com
  • B: new@email.com
  • C: undefined
  • D: ReferenceError

답: A

updateEmail함수는 화살표 함수로, user객체에 바인딩 되지 않았어요. this키워드는 user객체를 참조하지 않지만, 이 경우엔 전역 범위를 참조하고 있다는 의미예요. user 객체의 email 는 업데이트 되지 않아요. user.email을 출력할 때, my@email.com의 원래의 값이 반환되어요.


152. 무엇이 출력 될까요?
const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')

const runPromises = async () => {
	const res1 = await Promise.all([promise1, promise2])
	const res2  = await Promise.all([promise3, promise4])
	return [res1, res2]
}

runPromises()
	.then(res => console.log(res))
	.catch(err => console.log(err))
  • A: [['First', 'Second'], ['Fourth']]
  • B: [['First', 'Second'], ['Third', 'Fourth']]
  • C: [['First', 'Second']]
  • D: 'Third'

답: D

Promise.all 메소드는 프로미스를 병렬로 실행해요. 만약 하나의 프로미스가 실패하면, Promise.all 메소드는 rejected 프로미스의 값을 가지고 rejects 되어요. 이 경우, promise3는 값 "Third"과 함께 rejected 되었어요. runPromises 호출에 연결되어 있고 runPromises 함수 안에서 모든 에러를 잡은 catch 메소드에서 rejected 값을 잡아요. promise3가 이 값과 함께 rejected 되어 "Third"만 출력돼요.


153. 무엇이 method의 값이어야 { name: "Lydia", age: 22 }를 출력할까요?
const keys = ["name", "age"]
const values = ["Lydia", 22]

const method = /* ?? */
Object[method](keys.map((_, i) => {
	return [keys[i], values[i]]
})) // { name: "Lydia", age: 22 }
  • A: entries
  • B: values
  • C: fromEntries
  • D: forEach

답: C

fromEntries 메소드는 2차원 배열을 객체로 변환해요. 각 하위 배열의 첫번 째 요소는 키가 될거고, 각 하위 배열의 요소의 두번째 요소는 값이 될거에요. 이 경우엔, keys배열에서 현재 인덱스의 아이템을 첫 번재 요소로, values의 배열에서 현재 인덱스의 아이템을 두번째 요소로 반환하는 keys 배열을 매핑해요.

키와 값의 집합을 포함하고 있는 하위 배열을 만들었고, { name: "Lydia", age: 22 }가 되어.


154. 무엇이 출력 될까요?
const createMember = ({ email, address = {}}) => {
	const validEmail = /.+\@.+\..+/.test(email)
	if (!validEmail) throw new Error("Valid email pls")

	return {
		email,
		address: address ? address : null
	}
}

const member = createMember({ email: "my@email.com" })
console.log(member)
  • A: { email: "my@email.com", address: null }
  • B: { email: "my@email.com" }
  • C: { email: "my@email.com", address: {} }
  • D: { email: "my@email.com", address: undefined }

답: C

address의 기본 값은 빈 객체 {}예요. 변수 member의 값을 createMember 함수에서 반환한 값으로 설정하고, address의 값을 전달하지 않았어요, address의 값은 빈 객체 {}가 기본 값이예요. 빈객체는 진짜 같은 값으로, 조건 address ? address : null에서 true를 반환한다는 의미예요. address의 값은 빈 객체 {}예요.


155. 무엇이 출력 될까요?
let randomValue = { name: "Lydia" }
randomValue = 23

if (!typeof randomValue === "string") {
	console.log("It's not a string!")
} else {
	console.log("Yay it's a string!")
}
  • A: It's not a string!
  • B: Yay it's a string!
  • C: TypeError
  • D: undefined

답: B

if문 안에 조건은 !typeof randomValue값이 "string"와 같은지 여부를 확인해요. ! 연산자는 값을 불리언 값으로 변환해요. 값이 진짜 같은 값이라면 반환될 값은 false가 될 거고, 만약 값이 가짜 같은 값이라면 반환될 값은 true가 될 거예요. 이 경우에서, typeof randomValue의 반환된 값은 진짜 같은 값인 "number"이고, !typeof randomValue의 값은 불리언 값 false라는 의미예요.

!typeof randomValue === "string"은 실제로 false === "string"을 확인하기 때문에 항상 false를 반환해요. 조건은 false을 반환 하므로, else문의 코드 블록이 실행되어 Yay it's a string!가 출력돼요.