Skip to content

Latest commit

 

History

History
1713 lines (1132 loc) · 47.8 KB

README-ja_JA.md

File metadata and controls

1713 lines (1132 loc) · 47.8 KB

JavaScript (高度な) 問題集

私は毎日、JavaScriptに関する選択問題を Instagramに投稿していますが、ここにも投稿します。

初級から上級まで: JavaScriptの知識のテストを行ったり、知識を少し深めたり、コーディング面接の準備をしてください。:muscle: :rocket: 私はこのレポを毎週新しい質問で更新します。

答えは質問の下の折りたたまれたセクションにあります、クリックすればそれを広げられます。幸運を祈ります。:heart:

中文版本
Русский
Western Balkan
Deutsch
Tiếng Việt
日本語


1. 何が出力されるでしょうか?
function sayHi() {
  console.log(name);
  console.log(age);
  var name = "Lydia";
  let age = 21;
}

sayHi();
  • A: Lydiaundefined
  • B: LydiaReferenceError
  • C: ReferenceError21
  • D: undefinedReferenceError
答え

答え: D

関数内で、まず varキーワードを使って name変数を宣言します。これは、変数が定義されている行に実際に到達するまで、変数がデフォルト値の undefinedで初期化される(作成時にメモリ空間が設定される)ことを意味します。

name変数をログ出力を実行している行では、まだ変数を定義していませんので、undefinedの値を保持しています。

letキーワード(またはconst)を持つ変数は持ち上げられますが、 varとは異なり、初期化されません。それらを宣言(初期化)する行の前にはアクセスできません。これは"temporal dead zone"と呼ばれます。

宣言される前に変数にアクセスしようとすると、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 20 1 2
  • B: 0 1 23 3 3
  • C: 3 3 30 1 2
答え

答え: C

JavaScriptのイベントキューのため、setTimeoutコールバック関数はループが実行された後に呼び出されます。最初のループの変数 ivarキーワードを使って宣言されているので、この値はグローバル変数となります。ループの間、単項演算子 ++を使用して、毎回 iの値を1ずつインクリメントしました。 最初の例では setTimeoutコールバック関数が呼び出されるまでにi3となりました。

2番目のループでは、変数 iletキーワードを使って宣言されました。 let(またはconst)キーワードで宣言された変数はブロックスコープです(ブロックは {}の間のものです)。それぞれの繰り返しの間、 iは新しい値を持ち、それぞれの値はループの内側にあります。


3. 何が出力されるでしょうか?
const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius
};

shape.diameter();
shape.perimeter();
  • A: 2062.83185307179586
  • B: 20NaN
  • C: 2063
  • D: NaN63
答え

答え: B

diameterの値は正則関数であり、perimeterの値はアロー関数です。

アロー関数では、thisキーワードは通常の関数とは異なり、現在の周囲の範囲を参照します。これは、perimeter関数を呼ぶと、shapeオブジェクトではなく、その周囲の範囲(例えば window)を参照することを意味します。

そのオブジェクトにはradiusという値はなく、undefinedを返します。


4. 何が出力されるでしょうか?
+true;
!"Lydia";
  • A: 1false
  • B: falseNaN
  • C: falsefalse
答え

答え: A

単項プラスは、オペランドを数値に変換しようとします。true1false0です

文字列「Lydia」は truthy valueです。ここで求めているのは、「このtruthy valueは、falsyなのか」ということです。これは falseを返します。


5. 正解はどれでしょう?
const bird = {
  size: "small"
};

const mouse = {
  name: "Mickey",
  small: true
};
  • A: mouse.bird.size is not valid
  • B: mouse[bird.size] is not valid
  • C: mouse[bird["size"]] is not valid
  • D: これらすべて有効です
答え

答え: A

JavaScriptでは、すべてのオブジェクトキーは文字列です(Symbolでない限り)。たとえそれを文字列として入力していなくても、それらは常にフードの下で文字列に変換されます。

JavaScriptは、ステートメントを解釈(または、ボックス解除)します。大括弧表記を使用すると、最初の左大括弧 [を見て、右大括弧 ]が見つかるまで進みます。その時だけ、そのステートメントを評価します。

mouse [bird.size]: まず最初に、bird.sizeが評価されます。これは文字列の "small"となります。 mouse["small"]は、trueを返します。

しかし、ドット表記では、これは起こりません。 mousebirdと呼ばれるキーを持っていません。 つまりmouse.birdundefinedとなります。

また、ドット表記を使って sizeを求めます: mouse.bird.size。 mouse.birdは未定義なので、実際には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に代入します。

1つのオブジェクトを変更すると、それらすべてが変更されます。


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" });
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

グローバルオブジェクトに、空のオブジェクトを作成したばかりなので、オブジェクトはログ出力されます。greetinggreetignと誤って入力した場合、JSインタプリタは実際にこれを global.greetign = {}(またはブラウザの window.greetign = {})と見なします。

