暗記メーカー
ログイン
js2 コード品質、オブジェクト基本、データ型
  • 谷峻輔

  • 問題数 100 • 2/25/2024

    記憶度

    完璧

    15

    覚えた

    35

    うろ覚え

    0

    苦手

    0

    未解答

    0

    アカウント登録して、解答結果を保存しよう

    問題一覧

  • 1

    デバッグ時に利用できるjsコードはなにがあるか?

    debugger コマンドを使うことでもコードを停止することができます: function hello(name) { let phrase = `Hello, ${name}!`; debugger; // <-- デバッガはここで止まります say(phrase); }

  • 2

    2の部分の説明をせよ

    Call Stack – ネストされた呼び出しのチェーンを表示します。 現時点では、デバッガは hello() 呼び出しの内側におり、index.html のスクリプト(そこに関数はないので、 “anonymous” と呼ばれます)によって呼び出されました。 スタックの項目をクリックすると、デバッガは該当のコードにジャンプし、すべての変数も同様に調べられます。

  • 3

    アイコンの説明をせよ

    ステップ”: 次のコマンドを実行します, ホットキー F9. ステップオーバー”: 次のコマンドを実行しますが、関数の中には入りません, ホットキー F10 ステップイン”, ホットキー F11. “ステップ” と同じですが、非同期関数呼び出しで振る舞いが異なります setTimeoutに対応できる。 “ステップアウト”: 現在の関数の最後まで実行を継続します、ホットキー Shift+F11。 実行は現在の関数の最後の行で停止します https://ja.javascript.info/debugging-chrome

  • 4

    コンソールにログ出力するコマンドは?

    // 見るにはコンソールを開いてください for (let i = 0; i < 5; i++) { console.log("value", i); } 引数はなんこでもおけ 各オブジェクトの文字列表現が記述順で出力されます

  • 5

    文字列を複数行にまたがって宣言するには?

    // バッククォート ` を使うと、文字列を複数行に分割することができます let str = ` ECMA International's TC39 is a group of JavaScript developers, implementers, academics, and more, collaborating with the community to maintain and evolve the definition of JavaScript. `;

  • 6

    forや関数で余計なネストを増やさないためにできることは?

    continueやreturnを使う for (let i = 0; i < 10; i++) { if (cond) { ... // <- 1つネストレベルが増える } } for (let i = 0; i < 10; i++) { if (!cond) continue; ... // <- 余分なネストレベルなし } function pow(x, n) { if (n < 0) { alert("Negative 'n' not supported"); } else { let result = 1; for (let i = 0; i < n; i++) { result *= x; } return result; } } function pow(x, n) { if (n < 0) { alert("Negative 'n' not supported"); return; //ここ! } let result = 1;//ネストがへった! for (let i = 0; i < n; i++) { result *= x; } return result; }

  • 7

    オブジェクトプロパティへのアクセス方法は?

    プロパティ値へは、ドット表記を使ってアクセスすることができます。: // オブジェクトのフィールドを取得: alert( user.name ); // John ドットを使用したアクセスを使用するには、有効なプロパティ名である必要があります。具体的には、スペースが含まれていない、数値から始まっていない、特殊文字が含まれていないなどです(ただし、$ と _ は有効です)。 代わりに、任意の文字列で動作する “角括弧表記” を使います: let user = {}; // set user["likes birds"] = true; // get alert(user["likes birds"]); // true // delete delete user["likes birds"];

  • 8

    オブジェクトのプロパティ名自体に変数を用いることはできるか? 例えば入力した文字列でプロパティを生成できるか?

    できる。 オブジェクトリテラルでは、角括弧を使うことができます。それは 算出プロパティ と呼ばれます。 入社した文字列でプロパティを作成する 例: let fruit = prompt("Which fruit to buy?", "apple"); let bag = { [fruit]: 5, // プロパティ名は変数 fruit から取られます }; alert( bag.apple ); // 5 fruit="apple" の場合

  • 9

    プロパティの短縮構文とは? function makeUser(name, age) { return { name: name, age: age // ...他のプロパティ }; } let user = makeUser("John", 30); alert(user.name); // John

    name:name の代わりに、このように単に name と書くことができます: function makeUser(name, age) { return { name, // name: name と同じ age // age: age と同じ // ... }; } 同じオブジェクトで、通常のプロパティと短縮構文両方を使うこともできます: let user = { name, // name:name と同じ age: 30 };

  • 10

    オブジェクトプロパティは予約語を使用できるか?

    すでにご存知の通り、変数は “for”, “let”, “return” といった、予約語と同じものをもつことはできません。 しかし、オブジェクトプロパティではこのような制限はありません。どんな名前でも大丈夫です: // これらのプロパティはすべて問題ありません let obj = { for: 1, let: 2, return: 3 } alert( obj.for + obj.let + obj.return ); // 6 つまり、プロパティ名には制限がありません。 任意の文字列またはシンボル (後で説明する識別子の特別なタイプ) を使用することができます。

  • 11

    let obj = { 0: "test" // same as "0": "test" }; プロパティに文字列以外を指定すると どうやってアクセスできるか?

    alert( obj["0"] ); // test alert( obj[0] ); // test (同じプロパティ) 自動的に文字列に変換される。 なので 角カッコ記法でもアクセスできる。 alert( obj["0"] ); // test 例えば、0 という数値をプロパティに使用すると、文字列の "0" になります 内部でも文字列で管理される

  • 12

    プロパティの存在チェックに利用できる演算子は?

    in演算子 該当のオブジェクトに指定したキーが存在しているかどうかをチェックする演算子 let user = { name: "John", age: 30 }; alert( "age" in user ); // true, user.age は存在する alert( "blabla" in user ); // false, user.blabla は存在しない in の左側は プロパティ名 である必要があることに注意してください。通常それは引用符で囲まれた文字列です。

  • 13

    なぜ、in 演算子が存在するのでしょうか? undefined と比較するだけで十分ではないでしょうか?

    下記のような明示的にundefined を宣言するケースでは、振る舞いが異なる。 if文でチェックするケースと、in演算子を利用するケースで結果が異なり、 in演算子はプロパティが存在すると判断するのでただしい let obj = { test: undefined }; // if文を利用したらfalseとなる。 alert( obj.test ); // これは undefined, なので - このようなプロパティは存在しない? alert( "test" in obj ); // true, プロパティは存在します! 上のコードでは、プロパティ obj.test は技術的には存在します。なので、 in 演算子は正しく動いています。

  • 14

    オブジェクトのすべてのキーを見て回るための、ループの特別な形は?

    for..in let user = { name: "John", age: 30, isAdmin: true }; for(let key in user) { // keys alert( key ); // name, age, isAdmin // values for the keys alert( user[key] ); // John, 30, true }

  • 15

    オブジェクトは順序付けられますか?つまり、オブジェクトをループするとき、追加したのと同じ順序ですべてのプロパティを取得しますか?それを保証することはできるでしょうか?

    、“特別な方法で順序付けられます”: 整数値のプロパティはソートされます、それ以外は作成した順になります。以下、その詳細です。 例として、電話のコードをもつオブジェクトを考えてみましょう: let codes = { "49": "Germany", "41": "Switzerland", "44": "Great Britain", // .., "1": "USA" }; for(let code in codes) { alert(code); // 1, 41, 44, 49 } ちなみに、 文字列で定義しているが、アクセスする際も文字列に自動変換されるので、 codes[1]でもアクセスできる

  • 16

    プロパティを削除するには?

    delete文を利用 let user = {}; user.name = "John"; delete user.name;

  • 17

    let a = {}; let b = a; // 参照のコピー alert( a == b ); alert( a === b ); 答えは? let a = {}; let b = {}; // 2つの独立したオブジェクト alert( a == b ); 答えは?

    2つのオブジェクトが等しいのは、それらが同一のオブジェクトである場合のみです。 中身が同じでも同じオブジェクト(参照先が一緒)でないと必ずfalseになる! true true false

  • 18

    いくつかのオブジェクトを1つにマージしたり、クローン(浅いコピー)を作るのに使う関数は?

    destに対しsrcのプロパティをマージする。 Object.assign(dest[, src1, src2, src3...]) let user = { name: "John" }; let permissions1 = { canView: true }; let permissions2 = { canEdit: true }; // permissions1 and permissions2 のすべてのプロパティを user にコピー Object.assign(user, permissions1, permissions2); // now user = { name: "John", canView: true, canEdit: true } もし、既に同じプロパティ名のものをもっていた場合、上書きします クローンはこう ただし浅いコピー let clone = Object.assign({}, user)

  • 19

    javascriptのガベージコレクションについて説明せよ

    JavaScriptエンジンにはガベージコレクタと呼ばれるバックグラウンドプロセスがあります。それはすべてのオブジェクトを監視し、到達不可能になったオブジェクトを削除します。 // user は オブジェクトへの参照を持っています let user = { name: "John" }; user = null; ↑実体への参照をなくすと到達不可能 つまり、ガベージコレクションの対象となり、メモリ解放される。

  • 20

    ガベージコレクションの対象とするためにできることは? 2種類あげよ

    nullを代入して、参照をけす 参照している変数自体をdelete文でけす

  • 21

    let user = { sayHi: function() { alert("Hello"); } }; 上記はプロパティに関数リテラルで関数宣言をしている。 これの短縮表現は?

    let user = { sayHi() { // "sayHi: function()" と同じです alert("Hello"); } }; ただ、 実を言うと、両者の表記は完全に同一ではありません。オブジェクトの継承(後で説明します)に関して微妙な違いがあります ホームオブジェクトの設定に関する違い

  • 22

    JavaScriptにおけるthisの振る舞いは別言語と異なる振る舞いであるといわれている。 thisについて説明せよ

    this の値は、実行時にコンテキストを示す。 つまり、定義時ではなく実行時にthisの値が決まる。 オブジェクトのメソッドだけではなく、任意の関数内で使用することができる点が他言語と異なる。 このようなコードも構文エラーにはなりません: function sayHi() { alert( this.name ); } // 2つのオブジェクトで同じ関数を使う user.f = sayHi; admin.f = sayHi; ↑のドットの前が実行コンテキストである。※メソッド構文での呼び出し

  • 23

    オブジェクトなしで、thisを呼び出すとどうなるか?

    オブジェクトがなくても関数を呼び出すことができます: function sayHi() { alert(this); } sayHi(); // undefined このケースでは、 strict モードでは this は undefined になります。 非 strict モード(誰かが use strict を忘れた場合)では、このようなケースでは this の値は グローバルオブジェクト (ブラウザでは window、後ほど学びます)になります。

  • 24

    アロー関数とthisの関係性について説明せよ

    アロー関数内部にはthisをもたない。 アロー関数外部のthisと同様の振る舞いとなる。

  • 25

    ここにオブジェクトを返す makeUser 関数があります。 その ref へのアクセス結果は何でしょうか?それはなぜでしょう? function makeUser() { return { name: "John", ref: this }; }; let user = makeUser(); alert( user.ref.name ); // 結果は何?

    エラーになる。 makeUser関数にてthisを実行しているので、thisの値はundefinedを指すためエラーとなってしまう。 this実行時に関数実行ではなくメソッド実行である必要がある。 function makeUser() { return { name: "John", ref() { return this; } }; }; let user = makeUser(); alert( user.ref().name ); // John ↑これであれば、メソッド実行となるので、userオブジェクトがthisの対象となる。

  • 26

    コードの利便性を高めるために、 ladder.up(); ladder.up(); ladder.down(); ladder.showStep(); // 1 こういった操作をどのように改善できるか?

    ladder.up().up().down().showStep(); // 1 といったふうに連鎖してメソッド実行ができるとよい つまり、以下のように各メソッドに対して、thisを返せるように定義しておくとよい。 let ladder = { step: 0, up() { this.step++; return this; }, down() { this.step--; return this; }, showStep() { alert( this.step ); return this; } } こういったアプローチも覚えておくこと

  • 27

    オブジェクトを一つ作成するさいはどうするか? また同じオブジェクトを複数作成するのに利用するのはなにか?

    通常のオブジェクトリテラル、つまり {...} 構文で、1つのオブジェクトを作成できます。 複数のユーザやメニューアイテムなど、似たようなオブジェクトを多数作成する必要がある場合は コンストラクタ関数と "new" 演算子を使うことで実現できます。

  • 28

    new演算子とコンストラクタの動作を説明せよ

    コンストラクタの仕事は、必要なものをすべて this の中に書き込むことであり、this が自動的に戻り値となります。 new User(...) は次のようなことを行います: function User(name) { // this = {}; (暗黙) まず、オブジェクトを作りthisに割り当てる。 // this へプロパティを追加 this.name = name; this.isAdmin = false; // return this; (暗黙) thisを返す }

  • 29

    newキーワードの留意事項は? また、newされる関数としての目印はなにか?

    技術的にはどのような関数(this を持たないアロー関数を除く)でもコンストラクタとして使用できます。 つまり、どの関数も new で実行することができます。 また、“関数名の先頭が大文字” というのは、関数が new で実行されることを明確にするための共通の合意です。

  • 30

    再利用性を考えないが、new演算子によってオブジェクト生成したいパターンはどういうときか?

    1つの複雑なオブジェクトを作成するためのコードがたくさんある場合は、コンストラクタに色々処理がかけるので、リテラルではなく、 コンストラクタで生成する。

  • 31

    new を付けて「コンストラクタモード」で呼び出されたのか、あるいは new を付けずに「通常モード」で呼び出されたのかを知るのに利用できるコードはなにか?

    関数内でnew.targetというプロパティを使うと確認ができる。 これはコンストラクタ関数をかえす このプロパティは、 通常の呼び出しでは undefined であり、 new で呼び出された場合はその関数と等しい function User() { alert(new.target); } // new なし: User(); // undefined // new あり: new User(); // function User { ... } new の場合と、通常呼び出し両方の構文が同じように動作するようにするために使用することもできます これを利用するとコンストラクタモードならこの動き、 関数モードならこの動きみたいな感じの制御ができます

  • 32

    コンストラクタでreturnを行った時の動作はどうなるか説明せよ

    オブジェクトのreturn はそのオブジェクトを返し、それ以外のケース(プリミティブ)では this が返されます。 例えば、ここで return はオブジェクトと共に呼ばれているため、this より優先してこのオブジェクトが返されます: function BigUser() { this.name = "John"; return { name: "Godzilla" }; // <-- オブジェクトを返す } alert( new BigUser().name ); // Godzilla, オブジェクトを取得 ^^

  • 33

    変数からプロパティを複数辿って、あるプロパティにアクセスする際、 nullやundefinedがある場合は、エラーとならず、その値を返すようにしたい。 当然、アクセスできる場合はその値を返したい。 この時どうやれば実装できるか? 二通り示せ

    まず、undefinedやnullのプロパティにたいして、.でさらにアクセスしようとするとエラーとなってしまう。 下記のように、&& 演算子を使う方法もありだが、理想的ではない。 let user = {}; alert( user.address && user.address.street && user.address.street.name );//undefinedが返されて止まる。 ※処理が止まらなければ、エラーとなってしまうことを留意 つまりuser.addressで止まるのでエラーにならない。 オプショナルチェイニングを利用すると短くかける。 ?. の前の部分が undefined あるいは null であれば検査をストップし、undefined を返します。 let user = {}; alert( user?.address?.street ); // undefinedがかえされてとまる オプショナルチェイニングは、宣言済みの変数に対してのみ機能します。 つまりuserの宣言がされてないと動作しないので注意 また、エラーがでないことは悪である場合もあるので留意すること

  • 34

    存在しない可能性のある関数を呼び出す時に何が利用できるか?

    オプショナルチェイニング ?. は演算子ではなく、特別な構文構造であり、関数や括弧と一緒でも機能します。 例えば、?.() は存在しない可能性のある関数を呼び出すときに使用されます。 let userAdmin = { admin() { alert("I am admin"); } }; let userGuest = {}; userAdmin.admin?.(); // I am admin userGuest.admin?.(); // なにもしない (このようなメソッドはありません) adminが存在する場合は、通常通り関数実行 存在しない場合は、undefinedを返してなにもしない。 当然エラーではなくなることを留意すること

  • 35

    オプショナルチェイニングでは、カッコを使用してプロパティにアクセスする場合はどのようにかけるか

    ドット . の代わりに括弧 [] を使用してプロパティにアクセスしたい場合にも、?.[] 構文は機能します。前のケース同様、存在しない可能性のあるオブジェクトから安全にプロパティを読み取ることができます。 let key = "firstName"; let user1 = { firstName: "John" }; let user2 = null; alert( user1?.[key] ); // John alert( user2?.[key] ); // undefined

  • 36

    オプショナルチェイニングの制限事項は?

    ?. を使用して、読み取りと削除を安全に行うことができますが、書き込みはできません オプショナルチェイニング ?. は代入の左側では使用できません。 例: // 以下のコードは、ユーザが存在する場合に user.name を書き込もうとするものです user?.name = "John"; // エラー、動作しません // undefined = "John" と評価されるためです

  • 37

    オブジェクトのキーに利用できる型はなにか?

    文字列型かSymbol型

  • 38

    シンボルとはなにか?

    “シンボル” 値はユニークな識別子を表現します。 ちなみにプリミティブ値 // id は新しい symbol です let id = Symbol(); また、シンボルに説明を与えることもでき(シンボル名と呼びます)、デバッグ目的で便利です。 // id は "id" という説明を持つ symbol です let id = Symbol("id"); 同じ説明をもつ2つのシンボルがあります – これらは等しくありません: let id1 = Symbol("id"); let id2 = Symbol("id"); alert(id1 == id2); // false

  • 39

    Symbolの自動変換に関する留意事項をのべよ

    toStringはうごくけども、アラートで暗黙的な自動変換はされない! Symbols は文字列への自動変換はしません JavaScriptにおいて、ほとんどの値は文字列への暗黙の変換をサポートしています。例えば、任意の値で alert を呼びだすと、たいていの値は動作します。が、シンボルは特別です。それらは自動変換されません。 例えば、この alert はエラーになります: let id = Symbol("id"); alert(id); // TypeError: Cannot convert a Symbol value to a string これは、文字列とシンボルは根本的に異なるものであり、誤って別の文字列に変換してはいけないため、混乱を避けるための “言語によるガード” です。 もし本当にシンボルを表示したい場合は、このように toString() を呼ぶ必要があります: let id = Symbol("id"); alert(id.toString()); // Symbol(id), これは動作します あるいは、symbol.description プロパティを利用して、説明のみを表示します: let id = Symbol("id"); alert(id.description); // id オブジェクトのキーとして利用する場合は、descriptionの値でアクセスできる。

  • 40

    Symbolをキーとして利用するメリットはなにか?

    既存オブジェクトに対してプロパティを追加するときに、衝突が起きることを回避したり、既存のコードで利用されないように安全面を考慮することができる。 具体的には、 1.既に同名のプロパティが用意されてる場合 シンボルなら、同名でも回避できる。 2.シンボリックなプロパティはfor ..inループに参加しないので、既存コードに対して影響を与えない。 ※Object.keys()でもアクセスできない 既存オブジェクトにプロパティ追加したい時に使うとよき

  • 41

    Symbolをキーとして利用する場合のかきかたを二通り示せ

    既存オブジェクトへのシンボリックプロパティの登録 let user = { // 別のコードに属しているオブジェクト name: "John" }; // シンボル作成 let id = Symbol("id"); //シンボルをキーにプロパティを登録 user[id] = 1; alert( user[id] ); // アクセス時も symbol オブジェクトでデータにアクセスできます ちなみにdescription でアクセスする。 オブジェクトリテラルでのシンボリックプロパティの登録 let id = Symbol("id"); let user = { name: "John", [id]: 123 // 単に "id: 123" ではありません };

  • 42

    Object.assign はシンボルプロパティをコピーするか?

    コピー対象である。 let id = Symbol("id"); let user = { [id]: 123 }; let clone = Object.assign({}, user); alert( clone[id] ); // 123

  • 43

    グローバルシンボルについて説明せよ

    通常はたとえ同じ名前であったとしてもすべてのシンボルは異なります。しかし、時には同じ名前のシンボルを同じエンティティにしたいときがあります そんな時に、グローバルシンボルレジストリを利用する。 グローバルレジストリからシンボルを読み取る(ない場合は作成する)ためには、Symbol.for(key) を使います。 // グローバルレジストリから読む let id = Symbol.for("id"); // symbol が存在しない場合、作られます // 再度読み込み let idAgain = Symbol.for("id"); // 同じシンボル alert( id === idAgain ); // true レジストリ内のシンボルは グローバルシンボル と呼ばれます。コード内のどこからでもアクセス可能なアプリケーション全体のシンボルが必要な場合、これを使います。

  • 44

    グローバルシンボルで、シンボルからキー(description)を取得するには?

    Symbol.keyFor(グローバルシンボル) でキー情報(descriptionのこと)を取得する。 ローカルシンボルはsymbol.descriptionプロパティでアクセスできる。 グローバルシンボルではそれはできないっぽい? let globalSymbol = Symbol.for("name"); let localSymbol = Symbol("name"); alert( Symbol.keyFor(globalSymbol) ); // name, グローバルシンボル alert( Symbol.keyFor(localSymbol) ); // undefined, グローバルではないので alert( localSymbol.description ); // name

  • 45

    システムシンボル(ウェルノンシンボルともいう) について説明せよ

    Symbol.* としてアクセス可能なJavaScriptで使われている多くのシステムシンボルがあります。いくつかの組み込みの振る舞いを変更するためにそれらを使うことができます 例えば、Symbol.toPrimitive はオブジェクトからプリミティブへの変換を記述することができます

  • 46

    オブジェクトからすべてのシンボルで定義されたキーを取得できる関数はなにか?二つ挙げよ

    技術的には、シンボルは100%隠れる訳ではありません。全てのシンボルを取得する組み込み関数Object.getOwnPropertySymbols(obj) があります。また、シンボリックなものも含めてオブジェクトの 全ての キーを返すReflect.ownKeys(obj)と呼ばれる関数もあります。

  • 47

    オブジェクトが加算 obj1 + obj2、減算 obj1 - obj2, または alert(obj) を使って出力されるとき、なにがおきるか?

    オブジェクトはプリミティブへ自動変換され、その後演算が行われます。

  • 48

    hintとはなにか?

    以下の3種類あり、型変換が行われると、型変換対象のオブジェクトに対して、hintが渡される。 "string" "number" "default" hintを活用して型変換が行われる。

  • 49

    "string"ヒントが利用される例を二通りあげよ

    操作が alert のように文字列を期待するとき // アラート出力するとき alert(obj); // プロパティキーとしてオブジェクトを使うときも文字列に変換する anotherObj[obj] = 123;

  • 50

    "number"ヒントが利用される例をあげよ

    操作が数学のように数値を期待するとき // 明示的な変換 let num = Number(obj); // 算術 (二項演算子プラスを除く) let n = +obj; // 単項演算子プラス let delta = date1 - date2; // 大なり小なり比較 let greater = user1 > user2; <, > のような、大なり/小なり演算子もまた文字列と数字両方を扱うことができますが、これは “default” ではなく “number” を使います。これは歴史的な理由によるものです。

  • 51

    "default"ヒントが利用される例を二通りあげよ

    操作がどんな型を期待しているか “よくわからない” ようなレアケースで起こります 例えば、二項演算子 + は文字列(それらの連結)と数値(それらの加算)両方で動作するので、文字列と数値の両方の場合がありえます。なので、二項演算子が引数にオブジェクトが渡された場合、変換には "default" ヒントを使用します。 また、オブジェクトが == を使用して、文字列、数値またはシンボルと比較されるときです。これもどの変換をすべきか不明瞭なので、"default" ヒントが利用されます。 // 二項演算子 "default" ヒントを使用 let total = obj1 + obj2; // obj == 数値は "default" ヒントを使用 if (user == 1) { ... };

  • 52

    ObjectをBooleanに変換するとなにになるか?

    trueになる。 true固定なのでヒントとかはない。

  • 53

    JavaScript がオブジェクトの変換を行うためにどのような操作を行うか?

    obj[Symbol.toPrimitive](hint)メソッドが存在する場合、obj[Symbol.toPrimitive](hint) を呼び出します ない場合、hint が "string" であれば obj.toString() 、 obj.valueOf() の順番で試します。 そうでなく、hint が "number" であれば obj.valueOf() 、 obj.toString() の順番で試します。

  • 54

    オブジェクトの型変換の実装に関する留意事項は?

    すべての組み込みオブジェクトは "number" と "default" 変換は同じ方法で実装されています。そして、恐らく私たちも同じようにするべきです。 なので等価比較の場合は数値への変換が優先される 片方が文字列の場合はまた数値→文字列へ変換される また、プリミティブ型を返さないといけない。 オブジェクト型を返すと Symbol.toPrimitiveの場合はエラー、 toString あるいは valueOfの場合は無視される。

  • 55

    Symbol.toPrimitiveを利用した型変換の例を示せ

    以下はオブジェクトを型変換する際に stringであれば、`{name: "${this.name}"}` numberもしくはdefaultであれば、this.moneyを返す。 let user = { name: "John", money: 1000, // ↓は[シンボルのキー]:function(hint){}の省略記法 [Symbol.toPrimitive](hint) { alert(`hint: ${hint}`); return hint == "string" ? `{name: "${this.name}"}` : this.money; } }; // 変換動作の確認: alert(user); // hint: string -> {name: "John"} alert(+user); // hint: number -> 1000 alert(user + 500); // hint: default -> 1500 // userが数値の1000に変換された後に数値から文字列へ変換されてこうなる alert(user + “500”); // hint: default -> 1000500 1つのメソッド user[Symbol.toPrimitive] がすべての変換ケースを扱っています。

  • 56

    メソッド toString と valueOfについて説明せよ

    シンボルがない時代に行われていた型変換の古いやり方 これらのメソッドはプリミティブを返却する必要があります。オブジェクトを返す場合、無視されます(メソッドがない場合と同じ)。

  • 57

    デフォルト定義されたtoString と valueOf メソッドについてどんな動作か説明せよ

    文字列 "[object Object]" を返却する toString メソッド オブジェクト自身を返却する valueOf メソッド これはそのデモです。: let user = {name: "John"}; alert(user); // [object Object] alert(user.valueOf() === user); // true デフォルトの valueOf は、オブジェクト自体を返すため無視されます。これは歴史的な理由によるものです。したがって、存在しないものと想定できます。 未定義と同じ解釈でよい

  • 58

    toString と valueOfを利用して型変換を行う例を示せ

    let user = { name: "John", money: 1000, // hint="string" の場合 toString() { return `{name: "${this.name}"}`; }, // hint="number" or "default" の場合 valueOf() { return this.money; } }; alert(user); // toString -> {name: "John"} alert(+user); // valueOf -> 1000 alert(user + 500); // valueOf -> 1500 alert(user + “500”); // valueOf -> 1000500

  • 59

    すべてのプリミティブ変換が処理できる 最小限の実装例を示せ

    toString を実装するだけで実現できます: let user = { name: "John", toString() { return this.name; } }; alert(user); // toString -> John alert(user + 500); // toString -> John500 Symbol.toPrimitiveとvalueOf がなければ、 toString はすべてのプリミティブ変換を扱います。

  • 60

    型変換を行った結果、計算するのに正しい型でない場合はどうなるか?

    変換結果のプリミティブが正しい型ではない場合、さらに変換されます。 let obj = { // toString は他のメソッドがない場合にすべての変換を処理します。 toString() { return "2"; } }; alert(obj * 2); // 4, ToPrimitive は "2" を与えるので, 2 になります 乗算 obj * 2 は最初にオブジェクトをプリミティブに変換します(文字列の "2") "2" * 2 は 2 * 2 になります(文字列が数値に変換されます)

  • 61

    プリミティブ型について説明せよ

    プリミティブ型は 7 つあります: string, number, bigint, boolean, symbol, null, undefined プロパティやメソッドをもたないため軽い

  • 62

    javascriptでは、プリミティブに対してメソッドやプロパティを持たせるためにどのような仕組みをとっているか

    必要に応じて(使う時だけ)、追加の機能を提供する特別な “オブジェクトラッパー” が作られ、その後、破棄されます。 “オブジェクトラッパー” はプリミティブ型毎に異なり、String, Number, Boolean, Symbol と呼ばれます。従って、それらは異なるメソッドのセットを提供します。 let str = "Hello"; alert( str.toUpperCase() ); // HELLO 文字列 str はプリミティブです。なので、プロパティへアクセスした瞬間に、文字列の値を知る特別なオブジェクトが作られ、それは toUpperCase() のような便利なメソッドを持っています。 メソッドは実行され、新たな文字列を返します(alert で表示されたものです) 特別なオブジェクトは破棄され、プリミティブの str だけが残ります。 従って、プリミティブは依然として軽量なままですが、メソッドを提供できます。

  • 63

    明示的にnewキーワードでラッパーオブジェクトを作成してよいか

    ラッパーオブジェクトはプロパティやメソッドを提供するだけのものなので、やらないほうがいい。 alert( typeof 0); // "number" alert( typeof new Number(0) ); // "object"! ↑オブジェクトとして判定されてしまう オブジェクトは常にtrueなので、 new Number(0)がtrueと判断されてしまうので振る舞いが異なってしまう。 一方、new をつけずに同じ関数 String/Number/Boolean を使うことは、普通であり役に立ちます。それらは値を対応する型へ変換します: 文字列、数値、もしくは真偽値(プリミティブ) 例えば、これはまったく問題ありません: let num = Number("123"); // string から number へ変換

  • 64

    let str = "Hello"; str.test = 5; // (*) alert(str.test); はどのように動作するか?

    プリミティブなので、プロパティやメソッドは追加できない。 結果は2種類あります:: undefined エラー なぜでしょう? (*) で何が起きているのかもう一度見てみましょう: str のプロパティにアクセスされたとき、“ラッパーオブジェクト” が作られます。 プロパティの操作はそこで行われます。なので、オブエジェクトは test プロパティを取得します。 操作が終了し、“ラッパーオブジェクト” は消えます。 なので、最後の行では str はそのプロパティへのトレースを持っていません。

  • 65

    以下の数値記載に関するパターンを示せ let billion = 1000000000;

    区切りとしてアンダースコア _ を使用することも可能です: let billion = 1_000_000_000; ここで、アンダースコア _ は “糖衣構文” の役割をはたし、数値をより読みやすくします。JavaScriptエンジンは単に数字の間にある _ を無視するので、上の 10億とまったく同じです。 数値に文字 "e" を追加し、ゼロの数を指定することで数値を短くします。: let billion = 1e9; // 10 億, 文字通り: 1 と 9 個のゼロ

  • 66

    以下の数値記載に関する糖衣構文を示せ let ms = 0.000001;

    "e" が役立ちます。明示的にゼロを書くのを避けたい場合、このように書くことができます: let ms = 1e-6; // 1 から左にゼロを6つ 0.000001 の中のゼロの数は6つです。なので 1e-6 になります。

  • 67

    16進数、2進数、8進数で で、255の値を記載するにはどうするか?

    16進数 alert( 0xff ); // 255 alert( 0xFF ); // 255 (同じです。文字の大小は関係ありません) 2進数と8進数はあまり使われませんが、0b, 0o のプレフィックスでサポートされています: let a = 0b11111111; // 255 の2進数表記 let b = 0o377; // 255 の8進数表記 alert( a == b ); // true, 両方とも同じ数値(255)

  • 68

    文字列化する際に、進数変換を行うメソッドは?

    メソッド num.toString(base) は与えられた base の記数法で num の文字列表現を返します。 例: let num = 255; alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111

  • 69

    let num = 255; alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111 のように変数からメソッドを呼び出すのでなく、数値に対して直接メソッドを呼び出したい時はどうするか?

    255..toString(16)のようにドットを二つつかうとできる。 もし1つのドットを置いた場合 エラーになるでしょう。なぜならJavaScript構文は最初のドットの後を小数部分と考えるためです。そして、もう1つドットを置くと、JavaScriptは小数部分が空であることを知り、メソッドと判断します。 また、このように書くこともできます (255).toString(16)

  • 70

    数値の丸め処理を行う関数を4つ説明せよ

    Math.floor 切り捨て: 3.1 は 3 になり, -1.1 は -2 になります。 Math.ceil 切り上げ: 3.1 は 4 になり, -1.1 は -1 になります。 Math.round 四捨五入して最も近い整数にする: 3.1 は 3 になり, 3.6 は 4 になります。 -1.1 は -1 です。 Math.trunc (Internet Explorer では未サポート) 丸めを使わずに、小数点以下を削除: 3.1 は 3 になり, -1.1 は -1 です。

  • 71

    例えば、1.2345 という数値があり、1.23 のみを取り出すような、2桁に丸めたい場合の方法を二つかけ

    1 乗除算 例えば、小数第2位で数値を丸めるために、 数値を 100 で乗算し、丸め関数を呼び出した後、それを除算します。 let num = 1.23456; alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23 2 num.toFixed(n)メソッドを使う メソッド toFixed(n) は点の後の数字を “n” 桁に丸め、結果の文字列表現を返します。 今回は2桁にまとめたいので引数に2を指定 alert( num.toFixed(2) ); // "1.23" これは、Math.round と似たように、四捨五入で丸めます:

  • 72

    alert( 0.1 + 0.2 == 0.3 ); // false 上記の通り、もし 0.1 と 0.2 の合計が 0.3 かどうかをチェックした場合、false になります。 奇妙です! 0.3 でないのなら、何なのでしょう? alert( 0.1 + 0.2 ); // 0.30000000000000004 こうなるのはなぜか? どうすれば解決できるか?

    数値は内部ではバイナリ形式(2進数の64bit)となっている。 2進数を使って、 正確な 0.1 または 正確な 0.2 を格納する方法はありません。(無限の少数となってしまうため) alert( 0.1.toFixed(20) ); //0.10000000000000000555 この問題を回避できるのでしょうか?もちろん、幾つかの方法があります。最も信頼できる方法は、toFixed(n) メソッドにより結果を丸めることです: let sum = 0.1 + 0.2; alert( +sum.toFixed(2) ); // 0.3 toFixed は文字列がかえるので+で数値に変換もしている ただ根本的な解決策ではないので、小数点通しの計算はあんましないほうがいいかも

  • 73

    NaNは数値のエラーを表現するが、 NaNである(となる)か調べる方法はなにか?

    isNaN(value) はその引数を数値に変換し、NaN であるかをテストします: alert( isNaN(NaN) ); // true alert( isNaN("str") ); // true しかし、この関数は必要なのでしょうか?単に比較 === NaN は使えないのでしょうか?答えは 使えない です。NaN はそれ自身を含めて何とも等しくなく、ユニークです: alert( NaN === NaN ); // false

  • 74

    NaNやInfinite (と -Infinite) でないことをチェックする方法は?

    isFinite(value) は引数を数値に変換し、それが NaN/Infinity/-Infinity ではなく通常の数値であれば、true を返します。: alert( isFinite("15") ); // true alert( isFinite("str") ); // false, 特別な値: NaN alert( isFinite(Infinity) ); // false, 特別な値: Infinity 時々、isFinite は文字列値が通常の数値かどうかをチェックするのに使われます: let num = +prompt("Enter a number", ''); // 有効な数値であれば、trueとなる。 alert( isFinite(num) ); 空、またはスペースのみの文字列は、isFinite を含めた全ての数値関数で 0 として扱われる点に注意してください。

  • 75

    Object.is(a, b) は a === b との違いについて説明せよ

    NaN でうまく動作します: Object.is(NaN, NaN) === true、 これは良いことです。 値 0 と -0 は異なります: Object.is(0, -0) === false、 重要ではありませんが、技術的にはそれらは異なる値です。 上記2点において===より信頼性があるといえる。 それ以外はまったく同じ

  • 76

    parseInt と parseFloat関数について説明せよ

    文字列を頭から数値に変換していきます。 エラーが起きると、収集された数値が返されます。関数 parseInt は整数を返し、一方で、parseFloat は浮動小数を返します: alert( parseInt('100px') ); // 100 alert( parseFloat('12.5em') ); // 12.5 alert( parseInt('12.3') ); // 12, 整数部のみ返却されます alert( parseFloat('12.3.4') ); // 12.3, 2つ目の点で読むのをやめます parseInt/parseFloat が NaN を返す状況があります。それは数値が読み込めなかったときに発生します: alert( parseInt('a123') ); // NaN, 最初の文字で処理が止まります parseInt(str, radix) の2つ目の引数 parseInt() 関数は任意の2つ目のパラメータを持ちます。それは数値システムの基数を指定するので、parseInt もまた16進数、2進数などの文字列をパースすることが出来ます: alert( parseInt('0xff', 16) ); // 255 alert( parseInt('ff', 16) ); // 255, 0x がなくても動作します alert( parseInt('2n9c', 36) ); // 123456

  • 77

    ランダムな数値を返す関数は?

    Math.random() 0 から 1まで (1は含みません)のランダムな数値を返します alert( Math.random() ); // 0.1234567894322 alert( Math.random() ); // 0.5435252343232 alert( Math.random() ); // ... (any random numbers)

  • 78

    任意の数から最大、最小を返す関数は?

    Math.max(a, b, c...) / Math.min(a, b, c...) 任意の数の引数から最大/最小を返します alert( Math.max(3, 5, -10, 0, 1) ); // 5 alert( Math.min(1, 2) ); // 1

  • 79

    累乗を行う関数は?

    Math.pow(n, power) n を与えられた数だけ累乗します alert( Math.pow(2, 10) ); // 2 in power 10 = 1024 2の10乗のこと

  • 80

    数値にかかわる関数や定数のあるライブラリはなにか?

    Mathライブラリ

  • 81

    以下のようなうまく四捨五入が行われないときの対策法をかけ alert( 6.35.toFixed(20) ); // 6.34999999999999964473 alert( 6.35.toFixed(1) ); // 6.3 ↑四捨五入されない

    精度の低下が起きないように、整数に近づければ対策になる。 alert( (6.35 * 10).toFixed(20) ); // 63.50000000000000000000 alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(丸められた) -> 6.4

  • 82

    javascriptでは文字列の内部フォーマットはなにか?

    UTF-16

  • 83

    タグ付きテンプレートリテラルについて説明せよ

    バッククォートは最初のバッククォートの前に “テンプレート関数” を指定することができます。 構文は次のようになります: func`string`。 関数 func は自動的に呼ばれ、文字列と埋め込まれた式を受け取り、それらを処理することができます。 例 function tag(strings, ...values) { console.log(strings); // ["こんにちは、", "さん!"] console.log(values); // ["佐藤"] } let name = "佐藤"; tag`こんにちは、${name}さん!` tag関数に対し、テンプレートリテラルのうち埋め込み文字列以外を引数strings にわたし 埋め込み文字列をvaluesにわたして、関数実行している。

  • 84

    タグ付きテンプレートリテラルはどのような状況で利用できるか?

    タグ付きテンプレートは、文字列加工ができる。 埋め込んでない文字列を配列として取得し、 埋め込んだ文字列も引数のリスト渡されるので、処理ができる。…argsで取得できる とくに埋め込み文字列について、エスケープ処理とかできるので便利 エスケープ処理や多言語対応など、様々な応用が可能です。 例えば、下記のようにHTMLのエスケープ処理を実装することができます。 function htmlEscape(strings, ...values) { let escaped = values.map(value => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")); let result = strings[0]; for(let i = 0; i < escaped.length; i++) { result += escaped[i] + strings[i + 1]; } return result; } let tag = "<script>"; console.log(htmlEscape`次のタグは許可されていません: ${tag}`); // 次のタグは許可されていません: <script> https://lazy-developer.jp/javascript-template-literals#toc5

  • 85

    文字列で改行を表現するには? 2通りかけ

    let str1 = "Hello\nWorld"; // "改行文字" を使用した2行 // バッククォートを使用した2行 let str2 = `Hello World`; alert(str1 == str2); // true

  • 86

    文字列の長さをとるプロパティはなにか?

    length プロパティは文字列の長さを持ちます: alert( `My\n`.length ); // 3 \n は1つの “特殊” 文字であることに注意してください。なので、長さは実際に 3 です。

  • 87

    文字列に対して文字へアクセスする方法は?

    pos の位置の文字を取得する場合、角括弧 [pos] を使うか、もしくは str.charAt(pos) メソッドを呼び出します。最初の文字は 0 番目から始まります: let str = `Hello`; // 最初の文字 alert( str[0] ); // H alert( str.charAt(0) ); // H // 最後の文字 alert( str[str.length - 1] ); // o それらの唯一の違いは、文字が見つからなかった場合、[] は undefined を返し、charAt は空文字を返す点です。 let str = `Hello`; alert( str[1000] ); // undefined alert( str.charAt(1000) ); // '' (空文字)

  • 88

    文字列を一文字ずつ処理したい場合はどうするか?

    for..of を使って文字列をイテレートすることもできます: for (let char of "Hello") { alert(char); // H,e,l,l,o (文字は "H", 次に "e", その後は "l" ... となります) }

  • 89

    文字列を大文字小文字に変換する方法は?

    メソッド toLowerCase() と toUpperCase() はケースを変更します: alert( 'Interface'.toUpperCase() ); // INTERFACE alert( 'Interface'.toLowerCase() ); // interface 1文字だけ小文字にしたい場合は次のようにできます: 文字列 str 自身の値には影響を与えません。

  • 90

    文字列の中で、部分文字列を探す方法は?

    str.indexOf(substr, pos) これは str の中で substr を探し、与えられた pos の位置から開始して、見つかった位置、または見つからなかった場合は -1 を返します。 例えば、"id" の最初の出現は 1 の位置です。※0から数える 次の出現を探すために、2 の位置から検索を始めてみましょう。: let str = 'Widget with id'; alert( str.indexOf("id") ); // 1, "id" は位置 1 で見つかりました(..idget の id) alert( str.indexOf('id', 2) ) // 12 "id" は位置 12で見つかりました 文字列の最後から最初に向かって探す類似のメソッド str.lastIndexOf(pos) もあります。 それは逆の順序でマッチする対象を列挙します。

  • 91

    部分文字列で、とある文字列について全ての出現位置を出したい場合はどうするか?

    すべての出現箇所が知りたい場合は、ループの中で indexOf を使います。 検索結果の位置を返すので、 前回マッチした位置から+1した値で再呼び出しを行います: let str = "As sly as a fox, as strong as an ox"; let target = "as"; let pos = -1; while ((pos = str.indexOf(target, pos + 1)) != -1) { alert( pos ); //7 17 27 }

  • 92

    このコードについて説明せよ とくに~str の部分を説明せよ let str = "Widget"; if (~str.indexOf("Widget")) { alert( 'Found it!' ); // 動作します }

    ~演算子とは 数値を 32bit 整数に変換し(もし存在すれば小数部分を除いて)、その2進数表現のすべてのビットを反転します。 32ビット整数の場合、 〜n は(IEEE-754形式のため) -(n+1) と全く同じ意味です。 alert( ~0 ); // -1, -(0+1) と同じです alert( ~-1 ); // 0, -(-1+1) と同じです つまり -1は0になるので、  以下のように -1でチェックしなくていいってだけに使われる。 let str = "Widget with id"; if (str.indexOf("Widget") != -1) { alert("We found it"); // これで動きます! } 現在、このようなトリックは古いコードの中でのみ確認できます。現在の JavaScript では .includes メソッド(後述)が提供されています。

  • 93

    indexOfを利用しない部分文字列が含むかどうかをチェックする方法は?

    str.includes(substr, pos) は str が substr 含むかどうかで true/false を返します。 マッチしているかの確認は必要だが、その位置までは不要と言った場合にこのメソッド indexOfなら-1でチェックしないといけないところ、これならラクということらしい。 str.includes の任意の2つ目の引数は、検索開始の位置です: alert( "Midget".includes("id") ); // true alert( "Midget".includes("id", 3) ); // false, 位置 3 gのとこから見ると、"id" はありません

  • 94

    部分文字列から始まることや終わることを検知するメソッドは?

    メソッド str.startsWith と str.endsWith alert( "Widget".startsWith("Wid") ); // true, "Widget" は "Wid" で始まります alert( "Widget".endsWith("get") ); // true, "Widget" は "get" で終わります

  • 95

    とある文字列から、位置を指定して部分文字列を取得する方法を3つあげよ

    JavaScriptでは、部分文字列を取得する3つの方法があります: substring, substr と slice です。 slice(start, end) start から end まで 負の値を許可します 負の場合、位置が文字列の末尾からカウントされることを意味します:   let str = "stringify"; // 右から4番目から始まり、右から1つ目まで alert( str.slice(-4, -1) ); // gif substring(start, end) start と end の間 負の値は 0 扱いです これはほぼ slice と同じですが、start が end より大きくても良いです。 alert( str.substring(2, 6) ); // "ring" alert( str.substring(6, 2) ); // "ring" substr(start, length) start から length 文字を取得 負の start を許可します 最初の引数は、末尾からカウントするために負の値にもできます: let str = "stringify"; alert( str.substr(2, 4) ); // ring, 2の位置から 4文字取得します alert( str.substr(-4, 2) ); // gi, 4の位置から 2文字取得します

  • 96

    部分文字列の抽出は何を使うべきか?

    どれでもいい あえていえば、slice これらすべて使えます。正確には、substr は小さな欠点があります: それは コアなJavaScriptの仕様ではなく、主に歴史的な理由から存在するブラウザ専用の機能を扱う Annex B で説明されています。なので、非ブラウザ環境ではサポートされていない可能性があります。ただ、実際にはほぼどこでも動作しています。 著者はほとんどのケースで slice を使っています。

  • 97

    JavaScriptでは文字はUTF-16で表現されており、各文字は対応する数値コードを持っている。 文字から数値コードを取得するメソッドはなにか? また、数値コードから文字を取得するメソッドはなにか?

    str.codePointAt(pos) 位置 pos の文字コードを返します: // 大小異なる文字は文字コードも別です alert( "z".codePointAt(0) ); // 122 alert( "Z".codePointAt(0) ); // 90 String.fromCodePoint(code) 数値 code で文字を生成します: alert( String.fromCodePoint(90) ); // Z ちなみに文字列を比較する際はこの数値コードで大小比較を行うことになる。

  • 98

    16進数のコードを使って文字を出すにはどうするか?

    \u とそれに続く16進数のユニットコードを記載するとそのまま変換されて出力される。 \nのような特殊文字として扱われている // Zは10進数で90 、 16進数で 5a なので、 alert( '\u005a' ); // Z

  • 99

    アルファベットは言語によって異なる Öみたいなのをアルファベットとして使う言語もある。 そういった場合に正しく 文字列比較を行うためにはどんなメソッドが利用できるか?

    それは次のルールに従った、異なる言語で文字列を比較するための特殊なメソッドを提供します。 str.localeCompare(str2) 呼び出し: 言語規則に従って、str が str2 より大きい場合、1 を返します。 str が str2 より小さい場合は -1 を返します。 それらが等価な場合は 0 を返します。 例: alert( 'Österreich'.localeCompare('Zealand') ); // -1 ÖはOと同等として扱われ、Zより前(つまり小さい)と判断された。 オプション引数によって、 大文字小文字を同等として扱うなどさらに細かいルールで比較ができるようになるらしい https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#%E9%85%8D%E5%88%97%E3%81%AE%E4%B8%A6%E3%81%B9%E6%9B%BF%E3%81%88