これを避けるために、"use strict"を使用する事ができます。これにより、変数を何かに設定する前に、変数宣言したことを確認できます。


10. これを行うと、どうなりますか?
function bark() {
  console.log("Woof!");
}

bark.animal = "dog";
  • A: 何も起こらない、これは全く問題ない!
  • B: SyntaxError. この方法で関数にプロパティを追加することはできません。
  • C: undefined
  • 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

通常のオブジェクトのようにコンストラクタにプロパティを追加することはできません。一度にすべてのオブジェクトに機能を追加したい場合は、代わりにプロトタイプを使用する必要があります。だからこの場合は、

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

で、member.getFullName()が、機能するはずです。これはなぜ有益なのでしょうか。例えば、このメソッドをコンストラクタ自体に追加したとします。すべてのPersonインスタンスがこのメソッドを必要としなかったのかもしれません。

その場合、多くのメモリスペースを浪費する事でしょう。なぜならそれらはまだその特性を持ち、それは各インスタンスのためにメモリスペースを消費するからです。

その代わりに、プロトタイプに追加するだけであれば、メモリ内の1箇所に配置するだけで、すべてのユーザーがアクセスできます。


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を使用した場合、作成した新しい空のオブジェクトを参照します。しかし、newを追加しなければ、それはグローバルオブジェクトを参照することとなります。

this.firstName"Sarah"を代入、this.lastName"Smith"を代入したつもりでしたが、実際に行った事は、global.firstName = 'Sarah' と、global.lastName = 'Smith'を定義したのです。

sarah自体は undefinedのままです。


13. イベント伝播の3つの段階はどれですか?
  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling
答え

答え: D

captureフェーズの間、イベントは先祖の要素を通過してターゲットの要素になります。それからtarget要素に達した後、バブリングが開始されます。


14. すべてのオブジェクトはプロトタイプを持っています。
  • A: true
  • B: false
答え

答え: B

基本オブジェクトを除き、すべてのオブジェクトにプロトタイプがあります。ベースオブジェクトは.toStringのようないくつかのメソッドとプロパティにアクセスできます。

これが、組み込みのJavaScriptメソッドを使用できる理由です。このような方法はすべてプロトタイプで利用できます。

JavaScriptはそれをあなたのオブジェクト上で直接見つけることはできませんが、プロトタイプチェーンをたどり、見つけます。


15. 何が出力されるでしょうか?
function sum(a, b) {
  return a + b;
}

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

答え: C

JavaScriptは、動的に型付けされた言語です。: 特定の変数がどんな型であるかは指定しません。知らないうちに、値が自動的に別の型に変換されることがあります。この事をimplicit type coercionと呼ばれてます。 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.値を増やす(数値は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は、オブジェクトがメモリ内の同じ場所への参照を持っているかどうかを確認します。

比較している2つのオブジェクトにはそれがありません。パラメータとして渡したオブジェクトが、等価性を確認するために使用したオブジェクトとは異なるメモリ内の場所を参照しています。

これが { 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

スプレッド演算子(... 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"を使っているので参照エラーになります。

"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キーワードを使うと、同じ名前で複数の変数を宣言できます。変数は最新の値を保持します。

ブロックスコープのletconstでは、できません。


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

すべてのオブジェクトキー(Symbolsを除く)は、文字列として自分で入力しなくても、内部では文字列です。これが、obj.hasOwnProperty('1')も​​trueを返す理由です。

setではそうはいきません。上記のsetには'1' はありません: set.has('1')は、falseを返します。数値型1set.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

同じ名前のキーが2つある場合、最初の位置にあるキーは置き換えられ、最後に指定された値になります。


26. JavaScriptのglobal execution contextは、2つを作成します。: それはグローバルオブジェクトと "this"キーワードです。
  • A: true
  • B: false
  • C: 場合によりけり
答え

答え: A

基本的なexecution contextは、グローバルな実行コンテキストです。それはあなたのコードの至る所でアクセス可能なものです。


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";

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のキーとして、値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と呼ばれるものもあるからです。WebAPIは最初にsetTimeout関数を与えてくれます。例えばDOMです。

callbackがWebAPIにプッシュされた後、setTimeout関数自体(コールバックではありません!)がスタックからポップされます。

今、fooが呼び出され、"First"が、ログ出力されています。

fooがスタックからポップされ、bazが呼び出されます。"Third"が、ログ出力されます。

WebAPIは、準備が整ったときにスタックに、なにかを追加することはできません。代わりに、コールバック関数をqueueと呼ばれるものにプッシュします。

event loopが機能し始めるところです。 event loopはスタックとタスクキューを調べます。スタックが空の場合は、キューの最初のものを取り出し、それをスタックにプッシュします。

barが呼び出され、"Second"がログ出力され、スタックからポップされます。


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をクリックすると、pdivの2つのログが表示されます。イベント伝播中は、キャプチャ、ターゲット、バブリングの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)();
}

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. これらの値のどれがfalsyですか?
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: これらすべてfalsy
答え

答え: A

falsyの値は6つだけです。

  • undefined
  • null
  • NaN
  • 0
  • '' (empty string)
  • false

new Numberや、new Booleanのような関数コンストラクタはtruthyです。


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]

実行場所によって異なります(browser、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は未定義、yは2です。 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がラッパークラスの1つ、すなわちStringを使ってオブジェクトを暗黙的にラップし、式が評価された後ラッパーを直ちに破棄するためです。

nullundefinedを除くすべてのプリミティブはこの振る舞いをします。


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はfalsyです。!nulltrueを返します。!truefalseを返します。

""はfalsyです。!""trueを返します。!truefalseを返します。

1はtruthyです。!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

文字列はイテラブルです。スプレッド演算子は、イテラブルのすべての文字を1つの要素にマッピングします。

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 and 10, 20
答え

答え: C

通常の関数は、呼び出し後に途中で停止することはできません。ただし、ジェネレータ関数は途中で"停止"し、後で停止した場所から続行することができます。

ジェネレータ関数がyieldキーワードを見つけるたびに、その関数はその後に指定された値を返します。その場合のジェネレータ関数は、値を"返す"わけではないことに注意してください。値を生み出しています。

まず、i10を指定してジェネレータ関数を初期化します。次にnext()メソッドを使用してジェネレータ関数を呼び出します。

最初にジェネレータ関数を呼び出すと、i10になり、最初のyieldキーワードに遭遇します。そこからiの値が得られます。ジェネレータは"一時停止"され、10がログ出力されます。

それから、next()メソッドを使って関数を再度呼び出します。依然としてi10のまま、以前に停止したところから継続し始めます。

それから次の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メソッドに渡した時、"resolves/rejects"は、"最初"のプロミスの"resolves/rejects"を行います。

setTimeoutメソッドには、タイマーを渡します: 最初のプロミスには500ms(firstPromise)、2番目のプロミスには100ms(secondPromise)。

これは、secondPromiseが最初に'two'の値で解決されることを意味します。res'two'の値を保持するようになり、ログ出力されます。


46. 何が出力されるでしょうか?
let person = { name: "Lydia" };
const members = [person];
person = null;

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

答え: D

まず、nameプロパティを持つオブジェクトの値を使って、変数personを宣言します。

それから、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ループを使うと、オブジェクトキーであるnameageの繰り返し処理できます。内部的には、オブジェクトキーは文字列です(シンボルではない場合)。

すべてのループで、itemの値は反復している現在のキーに設定されます。まず、itemnameが代入され、ログに出力されます。その後、itemageが代入され、ログに出力されます。


48. 何が出力されるでしょうか?
console.log(3 + 4 + "5");
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"
答え

答え: B

演算子結合性は、コンパイラーが式を評価する順序(左から右または右から左)となります。これは、すべての演算子が同じ優先順位を持つ場合にのみ発生します。演算子の種類は1つだけです: +。さらに、結合性は左から右です。

3 + 4が最初に評価されます。これは数字の7になります。

7 + '5'は、強制的に"75"になります。 JavaScriptでは、数字の7を文字列に変換します。質問15を参照してください。2つの文字列を演算子の+を使って連結することができます。よって、"7" + "5"は、"75"になります。


49. numの値は何ですか?
const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN
答え

答え: C

文字列の最初の数字だけが返されます。"基数"(解析する数値の種類を指定するための2番目の引数: 基数10, 16進数, 8進数, 2進数など)に基づいて、parseIntは文字列内の文字が有効かどうかをチェックします。基数の中で有効な数字ではない文字に出会うと、構文解析を停止して次の文字を無視します。

*は、有効な数字ではありません。"7"を、10進数の7に解析するだけです。そのままnumは7の値を保持します。


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の値も変更されます。これらは両方とも同じオブジェクトへの参照を持つからです。personnameプロパティは、値の"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ステートメントを使って、カスタムエラーを作ることができます。このステートメントで、あなたは例外を投げることができます。例外は、string, number, boolean, objectのいずれかとなります。上記の場合だと、例外は文字列'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; is actually shorthand for:

y = 10;
let x = y;

y10を代入すると、実際にはグローバルオブジェクトにプロパティyが追加されます(ブラウザではwindow、nodeではglobal)。ブラウザでは、window.y10となりました。

それから、変数x10である値yで宣言します。letキーワードで宣言された変数は"ブロックスコープ"となり、宣言されたブロック内でのみ定義されます。この場合は即時関数(IIFE)となります。

typeof演算子使用時、オペランドxは定義されていません: 宣言されているブロックの外側でxにアクセスしようとしています。これはxが定義されていないことを意味します。

値が割り当てられていない、または宣言されていない値は"undefined"型となります。なのでconsole.log(typeof x)"undefined"を返します。

yに関しては、y10を代入するときにグローバル変数yを作成しました。この値は、コード内のどこからでもアクセスできます。yが定義されていて、"number"型の値を保持します。よってconsole.log(typeof y)"number"を返します。