2024フロントエンド実習面接の技術要点まとめ

目次

CSS

1.CSSのレイアウト方式にはどのようなものがありますか?

2.Flexboxで左右レイアウトを実装する方法。

3.CSSの一般的な単位。

4.CSSでは何が継承されますか?

5.リフローと再描画について。

6.Flexboxレイアウトのプロパティ。

7.CSSのカスケードスタイルの優先順位ルール。

8.擬似クラスと擬似要素の違い。

9.ボックスモデルの種類。

10.要素の中央揃え方法。

11.リスト内の特定の子要素を選択してスタイルを適用する方法。

12.CSSで要素を非表示にする方法。

JavaScript

1.ES6の新機能。

2.配列操作のメソッド。

3.クロージャの概念とその必要性。

4.デバウンスとスロットル。

5.thisの決定方法。

6.基本データ型。

7.配列であるかどうかの判定方法。

8.typeOfについて。

9.正の整数であるかどうかの判定方法。

10.非同期プログラミング。

11.非同期タスクの核心API。

12.フロントエンドインターセプター。

13.シャローコピーとディープコピーの違いと実装方法。

14.タスクキュー。

15.変数のスコープとその優先順位。

16.変数ホイスティングの長所と短所。

17.プロトタイプチェーン。

18.letとconstがそれぞれ解決する問題。

19.Promiseが解決する問題とasync/awaitの役割。

TypeScript

1.型が確定していない変数をrefで宣言する方法。

2.フォームバリデーションの実装方法。

3.ジェネリクスの役割。

4.interfaceとtypeの違い。

Vue

1.Vueのディレクティブとその役割。

2.v-ifとv-showの違い。

3.Vueの一般的な修飾子とその使用場面。

4.Vue2とVue3の違い。

5.Viteについて。

6.Vueのレンダリングプロセス。

7.MVVMパターンの説明。

8.VueでのVMの実装原理。

9.Vue3でのコンポーネント間のデータ受け渡し方法。

10.Vuexについて。

11.Webpackと、パッケージングが遅い場合の対策。

12.画像の遅延読み込み。

13.Vueのライフサイクル。

14.keep-aliveについて。

15.仮想DOMについて。

16.Vueのリアクティブシステムの原理。

17.computedとwatchの違い。

18.v-forにおけるkeyの役割と、インデックスをkeyとして使用しない理由。

ミニプログラム

1.ライフサイクルについて。

コンピュータネットワーク

1.httpとhttpsの違い。

2.httpステータスコード。

3.http1.0、http2.0、http3.0の違い。

Gitバージョン管理

1.Gitの一般的なコマンド。

2.現在の作業をコミットせずに他のブランチに移動する方法。

データ構造とアルゴリズム

1.どのようなデータ構造を理解していますか?Vueではどこで使用されていますか?

デザインパターン

1.どのようなデザインパターンを理解していますか?

MySQL

1.charとvarcharの違いは何ですか?

その他

1.自己紹介。

2.会社についてどのようなことを知っていますか?

3.なぜ遠くの実習先を希望しましたか?

4.いつから働けますか?どれくらいの期間実習できますか?

5.普段どのような方法で学習していますか?

6.希望給与はどれくらいですか?

7.プロジェクト開発でどのような困難に直面しましたか?どのように克服しましたか?

8.なぜフロントエンドの仕事に興味がありますか?

9.サークルや学生会に参加したことはありますか?具体的な業務内容は何ですか?指導的な立場に立ったことはありますか?

10.最も印象に残ったまたは達成感を感じたプロジェクトについて説明してください。

11.互換性の問題に遭遇したことはありますか?

12.どのような最適化を行いましたか?

13.他に質問はありますか?

CSS

1.CSSのレイアウト方式にはどのようなものがありますか?

  • 標準レイアウトフロー:ページに対してレイアウト制御を行わない場合、ブラウザが採用するデフォルトのHTMLレイアウト方式
  • displayプロパティ:CSSでページレイアウトを実現する主な方法で、標準フロー内のすべての要素にはデフォルトのdisplay値があります。このプロパティによりデフォルトの表示方式を変更できます
  • フレキシブルボックス(Flexbox):横方向または縦方向の一次元ページレイアウトを作成するために使用されます
  • グリッド(Grid)レイアウト:要素を行と列で整然と配置する二次元レイアウトです
  • フロート(float):要素を「浮かせる」ことで、その要素とそれに続く他の要素の動作を変更します。要素は左または右に浮かび、標準のレイアウトフローから削除されます。これにより、周囲のコンテンツがこのフロート要素の周りに配置されます
  • ポジショニング(position):要素を通常のレイアウトフロー内の位置から別の位置に移動させます。以下のような方式があります:
    • 静的ポジショニング(Static positioning):各要素のデフォルトプロパティで、文書レイアウトフローのデフォルト位置に配置されます
    • 相対的ポジショニング(Relative positioning):要素を標準的な文書フロー内の位置から相対的に移動させます
    • 絶対的ポジショニング(Absolute positioning):要素をページの標準レイアウトフローから完全に取り出し、複雑なレイアウト効果を作成する際に非常に役立ちます(例:タグによる表示/非表示コンテンツパネルや、ボタンで制御される画面にスライドする情報パネルなど)
    • 固定ポジショニング(Fixed positioning):絶対的ポジショニングに似ていますが、ブラウザビューポートに対して固定される点が異なります
    • 粘着ポジショニング(Sticky positioning):新しいポジショニング方式で、要素は最初にposition: staticのような位置に保持されますが、ビューポートに対する相対位置が特定の値に達すると、position: fixedのように固定されます
  • CSSテーブルレイアウト:FlexboxとGridをサポートしないブラウザの互換性のために使用される、従来の柔軟性のない方法です
  • マルチカラムレイアウト:コンテンツを列に並べる方法を提供します

2.Flexboxで左右レイアウトを実装する方法。

/* HTML */
<div class="container">
    <div class="left-panel">左側コンテンツ</div>
    <div class="right-panel">右側コンテンツ</div>
</div>

/* CSS */
.container {
    display: flex; /* 1.Flexboxレイアウトを有効化 */
    flex-direction: row; /* 2.左右レイアウトを実現 rowは水平配置、row-reverseは逆方向の水平配置も可能 */
    align-items: stretch; /* 3.子要素が垂直方向の高さを埋めるようにして高さを一致させる */
}
.left-panel {
    width: 300px; /* 4.左側の幅を設定 */
}
.right-panel {
    flex: 1; /* 5.残りの幅を割り当て */
}

3.CSSの一般的な単位。

  • 絶対単位
    • px:画像表示の基本単位
  • 相対単位
    • em:親要素のfont-sizeを基準に計算され、CSSルールがない場合、1emの長さは16pxです。em単位はfont-sizeプロパティを設定すると、階層的に乗算されます
    • rem:ルート要素のfont-sizeを基準に計算され、emのように階層的にサイズを計算する必要がありません
    • vw:ビューポート幅のパーセンテージ(1vwはビューポート幅の1%を表します)
    • vh:ビューポート高さのパーセンテージ
    • vmin:現在のvwとvhのうち小さい方の値
    • vmax:現在のvwとvhのうち大きい方の値
    • %:親要素のサイズを基準に計算されます

4.CSSでは何が継承されますか?

  • フォント系プロパティ:font、font-family、font-weight、font-size、font-style
  • テキスト系プロパティ
    • インライン要素:color、line-height、word-spacing、letter-spacing、text-transform
    • ブロック要素:text-indent、text-align
  • 要素の可視性:visibility
  • テーブルレイアウトプロパティ:caption-side、border-collapse、border-spacing、empty-cells、table-layout
  • リストレイアウトプロパティ:list-style
  • 生成コンテンツプロパティ:quotes
  • カーソルプロパティ:cursor
  • ページスタイルプロパティ:page、page-break-inside、windows、orphans
  • 音声スタイルプロパティ:speak、speech-rate、volume、voice-family、pitch、stress、elevation

5.リフローと再描画について。

  • リフロー:レイアウトエンジンは各スタイルに基づいて各ボックスのページ上のサイズと位置を計算します
    • トリガー
      • 表示されるDOM要素の追加または削除
      • 要素のサイズの変更(マージン、パディング、ボーダー、高さ、幅など)
      • 要素の位置の変更
      • コンテンツの変更(テキストの変更や、異なるサイズの画像による置換など)
      • ページの最初のレンダリング時(避けられません)
      • ブラウザウィンドウサイズの変更
      • 特定のプロパティ値の取得(オフセットやスクロールなど、計算が必要なプロパティ)
    • 回避方法
      • 要素のクラス名を変更してスタイルを設定
      • インラインスタイルの複数設定を避ける
      • アニメーションを適用し、positionプロパティのfixedまたはabsolute値を使用して、可能な限り要素を文書フローから分離させ、他の要素への影響を減らす
      • テーブルレイアウトの使用を避ける(テーブル内の各要素のサイズやコンテンツの変更は、テーブル全体の再計算を引き起こします)
      • CSS3ハードウェアアクセラレーションを使用して、transform、opacity、filtersなどのアニメーションがリフローと再描画を引き起こさないようにする
      • CSSのJavaScript式の使用を避ける
  • 再描画:ボックスモデルの位置、サイズ、その他のプロパティが計算された後、ブラウザは各ボックスの特性に基づいて描画します
    • トリガー
      • リフローのトリガー(リフローは必ず再描画を引き起こします
      • 色の変更
      • テキスト方向の変更
      • 影の変更

6.Flexboxレイアウトのプロパティ。

<div class="container">
    <div class="item1">1</div>
    <div class="item2">2</div>
</div>
  • display:flexコンテナに適用され、flexレイアウトを実現します
  • flexアイテムに適用され、コンテナ全体の容量に対するアイテムの割合を指定します
  • flex-direction:主軸の方向を決定します
    • row(デフォルト):主軸が水平方向で、起点は左端
    • row-reverse:主軸が水平方向で、起点は右端
    • column:主軸が垂直方向で、起点は上端
    • column-reverse:主軸が垂直方向で、起点は下端
  • flex-wrap:一行に収まらないアイテムをどう配置するかを決定します
    • nowrap:折り返さず、幅の比率に応じて一行に配置
    • wrap:折り返し、順序通りに配置
    • wrap-reverse:折り返し、逆順に配置
  • justify-content:アイテムを主軸上でどのように配置するかを決定します
    • flex-start(デフォルト):左揃え
    • flex-end:右揃え
    • center:中央揃え
    • space-between:両端揃えで、アイテム間の間隔が等しい
    • space-around:各アイテムの両側の間隔が等しく、アイテムとボーダー間の間隔はアイテム間間隔の半分
    • space-evenly:各アイテム間の間隔が等しい
  • align-items:アイテムを交差軸上でどのように配置するかを決定します
    • stretch(デフォルト):アイテムに高さが設定されていない場合、コンテナの高いさ全体を占めます
    • flex-start:上端揃え
    • flex-end:下端揃え
    • center:中央揃え
    • baseline:ボックス内の最初の行のテキストのベースラインに揃えます
  • align-self:アイテムを他のアイテムと異なる配置にすることができ、align-itemsを上書きできます
  • align-content:複数行のアイテムを交差軸上でどのように配置するかを決定します。一行の場合は無効で、flex-wrapと組み合わせて使用する必要があります
    • stretch(デフォルト):軸が交差軸全体を占めます
    • flex-start:上揃え
    • flex-end:下揃え
    • center:中央揃え
    • space-between:交差軸の両端に揃え、軸間の間隔を均等に分配
    • space-around:各軸の両側の間隔が等しい
    • space-evenly:アイテムが均等に分布
  • order:アイテムの配置順序を定義し、値が小さいほど前に配置されます。デフォルト値は0です
  • flex-grow:アイテムが残りのスペースを占める能力を決定します
  • flex-shrink:コンテナのスペースが不足した場合に、アイテムが縮小する割合を決定します。デフォルト値は1です
  • gap:アイテム間の最小間隔。間隔が何らかの方法で大きくなった場合、その間隔が最終的に小さくなった場合にのみ有効になります
  • row-gap:主軸方向の最小間隔
  • column-gap:交差軸方向の最小間隔

7.CSSのカスケードスタイルの優先順位ルール。

  1. 最も近い祖先のスタイルは、他の祖先のスタイルより優先度が高い
  2. 直接のスタイルは祖先のスタイルより優先度が高い
  3. インラインスタイル > IDセレクタスタイル > クラスセレクタスタイル = 属性セレクタスタイル = 擬似クラスセレクタスタイル > タグセレクタスタイル = 擬似要素セレクタスタイル
  4. セレクタ内のIDセレクタの数(a)を計算し、次にクラスセレクタ、属性セレクタ、および擬似クラスセレクタの数の合計(b)を計算し、タグセレクタと擬似要素セレクタの数の合計(c)を計算します。a、b、cの順に比較し、大きい方が優先度が高く、等しい場合は次を比較します。最後に2つのセレクタのa、b、cが等しい場合、近接の原則に基づいて判断します。セレクタは以下の通りです:
    • 子孫セレクタ:.parent .child {}
    • 子セレクタ:.parent > .child {}
    • 隣接セレクタ:.sibling1 + .sibling2 {}
  5. プロパティ後に!importantが付いているプロパティは最も高い優先度を持ち、同時に!importantがある場合は、ルール3、4で優先度を判断します

8.擬似クラスと擬似要素の違い。

  • 擬似クラスは本質的に要素に追加のクラス名を作成し、複数のクラス名で複数の効果を実現します
  • 擬似要素はコンテンツを持つ仮想コンテナを作成し、**追加のDOMノード(要素)**を作成します
  • CSS3では擬似クラスと擬似要素の構文が異なり、擬似要素は一般的に**::擬似クラス:**です
  • 複数の擬似クラスを同時に使用できます(間にスペースを入れない)が、一つの擬似要素しか同時に使用できません

9.ボックスモデルの種類。

  • W3C標準のボックスモデル(標準ボックスモデル
    • widthはコンテンツの幅を指し、heightはコンテンツの高さを指します
    • ボックスサイズ = コンテンツ + ボーダー + パディング + マージン
  • IE標準のボックスモデル(怪異ボックスモデル
    • widthはコンテンツ、ボーダー、パディングの合計幅を指し、heightはコンテンツ、ボーダー、パディングの合計高さを指します
    • ボックスサイズ = width + マージン

10.要素の中央揃え方法。

  • 絶対配置 + transformの逆方向オフセット
// HTML
<div class="main-container">1</div>

// CSS
.main-container {
    position: absolute;
    left: 50%; // body内での左からの50%の位置から開始
    top: 50%; // 実際にはbody内での上からの50%の位置
    transform: translate(-50%, -50%); // 水平、垂直ともに中央揃え
}
  • フレキシブルボックス
// HTML
<div class="flex-container">
    <div class="flex-item">1</div>
</div>

// CSS
.flex-container {
    display: flex;
    justify-content: center; // 水平中央揃え
    align-items: center; // 垂直中央揃え
}

11.リスト内の特定の子要素を選択してスタイルを適用する方法。

  • :nth-child(n):n番目の子要素を選択し、nは1からカウントします
  • :nth-child(odd)/:nth-child(even):子要素の中で奇数/偶数番目のものを選択し、nは1からカウントします
  • :nth-child(an+b):nは0からカウントします

12.CSSで要素を非表示にする方法。

  • opacityで要素の不透明度を設定し、要素はページ上に残ります
.element {
    opacity: 0;
}
// またはフィルター属性と一緒に使用
.element {
    filter: opacity(0);
}
  • visibilityで要素の可視性を制御し、要素はページ上に残ります
.element {
    visibility: hidden;
}
  • displayで要素を非表示にし、文書フローから削除され、DOMに存在しなかったかのように振る舞います
.element {
    display: none;
}

13.ブロック要素とインライン要素の違い。

ブロック要素

  • 各ブロック要素は一行を占有し、デフォルトで垂直に配置されます
  • 高さ、幅、マージン、パディングは制御可能で、設定が有効で境界効果があり、幅が設定されていない場合はデフォルトで100%
  • ブロック要素にはブロック要素とインライン要素を含めることができます

インライン要素

  • インライン要素は他のインライン要素と共に水平線上に配置されます
  • 高さ、幅は制御不可能で、設定は無効であり、コンテンツによって決まります
  • タグのセマンティックの理念に基づき、インライン要素はインライン要素のみを含むのが理想的で、ブロック要素を含むべきではありません

JavaScript

1.ES6の新機能。

  • letとconst:
    • let:変数を定義するために使用され、ブロックスコープ内でのみアクセスでき、同名の変数を宣言できず、関数をまたいでアクセスできません
    • const:定数を定義するために使用され、使用時に初期化する必要があり、同名の変数を宣言できず、変数ホイスティングが存在せず、ブロックスコープ内でのみアクセスでき、値を変更できません(オブジェクトの場合はプロパティ値は変更可能)、関数をまたいでアクセスできません
  • 新しい基本データ型symbolとbigInt
    • symbolユニーク不変(グローバル変数の競合、内部変数の上書きを解決)
    • bigInt任意の精度の整数を表し、大きな数値の安全な保存と操作をサポートします
  • 関数の面:
    • 関数のデフォルト値:関数に引数が渡されない場合、パラメータ値はデフォルト値になります
    • アロー関数:より簡潔ですが、内部にargumentsとprototypeがないため、newで呼び出せず、内部のthisは常に親スコープのthisを指します
  • 配列操作:
    • fill():指定された値で配列を埋めます
    • find():配列を走査し、最初に条件に一致する要素を返し、見つからない場合はundefinedを返します
    • findIndex():find()に似ていますが、返されるのは要素のインデックスで、見つからない場合は-1を返します
    • Array.from():配列のようなオブジェクトや疑似配列を配列に変換します。配列のようなオブジェクトのプロパティは数値または文字列の数字である必要があり、lengthプロパティが必要です。lengthプロパティがない場合は空配列が生成されます
    • flat():ネストされた配列を一度または複数回平らにします。デフォルトは1回で、Infinityを使用するとすべて平らにします
    • flatMap():map()とflat()の組み合わせで、map()で生成された新しい配列を一度平らにします
    • includes():配列に特定の要素が存在するかどうかを確認し、存在すればtrueを返し、そうでなければfalseを返します
  • テンプレート文字列
    • ${}」で区切り、「``」で完了します
    • 文字列メソッド:
      • includes():文字列にパラメータ文字が含まれるかどうかを判断し、boolean値を返します
      • startsWith():文字列がパラメータ文字列で始まるかどうかを判断し、boolean値を返します
      • endsWith():文字列がパラメータ文字列で終わるかどうかを判断し、boolean値を返します
      • repeat():指定された回数だけ新しい文字列を返します
      • padStart():指定された長さで文字列を前方から埋めます(パラメータが指定されていない場合はデフォルトで空白)、新しい文字列を返します
      • padEnd():指定された長さで文字列を後方から埋めます(パラメータが指定されていない場合はデフォルトで空白)、新しい文字列を返します
  • 分解式(デストラクチャリング)
    • 配列の分解
        const[a,b,c] = [1,2,3];
        console.log(a,b,c); // 1 2 3
    
        const[a,b,c] = [1,2];
        console.log(a,b,c); // 1 undefined 2
    
        const[a,,b] = [1,2,3];
        console.log(a,b); // 1 3
    
        const[a,...b] = [1,2,3];
        console.log(a,b); // 1 [2,3]
    
    • オブジェクトの分解
        const obj = {
            name: "tanaka",
            age: 25,
            gender: "male"
        };
        const { name, age, gender } = obj;
        console.log({ name, age, gender }); // "tanaka" 25 "male"
        const { name: myName, age: myAge, gender: myGender } = obj;
        console.log({ myName, myAge, myGender }); // "tanaka" 25 "male"
    
  • オブジェクトの面:
    • Map:キーは任意の値を保持でき、sizeプロパティを提供します
    • Object.is():2つの値が同じ値であるかどうかを判断します
    • Object.assign():オブジェクトをマージし、宛先オブジェクトを返します(同じプロパティは上書きされます)
    • Object.keys():オブジェクトのすべてのプロパティを返します
    • Object.values():オブジェクトのすべてのプロパティ値を返します
    • Object.entries():複数の配列(プロパティ + プロパティ値)を返します
  • class:クラスと継承を作成します(サブクラスはコンストラクタ内でsuper()を呼び出す必要があります)、本質的には関数です
  • モジュール化
    • importキーワードでモジュールをインポート
    • exportとexport defaultキーワードでモジュールをエクスポート
    • 利点:
      • 名前の競合を防止
      • 再利用性が高い
  • Promise:非同期プログラミングの解決方法の一つで、コンストラクタ同期で実行され、thenメソッド非同期で実行されます
    • 状態(状態は一度変更されると変更できません):pending(初期状態)、fulfilled(成功状態)、rejected(失敗状態)
      • pending→fulfilled || pending→rejectedのみ可能
    • メソッド:
      • then():関数コールバックを実行し、リクエストインターフェースから返されたデータを受け取るために使用されます。2つのパラメータがあり、1つはPromise成功時のコールバック関数用、もう1つはPromise拒否時のコールバック関数用です。戻り値もPromiseオブジェクトです
      • catch()Promiseが拒否された場合のコールバック関数を処理し、戻り値はPromiseオブジェクトです。同時にコードの異常やエラーをキャッチするためにも使用されます
      • finally():Promiseの状態に関係なく、パラメータを受け取らず、戻り値もなく、どちらの場合でも実行されます
      • resolve()(静的メソッド):成功状態のPromiseオブジェクトを作成するために使用されます
      • reject()(静的メソッド):失敗状態のPromiseオブジェクトを作成するために使用されます
      • race()(静的メソッド):Promiseの配列を受け取り、いずれかのPromiseオブジェクトの状態が確定した直後にコールバック関数を実行します
      • any()(静的メソッド):Promiseの配列を受け取り、配列内に1つでも成功したPromiseオブジェクトがあると、その成功したPromiseの結果が返されます。すべてがrejected状態の場合、最後のPromiseオブジェクトの実行後に、すべてのpromiseが異常関数に返されます
      • all()(静的メソッド):Promiseの配列を受け取り、配列内のすべてのPromiseオブジェクトにrejected状態がない場合、すべてのresolve成功後にコールバックを実行し、1つでもrejected状態が発見されるとすぐに異常関数を実行します
      • allSettled()(静的メソッド):Promiseの配列を受け取り、すべてのPromiseオブジェクトの状態が確定した後(成功でも拒否でも)にコールバック関数を実行し、オブジェクトの配列**{[state: xx, value/reason(成功はvalue、失敗はreason): xx]}**を返します
  • Proxy:オブジェクトのプロキシを作成し、基本操作のインターセプトとカスタマイズ(プロパティの検索、代入、列挙、関数呼び出しなど)を実現します
    • メソッド:
      • Proxy.revocable()取り消し可能なProxyオブジェクトを作成します
    • 構文:const p = new Proxy(target, handler)
      • target:Proxyでラップする対象オブジェクト(任意の種類のオブジェクトで、ネイティブの配列、関数、さらには別のプロキシでさえも可能です)
      • handler:通常、関数をプロパティとして持つオブジェクトで、各プロパティの関数は、様々な操作を実行する際にプロキシpの動作を定義します
  • 演算子
    • ...:スプレッド演算子、コピーとマージに使用されます
    • ?.:オプショナルチェーン演算子
    • :::バインド演算子

2.配列操作のメソッド。

# ES5およびそれ以前

  • push():配列の最後尾に1つ以上のパラメータを追加し、新しい配列の長さを返します
  • pop():配列の最後尾を削除し、その要素を返します
  • unshift():push()に似ていますが、配列の先頭で操作を行います
  • shift():pop()に似ていますが、配列の先頭で操作を行います
  • forEach():配列を走査し、コールバック関数を実行します
  • map():forEach()に似ていますが、結果を返すことができます
  • filter():配列を走査し、条件を満たすすべての要素をフィルタリングし、新しい配列を返します
  • reduce():配列を走査し、コールバック関数の各結果を次の初期値preとして使用し、最終結果を返します
  • reduceRight():reduce()に似ていますが、右から左へ実行されます
  • every():配列を走査し、すべての要素が条件を満たす場合trueを返し、そうでなければfalseを返します
  • some():every()に似ていますが、1つでも条件を満たす要素が存在すればtrueを返します
  • valueOf():配列の元の値を返し、通常は配列自体を返します
  • indexOf():指定された要素が配列内で最初に現れる位置を返し、存在しない場合は-1を返します
  • lastIndexOf():indexOf()に似ていますが、最後に現れる位置を返します
  • sort():配列をソートし、パラメータなしのソートはUnicodeコードポイントに基づきます。不安定です
  • reverse():配列を反転します
  • splice():配列の追加、削除、置換操作を行います。最初のパラメータは操作開始位置のインデックス、2番目のパラメータは削除する要素の数、後続のパラメータは追加する要素です
  • slice():配列を切り取った新しい配列を返し、元の配列を変更しません。範囲は左閉右開です
  • concat():複数の配列を結合し、新しい配列を返し、元の配列を変更しません
  • join():指定された文字で配列を文字列に変換し、パラメータがない場合は「,」がデフォルトです
  • toString():配列を文字列に変換し、join()のパラメータなしの場合に似ています

# ES6

  • find():配列を走査し、最初に条件に一致する要素を返し、見つからない場合はundefinedを返します
  • findIndex():find()に似ていますが、返されるのは要素のインデックスで、見つからない場合は-1を返します
  • includes():配列に特定の要素が存在するかどうかを確認し、存在すればtrueを返し、そうでなければfalseを返します
  • Array.from():配列のようなオブジェクトや疑似配列を配列に変換します。配列のようなオブジェクトのプロパティは数値または文字列の数字である必要がありlengthプロパティが必要です。lengthプロパティがない場合は空配列が生成されます
  • flat():ネストされた配列を1回または複数回平らにします。デフォルトは1回で、Infinityパラメータを使用するとすべて平らにします
  • flatMap():map()とflat()の組み合わせで、map()で生成された新しい配列を1回平らにします
  • fill():指定された値で配列を埋めます

3.クロージャの概念とその必要性。

クロージャとは、別の関数のスコープ内の変数にアクセスできる関数のことです。

クロージャ関数とは、関数内で宣言された関数のことです。

  • 特徴:
    • 外部から関数内部の変数にアクセスできるようにします
    • ローカル変数がメモリに常駐します
    • グローバル変数の使用を避け、グローバル変数の汚染を防ぎます
    • メモリリークを引き起こす可能性があります(メモリ領域が長期に占有され解放されない状態)

4.デバウンスとスロットル。

デバウンスとスロットルは、両方とも一般的なフロントエンドのパフォーマンス最適化手法です。

  • デバウンス複数回トリガーされても、最後の実行のみを行います
// lodashライブラリのdebounceメソッドを使用してデバウンスを実装できます
// _.debounce(func,[wait = 0],[option=])    戻り値:デバウンスされた新関数
//     1.func:元の関数
//     2.wait:デバウンス遅延時間
//     3.option:その他の設定(オプション)

// ---------- デバウンスの手動実装 -----------
function debounce(func,wait = 0) {
    let timeId;
    // thisを返すためにアロー関数を使用しない
    return function(...args) {
        clearTimeout(timeId); // 前のタイマーをクリア
        timeId = setTimeout(function() {
            const _this = this;
            func.apply(_this,args); // thisを指定し、配列形式で引数を渡す
        },wait);
    };
}
  • スロットル指定された時間内で1回のみ実行されます
// lodashライブラリのthrottleメソッドを使用してスロットルを実装できます
// _.throttle(func,[wait = 0],[option=])    戻り値:スロットルされた新関数
//     1.func:元の関数
//     2.wait:スロットル時間
//     3.option:その他の設定    options.leading——スロットル開始前に呼び出すか、デフォルトはtrue

// ---------- スロットルの自実装 ----------
function throttle(func,wait = 0) {
    let timeId;
    return function(...args) {
        // すでにタイマーが存在する場合は、戻る
        if(timeId !== undefined) {
            return;
        }
        const _this = this;
        timeId = setTimeOut(() => {
            func.apply(_this,args);
            timeId = undefined; // 完了後、idを空に設定
        },wait);
    };
}

5.thisの決定方法。

ps:グローバル環境または関数先頭で'use strict'を宣言すると厳格モードになります

  • グローバル環境:厳格モードでも非厳格モードでも、thisはグローバルオブジェクト(Window)を指します
  • 関数内部
    • 直接呼び出し:厳格モードではthisはundefinedを指し、非厳格モードではthisはグローバルオブジェクト(Window)を指します
    • オブジェクト経由での呼び出し:厳格モードでも非厳格モードでも、thisは呼び出し元を指します

6.基本データ型。

ES5およびそれ以前:undefined、null、boolean、string、number、object

ES6で追加:symbol、bigInt

7.配列であるかどうかの判定方法。

  1. arr instanceof Array; // true
  2. Object.prototype.toString.call(arr); // "[object Array]"
  3. arr.constructor === Array; // true
  4. Array.isArray(arr); // true
  5. arr.proto === Array.prototype; // true
  6. Object.getPrototypeOf(arr) === Array.prototype; // true

8.typeOfについて。

const user = {
   name: 'yamada',
   age: 22
};

console.log(typeof 1); // number
console.log(typeof NaN); // number
console.log(typeof '1'); // string
console.log(typeof undefined); // undefined
console.log(typeof true); // boolean
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof user); // object

9.正の整数であるかどうかの判定方法。

  1. num > 0 && Number.isInteger(num); // ES6で提供
  2. num > 0 && ((num | 0) === num); // 効率が高い
  3. num > 0 && num % 1 === 0 && typeof num === 'number'; // num % 1の際、非数値型は自動的に型変換されて判定結果もtrueになるため(例えば'true'は1に変換)、numが数値型かどうかを判定する必要があります
  4. num > 0 && Math.floor(num) === num; // 小数点以下を切り捨てても元の値と同じ
  5. num > 0 && parseInt(num,10) === num; // 検索範囲を超える数値は検出されず、最初の数字を返します

10.非同期プログラミング。

  • Promise
axios('url1').then(res1 => {
    return axios('url2');
}).then(res2 => {
    return axios('url3');
}).then(res3 => {
    // ...
});
  • Generator
function* myGenerator() {
    yield axios('url1');
    yield axios('url2');
    yield axios('url3');
    // ...
}
  • async
async function myAsync() {
    const res1 = await axios('url1');
    const res2 = await axios('url2');
    const res3 = await axios('url3');
    // ...
}

11.非同期タスクの核心API。

  • queueMicrotask
console.log(1);
queueMicrotask(() => {
    console.log(2);
});
console.log(3); // 出力:1 3 2
  • MutationObserver
console.log(1);
// オブザーバーを作成
const obs = new MutationObserver(() => {
    console.log(2);
});
// 要素を作成し監視を追加
const divNode = document.createElement('div');
/*
 * パラメータ1:監視するDOMノード
 * パラメータ2:監視オプション(childListは子ノードの変更を監視)
*/
obs.observe(divNode,{ childList: true });
// 要素の内容を変更
divNode.innerText = 'test123';
console.log(3); // 出力:1 3 2
  • setTimeout
console.log(1);
setTimeout(() => {
    console.log(2);
},1000);
console.log(3); // 出力:1 3 2

12.フロントエンドインターセプター。

  • ルートガード
import { createRouter, createWebHashHistory } from "vue-router";
// ルート
const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        // ログイン画面
        {   
            path: '/login'
            name: 'Login',
            component: () => import("../views/Login.vue"),
        },
        // メイン画面
        {
            path: '/main',
            name: 'Main',
            meta: { requireAuth: true },
            component: () => import("../views/Main.vue"),
        },
    ]
});

/* ルートガード(主にログイン検証に使用)
 * 1.to:目的のルート
 * 2.from:現在のルート
 * 3.next:resolveフックを実行する関数
*/
router.beforeEach((to, from, next) => {
    const isAuthenticated = !!localStorage.getItem('user');
    // ルートにログインが必要だがユーザーが認証されていない場合、ログイン画面にリダイレクト
    if(to.meta.requiresAuth && !isAuthenticated) {
        next({ name: 'Login' });
    } else { // ルートにログイン認証が不要な場合、直接通過
        next();
    }
});
  • AxiosのHTTPインターセプター
const service = axios.create({
    baseURL: "http://" + ipUrl; // ipUrl:バックエンドのIPアドレス
});

// リクエストインターセプター:リクエスト送信前にトリガー
service.interceptors.request.use(config => {
    // 送信リクエストで行うこと
    // ここでリクエストヘッダーのロジックを追加できます。例えばトークンの設定など
    return config;
}, error => {
    // 送信リクエストの失敗を処理
    return Promise.reject(error);
});

// レスポンスインターセプター:レスポンス取得後にトリガー
service.interceptors.response.use(response => {
    // 取得したレスポンスデータを処理
    // ここで実際のバックエンドのレスポンス値に基づいて判断できます。例えばログイン失敗でログインページにリダイレクトなど
    return response.data;
}, error => {
    // レスポンス取得の失敗を処理
    return Promise.reject(error);
})

13.シャローコピーとディープコピーの違いと実装方法。

  • シャローコピー:オブジェクトへのポインタのみをコピーし、オブジェクト自体はコピーせず、新旧オブジェクトが共有メモリ領域を使用します
    • Object.assignを使用して実装
// オブジェクトプロパティに参照型やオブジェクトが存在する場合、そのオブジェクトに対してはシャローコピー
const oldObj = {
    'name': 'sato',
    'scores': {
        'english': 75,
        'math': 85
    }
};
const newObj = Object.assign({}, oldObj);
  • ディープコピー:同一のオブジェクトをコピーして作成し、共有されていないメモリを使用します
    • Object.assignを使用して実装
        // Object.assign()の場合、オブジェクトプロパティ値が単純な型の場合はディープコピー
        const oldObj = {
            'name': 'sato',
            'scores': 75
        };
        const newObj = Object.assign({}, oldObj);
    
    • JSONオブジェクトを使用して実装
        function deepCopy(oldObj) {
            const obj = JSON.stringify(oldObj);
            const newObj = JSON.parse(obj);
            return newObj;
        }
    
    • jQueryextendメソッドを使用して実装
        /* deep:ディープコピーかどうか
         * target:ターゲットオブジェクト
         * obj:objNオプション、最初およびN番目にマージされるオブジェクト
        */
        $.extend([deep], target, obj1, [objN])
    
        const oldObj = [0, 1, 2];
        const newObj = $.extend(true, [], oldObj);
    
    • **concat()**を使用して配列をコピー
        concat(arr1, arr2, ...)
    
        const oldArr = [0, 1, 2];
        const newArr = [].concat(oldArr);
    
    • **slice()**を使用して配列をコピー
        slice(start, end)
    
        const oldArr = [0, 1, 2];
        const newArr = oldArr.slice(0); // [0, 1, 2]
    
    • lodashライブラリの**cloneDeep()**を使用して実装
        // value:コピーする値
        _.cloneDeep(value)
    
        const oldObj = [
            { 'a': 1 },
            { 'b': 2 }
        ];
        const newObj = _.cloneDeep(oldObj);
    
    • **スプレッド演算子...**を使用して実装
        const oldArr = [0, 1, 2];
        const newArr = [...oldArr];
    
  • 再帰を使用してディープコピー関数をカプセル化して実装
function deepCopy(newObj, oldObj) {
    for(var key in oldObj) {
        // 1.プロパティ値を取得
        const item = oldObj[key];
        // 2.配列かどうかを判断
        if(item instanceof Array) {
            newObj[key] = [];
            deepCopy(newObj[key], item);
        } else if(item instanceof Object) {
            // 3.オブジェクトかどうかを判断
            newObj[key] = {};
            deepCopy(newObj[key], item);
        } else {
            // 4.単純なデータ型は直接代入
            newObj[key] = item;
        }
    }
}

14.タスクキュー。

タスクキューはJSエンジンの一種のメカニズムで、非同期タスクとイベントを処理する責務を負っています。タスクキューでは、JSエンジンはタスクを2つのカテゴリに分けます:マクロタスクとマイクロタスク。

  • マクロタスク
    • 同期コード:メインスレッドで実行される同期コード
    • setTimeout/setInterval:タイマーで設定された非同期タスク
    • scriptタグ:scriptタグで導入されたスクリプト
  • マイクロタスク
    • Promise:Promiseで設定された非同期タスク
    • async/await:非同期関数内でawaitキーワードで待機する非同期タスク
    • MutationObserver:DOMツリーの変更を監視する非同期タスク
  • 実行順序
    1. 同期タスクを実行
    2. マイクロタスクキュー内のすべてのマイクロタスクを実行
    3. マクロタスクキュー内のすべてのマクロタスクを実行
    4. レンダリング更新を実行
    5. 1〜4のステップを繰り返す
  • 違い
    1. 実行順序:イベントループの各反復終了時には1回のみマクロタスクを実行し、マクロタスク実行後にマイクロタスクが存在する場合は、すべてのマイクロタスクを即座に実行するため、マイクロタスクはマクロタスクより速く実行されます
    2. 実行タイミング:マクロタスクの実行タイミングは比較的固定されています(例:タイマー、非同期関数など)が、マイクロタスクの実行タイミングはその存在するタスクキューが空かどうかによって決まります。マイクロタスクキューにタスクが残っている場合、これらのタスクは次のマクロタスク実行前にすべて実行されます

15.変数のスコープとその優先順位。

スコープとは、変数と関数が有効な領域のことです。

  1. グローバルスコープ:変数がファイルの先頭から末尾まで有効であるグローバル変数
  2. 関数スコープローカル変数
  3. ブロックスコープ:**{}**で定義された変数で、コードブロック内で有効
  4. 関数の宣言スコープ関数プロトタイプ):変数は宣言の開始から宣言パラメータの終わりまで有効

16.変数ホイスティングの長所と短所。

変数ホイスティングとは、変数の宣言が現在のスコープの先頭に昇格されることです。

  • 長所:
    1. より高い容認性:JSコード実行プロセスで、先に値を代入してから宣言するという誤った書き方でも正しく実行できます
    2. パフォーマンス向上:変数ホイスティングにより、JSコード実行前の構文チェックとコンパイルは一度だけ実行され、関数に対してプリコンパイルコードが生成されます。そのため、コードが変更されていない場合、プリコンパイル中の変数と関数が直接使用され、コード実行時にコンパイルする必要がなくなります
  • 短所:
var text = "suzuki";
function f() {
    // 外層のsuzukiを出力したかったが、変数ホイスティングにより関数内部のtext宣言が関数先頭に昇格する
    // そのため最終的にはundefinedが出力される
    console.log(text);
    if(false) {
        var text = "yamada";
    }
}

17.プロトタイプチェーン。

プロトタイプ関数(またはコンストラクタ)にのみprototype(プロトタイプはオブジェクト)があり、それ以外のコンストラクタからインスタンス化されたオブジェクト(null、undefinedを除く)にはすべて**proto**があります。インスタンス化されたオブジェクトの__proto__はコンストラクタのprototypeと等しい(===関係)で、undefinedとnullはprototypeも__proto__もありません(両方とも関数でも関数からインスタンス化されたオブジェクトでもないため)

プロトタイプチェーン:インスタンス化されたオブジェクトでプロパティにアクセスする際、まずそのオブジェクト内部(自身のプロパティ)を探し、見つからない場合はその**__proto__が指すプロトタイプを探し、それでも見つからない場合はプロトタイプ内の__proto__が指す次のプロトタイプを探し続け、見つかるまたはObject.prototype.proto**(値はnull)に到達するまでこの連鎖的なプロセスが続きます。このような鎖状のプロセスをプロトタイプチェーンと呼びます。

プロトタイプチェーンの役割

  • コードの冗長性を回避し、共通のプロパティとメソッドをプロトタイプオブジェクトに置くことで、そのコンストラクタからインスタンス化されたすべてのオブジェクトがそのプロパティとメソッドを使用できます
  • メモリ使用量を削減します

プロトタイプチェーンの使用場面

  • Object.prototype.toString.call()を使用した型判定
  • Vueプロジェクトでは、通常共通のプロパティをVueプロトタイプに置いたり、プラグインをVueプロトタイプにマウントしたりします

18.letとconstがそれぞれ解決する問題は何ですか?

  • letにはブロックスコープの概念があり、変数の漏洩問題を解決します
for(var i = 0;i < 5;i ++) {
    console.log(i); // 0 1 2 3 4
}
console.log(i); // 5 変数漏洩が発生

for(let i = 0;i < 5;i ++) {
    console.log(i); // 0 1 2 3 4
}
console.log(i); // Uncaught ReferenceError: i is not defined
  • constは定数を定義し、varで定義された値が変更できる問題を解決します

19.Promiseが解決する問題とasync/awaitの役割は何ですか?

Promise

  • コールバック地獄、コードの保守が困難で、最初の関数の出力が2番目の関数の入力になるという現象
  • Promiseは複数の並行リクエストをサポートし、並行リクエストの効果を得ることができます

async/await

  • Promiseの冗長な.then()、.catch()チェーン呼び出しと比較して、async/awaitはコードをより同期プロセスのようにし、エラーハンドリングがより直感的で、可読性も向上します

TypeScript

1.型が確定していない変数をrefで宣言する方法は?

// 入力パラメータから型を推論 Ref<String>
const a = ref('');
// ジェネリクスで明示的に型を指定 Ref<String[]>
const b = ref<String[]>([]);
// 型を指定して宣言 Ref<String[]>
const c: Ref<String[]> = ref([]);
// 型が確定しない場合
type Ref<T = any> = {
   value: T
};
function ref<T>(value: T): Ref<T>;
const count1 = ref(2);
const count2 = ref("2");
console.log(typeof count1.value); // number
console.log(typeof count2.value); // string

2.フォームバリデーションの実装方法は?

<template>
   // el-formを使用し、refと検証ルールrulesをバインド
   <el-form ref="formRef" :model="form" :rules="rules">
       <el-form-item label="ユーザー名">
           <el-input v-model="form.username" />
       </el-form-item>
       <el-form-item label="パスワード">
           <el-input v-model="form.password" />
       </el-form-item>
       <el-button @click="submitForm">送信</el-button>
   </el-form>
</template>

<script setup lang="ts">
import{ FormInstance, FormRules } from 'element-plus';
import{ ref, reactive } from 'vue';

const formRef = ref<FormInstance>();
const form = reactive({
   username: '',
   password: ''
});
// 検証ルールを定義
const rules = reactive<FormRules>({
   username: [
       /**
        * 1.required: true —— 必須項目
        * 2.message —— 空の場合はmessageの情報を表示
        * 3.trigger —— el-selectの場合はtriggerを'change'に設定
       **/
       { required: true, message: '必須項目です', trigger: 'blur' },
       // カスタムルール
       { asyncValidator: validateCheck, trigger: 'blur' }
   ],
   password: [
       { required: true, message: '必須項目です', trigger: 'blur' }
   ]
});
/**
* asyncValidatorでカスタム検証ルールを定義
* function(source, [options], callback): Promise
* 1.source —— 検証するオブジェクト(必須)
* 2.[options] —— 検証処理オプションオブジェクト(オプション)
* 3.callback —— 検証完了時に呼び出されるコールバック関数(オプション)
**/
const validateCheck = async(rule: any, value: any, callback: any) => {
   if(value === '') {
       callback(new Error('ユーザー名は空にできません!'));
   } else {
       callback();
   }
}
// 送信ボタンクリックでトリガー
async function submitForm() {
   await formRef.value?.validate((valid) => {
       if(valid) {
           // 検証が通過した場合、対応するアクションを実行
       }
   })
}
</script>

3.ジェネリクスの役割は何ですか?

ジェネリクスはJava言語の型システムの一つの拡張で、型パラメータ化によるクラスの作成をサポートします。役割は以下の通りです:

  1. 型の安全性(主な目標
  2. キャストの削除
  3. 潜在的なパフォーマンス向上
  4. より良いコードの再利用性

4.interfaceとtypeの違いは何ですか?

  • typeでできるがinterfaceでできないこと
// 1.基本型を宣言できる
type Name = string;
// 2.ユニオン型を宣言できる
type User = string | number;
// 3.タプル型を宣言できる
type User = [number, string];
// 4.typeof演算子を使用して宣言できる
type User = typeof someObj;
  • interfaceでできるがtypeでできないこと
// 宣言を繰り返してもエラーにならない
interface User {
    name: string
}
interface User {
    age: number
}
// マージされて
interface User {
    name: string,
    age: number
}
  • typeは**&で継承を実現し、interfaceはextends**で継承を実現します

Vue

1.Vueのディレクティブとその役割は何ですか?

  • v-for:動的レンダリング、配列の走査
  • v-show:コンテンツの表示
  • v-if:表示と非表示
  • v-on:クリック関数をバインド
  • v-model:主にフォーム要素で双方向データバインディングを実現
  • v-bind:単方向データバインディング
  • v-text:データをレンダリングするがタグを解析しない
  • v-html:データをレンダリングし同時にタグを解析する
  • {{}}(補間式):データをレンダリングするがタグを解析しない

2.v-ifとv-showの違いは何ですか?

  • v-ifはDOMノードの存在有無を制御して要素の表示/非表示を制御し、v-showはDOM要素のdisplayスタイル(blockで表示、noneで非表示)を設定します
  • v-ifの切り替えでは内部のイベントリスナーや子コンポーネントが破棄され再作成されますが、v-showは単純なCSSの切り替えです
  • v-ifは切り替えにおいてよりパフォーマンスを消費しますが、v-showは初期レンダリングにおいてよりパフォーマンスを消費します

3.Vueの一般的な修飾子とその使用場面は何ですか?

修飾子は、DOMイベントの詳細を処理するための記号です。

  • フォーム修飾子:フォーム入力時にinputとv-modelに対するいくつかの修飾
    • .lazy:情報入力が完了しフォーカスが外れた後に入力値をvalueに割り当てる
    • .trim:ユーザー入力の先頭の空白文字を自動的にフィルタリングするが、中間の空白文字はフィルタリングされない
    • .number:ユーザー入力値を自動的に数値型に変換し、この値がparseFloatで解析できない場合は元の値が返される
  • イベント修飾子:イベントのキャプチャおよびターゲットの処理
    • .stop:イベントのバブリングを阻止
    • .prevent:イベントのデフォルト動作を阻止
    • .self:イベントを自身にバインドし、イベントのバブリングを阻止するのと同等
    • .once:イベントバインドを一度だけトリガーする
    • .capture:イベントのトリガーを包含する要素のトップから下へ向かってトリガーするようにする
    • .passive:onscrollイベントに.lazy修飾子を追加したのと同等で、要素のスクロールイベントを監視する際に常にonscrollイベントがトリガーされることでページが遅くなるのを防ぐ(.preventと一緒に使用できない、.preventは無視される)
    • .native:コンポーネントがルート要素のネイティブイベントを監視できるようにする(通常のHTMLタグを操作するとイベントが無効になる
  • マウスボタン修飾子:主に左、右、中クリックに対応
    • .left:左クリック
    • .right:右クリック
    • .middle:中クリック
  • キー値修飾子:キーボードイベント(onkeyuponkeydown)を修飾する
    • .keyCode:特定のキー押下を監視し、以下の2つのカテゴリに分けられる:
      • 通常のキー:enter、tab、delete、space、esc、up、...
      • システム修飾キー:ctrl、alt、meta、shift、...
  • v-bind修飾子
    • .sync:propsに対する双方向バインディング
    • .prop:カスタムタグを設定し、データの露出を避け、HTML構造の汚染を防ぐ
    • .camel:名前をキャメルケースに変換する

4.Vue2とVue3の違いは何ですか?

  • アーキテクチャの設計と実装:Vue2は通常大規模なモノリシックシステムアーキテクチャパターンを使用し、このパターンは開発が困難で保守が難しいですが、Vue3はAPI+TypeScriptを使用したアーキテクチャ設計と実装に傾向しており、コードがより簡潔で構造が明確で、コンポーネント化とモジュール管理が容易です
  • リアクティブシステム:Vue3はProxyプロキシオブジェクトを使用してVue2のObject.definePropertyメソッドを置き換え、より良いパフォーマンスとリアクティブ能力をもたらします
  • パフォーマンス:Vue3は仮想DOMの更新回数を減らし、より効率的なレンダリングを行うことで、Vue2より高速でメモリ使用量が少なくなっています
  • コンパイラ:Vue2は文字列ベースのテンプレートコンパイラを使用しますが、Vue3はコンパイラベースの静的分析を導入し、テンプレートをより高度なレンダリング関数にコンパイルし、より最適化されたコードを生成し、ランタイムのオーバーヘッドを減らし、パフォーマンスを向上させ、バンドルサイズを縮小します
  • ツールチェーン:Vue3は開発者ツールにおいてより強力なデバッグとパフォーマンス分析ツールを提供し、開発者がアプリケーションをより簡単にデバッグし最適化できるようにします
  • コンポーネントインスタンスのマウント:Vue2は手動で$mount()メソッドを呼び出す必要がありますが、Vue3ではデフォルトでコンポーネントインスタンスが自動的にその定義位置に対応するDOM要素にマウントされます
  • 新機能と強化機能:Vue3はComposition API(合成API)を導入し、Vue2のOption API(オプショナルAPI)と比較して、より柔軟なコンポーネントの組み合わせ方式を提供し、コードの可読性と保守性を向上させます
  • TypeScriptサポート:Vue3はTypeScriptに対するサポートがより親和的で、より包括的で正確な型定義を提供します

5.Viteについて。

Viteは現代のブラウザ向け、ES-Moduleに基づくより軽く速いWebアプリケーション開発ツールです。

Viteの特徴

  • 高速なコールドスタート
  • 即時のモジュールホットリロード
  • 真のオンデマンドコンパイル

6.Vueのレンダリングプロセスは?

  1. テンプレートの解析:Vueはまずテンプレートを解析し、**抽象構文木(AST)**を生成します
  2. レンダリング関数の生成:VueはASTに対して静的分析を行い、レンダリング関数(JavaScript関数)を生成します。この関数は仮想DOMツリーを生成するために使用されます
  3. レンダリング関数の実行:コンポーネントの状態が変化すると、Vueはレンダリング関数を再実行し、新しい仮想DOMツリーを生成します
  4. 新旧仮想DOMツリーの比較:VueはDiffアルゴリズムを使用して新旧仮想DOMツリーの差分を検出し、更新する部分を特定します
  5. DOMの更新:Vueは差分に基づきpatch関数を使用して実際のDOMツリーを更新します

7.MVVMパターンを説明してください。

MVVMはModel-View-ViewModelの略で、ユーザーインターフェースを構築するための設計パターンです。ユーザーインターフェースの開発とビジネスロジックの開発を分離することで、コードをよりモジュール化し、保守性を高め、フロントエンド開発プロセスを簡素化します。

View(ビューレイヤー)はViewModelのDOMリスナを介してイベントをModelにバインドし、Model(データモデルレイヤー)はデータバインディングを使用してView内のデータを管理し、ViewModel(ビューモデルレイヤー)は双方向バインディングを介してViewとModelを接続します。

8.VueでのVMの実装原理は何ですか?

  1. まず**Object.defineProperty()**を使用してデータのハイジャックとリアクティブを実現します
  2. 次にVueのrender関数を使用してテンプレートを仮想DOMに変換します
  3. 最後にupdateComponentメソッドを使用して仮想DOMをHTMLにレンダリングします

9.Vue3でのコンポーネント間のデータ受け渡し方法は何がありますか?

  • 親から子へpropsを使用
// 親コンポーネント、動的バインド方式
<template>
    <div>
        <ChildComponent :userName="userName" @click="parentMethod"></ChildComponent>
    </div>
</template>
<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';
import { ref } from 'vue';

const userName = ref('sato');
const parentMethod = () => {
    console.log("親コンポーネントのメソッド");
};
</script>

// 子コンポーネント
<template>
    <div>
        <button @click="childMethod">子コンポーネント</button>
    </div>
</template>
<script setup lang="ts">
// 子コンポーネントで受け取る
const props = defineProps(["userName"]);
const childName = props.userName;
const emits = defineEmits(["parentMethod"]);
const childMethod = () => {
    emits("parentMethod");
}
</script>
  • 子から親へemitsを使用
// 子コンポーネント
<template>
    <div>
        <button>子コンポーネント</button>
    </div>
</template>
<script setup lang="ts">
const emits = defineEmits(["userName"]);
function age() {
    emit('age',18);
};
const childMethod = () => {
    console.log("子コンポーネントのメソッド");
};
// 外部に公開
defineExpose({
    childMethod
});
</script>

// 親コンポーネント
<template>
    <div>
        <button @click="parentMethod">親コンポーネント</button>
        <ChildComponent ref="childRef">{{ userName }}</ChildComponent>
    </div>
</template>
<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';
import { ref } from 'vue';

// 子コンポーネントを宣言
const childRef: any = ref(null);
const parentMethod = () => {
    childRef.value.childMethod();
}
</script>
  • 依存注入provideinjectを使用して祖孫コンポーネント間のデータ受け渡しを実現し、propsの受け渡しが困難な深いコンポーネント階層でも不要な状態管理を避けます。
// 親コンポーネント
import { provide } from 'vue';
provide('userName', 'sato');

// 子コンポーネント
import { inject } from 'vue';
const userName = inject('userName');
  • ブラウザキャッシュsessionStorageを使用
// コンポーネント1
sessionStorage.setItem("user", JSON.stringify(user));

// コンポーネント2
const user = JSON.parse(sessionStorage.getItem("user"));
  • イベントバスmittを使用
// mittのindex.ts
import mitt from "mitt";
const emitter = mitt();
export default emitter;

// コンポーネント1
<template>
    <div>
        {{ count }}
        <ChildPage />
    </div>
</template>
<script setup>
import ChildPage from "./ChildPage.vue";
import emitter from "@/mitt/index";
import { ref } from "vue";

const count = ref(0);
emitter.on("changeCount", (counter) => {
    count.value = counter;
});
</script>

// コンポーネント2
<template>
    <div>
        <button @click="changeCount">ボタン</button>
    </div>
</template>
<script>
import emitter from "../mitt/index";

let a = 0;
const changeCount = () => {
    a ++;
    emitter.emit("changeCount", a);
};
</script>
  • piniaを使用
// storeのindex.ts
import { defineStore } from "pinia";
import { ref } from "vue";
export const useCounterStore = defineStore("counter", () => {
    const count = ref(0);
    const changeCount = () => {
        count.value ++;
    };
    return { count, changeCount };
});

// コンポーネント1
<template>
    <div>
        {{ count }}
        <Child />
    </div>
</template>
<script lang="ts" setup>
import Child from "./Child.vue";
import { useCounterStore } from "../store/index";
import { storeToRefs } from "pinia";

const store = useCounterStore();
const { count } = storeToRefs(store);
</script>

// コンポーネント2
<template>
    <div>
        <button @click="changeCount">ボタン</button>
    </div>
</template>
<script lang="ts" setup>
import { useCounterStore } from "../store/index";

const store = useCounterStore();
const { changeCount } = store;
</script>
  • Vuexを使用
// vuexのindex.ts
import { createStore } from "vuex";

export default createStore({
    state: {
        number: 0,
    },
    getters: {},
    mutations: {
        changeNumber(state, payload) {
            state.number = payload;
        },
    },
    actions: {},
    modules: {},
});

// コンポーネント1
<template>
    <div>
        {{ a }}
        <Child />
    </div>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import { useStore } from "vuex";
import Child from "./Child.vue";

const store = useStore();
const a = computed(() => store.state.number);
</script>

// コンポーネント2
<template>
    <div>
        <button> @click="update">ボタン</button>
    </div>
</template>
<script setup lang="ts">
import { useStore } from "vuex";

const store = useStore();
let a = 0;
const update = () => {
    a ++;
    store.commit("changeNumber", a);
};
</script>
  • 親子コンポーネント間の双方向バインディングv-modelを使用
// 親コンポーネント
<template>
    <div>
        {{ a }}
        <ChildComponent v-model="a" />
    </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const a = ref<number>();
</script>

// 子コンポーネント
<template>
    <div>
        <button @click="update">ボタン</button>
    </div>
</template>
<script setup lang="ts">
import { defineModel } from 'vue';

const a = defineModel({
    type: Number,
    default: 0,
});
const update = () => {
    a.value += 1;
};
</script>

10.Vuexについて。

VuexはVue.jsアプリケーション専用の状態管理パターンで、集中管理によりアプリケーション全体の状態を管理し、複数コンポーネント間のデータ通信を解決します。

Vuexの5つの部分:

  • state:共有データの保存(コンポーネントのdataに相当)
  • mutations:データ変更メソッドの集合(methodsに相当)
  • getters:既存の状態から計算して新しいデータを取得——派生データ(computedに相当)
  • actions:非同期操作
  • modules:モジュール化による分割

11.Webpackと、パッケージングが遅い場合の対策は?

Webpackフロントエンドリソースの読み込み/バンドルツールです。これはモジュールの依存関係に基づいて静的分析を行い、これらのモジュールを指定されたルールに従って対応する静的リソースを生成します。

パッケージング速度を向上させる方法は以下の通りです:

  • Webpackバージョンのアップグレード
  • マルチスレッド/マルチインスタンスビルド
  • オンデマンドバンドル
  • キャッシュの最大限活用
  • DLLの使用
  • resolve.modules設定項目の設定
  • Tree Shakingの使用
  • コードの圧縮

12.画像の遅延読み込み。

画像の遅延読み込みとは、画像がユーザーの視覚領域外にある場合はデフォルトで読み込まず、視覚領域内に入った時に読み込んで表示することです。

// main.js
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyLoad);
const loadimage = require('./assets/loading.gif');
const errorimage = require('./assets/error.gif');
Vue.use(VueLazyLoad, {
   preLoad: 1.3, // 事前ロード高さ比率
   error: errorimage, // 読み込み失敗時の画像パス
   loading: loadimage, // 読み込み中の画像パス
   attempt: 1, // 試行回数
   listenEvents: ['scroll'], // 監視したいイベント
});

// プロジェクト内のimgタグの:src属性をv-lazyに変更
<img v-lazy="'/static/img/' + item.image" alt="">

13.Vueのライフサイクルは?

  • beforeCreate:コンポーネントインスタンスが作成されたばかりで、実行時にはコンポーネントインスタンスはまだ作成されていません。通常はプラグイン開発で初期化タスクを実行するために使用されます
  • created:コンポーネントインスタンスが完全に作成され、初期化が完了した状態です。様々なデータを使用でき、非同期データの取得に使用されます
  • beforeMount:コンポーネントマウント前で、レンダリングや更新が実行されておらず、DOMが作成されていません
  • mounted:コンポーネントインスタンスがDOMにマウントされた後で、初期化が完了し、DOMが作成されています。データとDOM要素へのアクセスに使用できます
  • beforeUpdate:コンポーネントデータが変化し、更新される前で、更新前の様々な状態の取得に使用できます
  • updated:コンポーネントデータが更新された後で、すべての状態が最新です
  • beforeDestroy:コンポーネントインスタンスが破棄される前で、タイマーや購読の解除に使用できます
  • destroyed:コンポーネントインスタンスが破棄された後で、上記と同じ役割を果たします
  • activated:keep-aliveでキャッシュされたコンポーネントがアクティブ化されたときに呼び出されます
  • deactivated:keep-aliveでキャッシュされたコンポーネントが非アクティブ化されたときに呼び出されます
  • errorCaptured:子孫コンポーネントからのエラーをキャプチャしたときに呼び出されます

14.keep-aliveについて。

<keep-alive>は動的コンポーネントをラップすると、非アクティブなコンポーネントインスタンスをキャッシュし、破棄しません。<transition>と同様に、抽象コンポーネントで、自身はDOM要素をレンダリングせず、コンポーネントの親コンポーネントチェーンにも現れません。

<keep-alive>でラップされたコンポーネントの場合:

  • 最初の进入:created --> mounted --> activated
  • 离开:deactivated
  • 再次进入:activated

属性:

  • include:名前が一致するコンポーネントのみがキャッシュされます
  • exclude:名前が一致するコンポーネントはキャッシュされません
  • max:キャッシュできるコンポーネントインスタンスの最大数。この数に達すると、新しいインスタンスが作成される前に、キャッシュされたコンポーネントの中で最もアクセスされていないコンポーネントが破棄されます
  • meta
export default[
    {
        path: '/',
        name: 'home',
        component: Home,
        meta: { keepAlive: true } // キャッシュされるコンポーネント
    },
    {
        path: '/book',
        name: 'book',
        component: Book,
        meta: { keepAlive: false } // キャッシュされないコンポーネント
    },
]

15.仮想DOMについて。

  • 定義:仮想DOMは実際のDOMに対する抽象化レイヤーです
  • 役割:JavaScriptによる実際のDOM操作のパフォーマンス消費を減らし、抽象化されたレンダリングプロセスを提供し、クロスプラットフォームの能力を実現します

16.Vueのリアクティブシステムの原理は?

  • Vue2:
    • データ観測:Vueインスタンス作成時、dataオブジェクトのすべてのプロパティを走査し、Object.definePropertyを使用して各プロパティをリアクティブに変換します。このプロセスはObserverクラスによって完了します
    • 依存収集:テンプレートのレンダリングや計算プロパティの場合、Vueはどのデータがアクセスされたかを追跡します。これはDepクラスとWatcherクラスによって行われ、Watcherはデータを読み取る際に自身をデータの依存リストに追加します
    • データ変更通知:データが変更されると、対応するWatcherは通知を受け取り、ビューの更新をトリガーします
  • Vue3:
    • データラッピング:Vue3では、リアクティブデータはもはや元のオブジェクトではなく、reactive関数でラップされたプロキシオブジェクトです。このプロキシオブジェクトはProxyを使用して作成され、すべての読み取りと書き込み操作をインターセプトできます
    • 読み取り操作の追跡:リアクティブデータのプロパティにアクセスすると、Proxyのgetメソッドが呼び出され、Vueのリアクティブシステムはこの読み取り操作を記録し、現在の副作用関数(effect)に関連付けます
    • 書き込み操作の追跡:リアクティブデータのプロパティを変更すると、Proxyのsetメソッドが呼び出され、Vueのリアクティブシステムはどの副作用関数がこのプロパティに依存しているかをチェックし、それらを更新が必要としてマークします
    • 更新のトリガー:更新が必要としてマークされた副作用関数が実行されると、Vueのスケジューラはそれらが再実行されることを保証し、ビューの更新をトリガーします。このプロセスは通常非同期で行われ、パフォーマンスを向上させます

17.computedとwatchの違いは何ですか?

違い

  1. computedはキャッシュをサポートしており、依存するプロパティ値が変化した場合に計算プロパティは再計算されます。それ以外の場合はキャッシュ内のプロパティ値を使用しますが、watchはキャッシュをサポートせず、対応するプロパティ値が変化すると実行されます
  2. computedは非同期をサポートせず、非同期操作がある場合データ変化を監視できませんが、watchは非同期操作をサポートします
  3. computedは最初の読み込み時監視され、watchはデフォルトで最初の読み込み時には監視されません
  4. computedは計算プロパティで、watchは監視(data内のデータ変化を監視)です
  5. computed内の関数はreturnを呼び出す必要がありますが、watchはそうではありません

使用場面

  • computed:1つのデータが複数のデータに影響を受ける場合(例:ショッピングカートの合計計算)
  • watch:1つのデータが複数のデータに影響を与える場合(データ変化への対応、非同期操作または高パフォーマンス消費操作の実行、watchが最適)、検索データなど

18.v-forにおけるkeyの役割は何ですか?インデックスをkeyとして使用しない理由は何ですか?

keyは各vnodeの一意のIDであり、diffアルゴリズムの一つの最適化戦略で、keyに基づきより正確かつ速く対応するvnodeノードを見つけることができます。

インデックスindexをkey値として使用しないでください。必ず一意の識別値(例:idなど)を使用してください。配列のインデックスindexをkeyとして使用すると、配列の特定の位置に新しい要素を挿入すると、インデックスが再更新され、対応する仮想DOMのkey値もすべて更新され、keyがないのと同じように不要な更新が行われます。したがって、indexはkeyの競合問題を解決できますが、再利用の問題を解決できません。静的データの場合は問題ありません。

ミニプログラム

1.ライフサイクルについて。

ミニプログラム起動後、まずミニプログラムonLaunchonShowが完了し、次にページonLoadonShowonReadyが完了します。ミニプログラムがバックグラウンドに切り替わると、まずページonHideがトリガーされ、次にミニプログラムonHideがトリガーされます。ミニプログラムがフォアグラウンドに切り替わると、まずミニプログラムonShowがトリガーされ、次にページonShowがトリガーされます。

  • onLaunch:ミニプログラムの初期化が完了したときにトリガーされます(グローバルで一度だけ)
  • onShow:ミニプログラムの起動またはバックグラウンドからフォアグラウンドへの切り替え時にトリガーされます
  • onHide:ミニプログラムの非表示またはフォアグラウンドからバックグラウンドへの切り替え時にトリガーされます
  • onReady:ページの初回レンダリング完了
  • onLoad:ページの読み込み
  • onUnload:ページのアンロード
  • onError:ミニプログラムでスクリプトエラーまたはAPI呼び出しが失敗した場合にトリガーされ、エラー情報と共に呼び出されます

コンピュータネットワーク

1.httpとhttpsの違いは何ですか?

http(ハイパーテキスト転送プロトコル)は、分散型、協調型、ハイパーメディア情報システム用のアプリケーション層プロトコルで、webブラウザとウェブサイトサーバー間の情報伝達に使用されます。

https(ハイパーテキスト転送セキュアプロトコル)は、コンピュータネットワークを介した安全な通信のための伝送プロトコルで、httpを介して通信を行いますが、データパケットを暗号化するためにssl/tlsを使用します。

違い

  1. httpは平文で送信され、データはすべて暗号化されていないため、セキュリティが低いですが、httpsデータ送信プロセスは暗号化されており、セキュリティが高いです
  2. httpsプロトコルを使用するにはCA(デジタル証明書認証機関)に証明書を申請する必要があり、無料証明書は少ないため一定の費用がかかります。証明書発行機関は:Symantec、Comodo、GoDaddy、GlobalSignなど
  3. httpページの応答速度はhttpsより速いですが、これはhttpがTCP3ウェイハンドシェイクで接続を確立し、クライアントとサーバーが3つのパケットを交換するのに対し、httpsはTCPの3つのパケットに加え、sslハンドシェイクに9つのパケットが必要なため、合計12個のパケットが必要です
  4. httpとhttpsは完全に異なる接続方式を使用しており、使用するポートも異なります。前者は80、後者は443です
  5. httpsは本質的にssl/tls上に構築されたhttpプロトコルであるため、httpsはhttpより多くのサーバーリソースを消費します

2.httpステータスコードは?

  • 1xx(情報ステータスコード):受信したリクエストが処理中であることを示します
  • 2xx(成功ステータスコード):リクエストが正常に処理されたことを示します
  • 3xx(リダイレクトステータスコード):リクエストを完了するには後続操作が必要であることを示します
  • 4xx(クライアントエラーステータスコード):リクエストに構文エラーまたは完了不可能な内容が含まれていることを示します
  • 5xx(サーバーエラーステータスコード):サーバーがリクエストを処理する際にエラーが発生したことを示します

3.http1.0、http2.0、http3.0の違いは何ですか?

  • http1.0
    • 非永続接続:各リクエスト/レスポンスに新しい接続が必要で、各リクエストで3ウェイハンドシェイクと接続終了のプロセスが必要です
    • リクエスト/レスポンスヘッダーの圧縮をサポートしない:各リクエスト/レスポンスのヘッダー情報は完全に送信されます
    • パイプライン化をサポートしない:クライアントは同時に複数のリクエストを送信できず、前のリクエンスのレスポンスを待ってから次のリクエストを送信する必要があります
  • http2.0
    • バイナリフレーミング:データをより小さなフレームに分割し、マルチプレクシングを使用して同じ接続上で並列に複数のフレームの送受信を行い、伝送効率を向上させます
    • ヘッダー圧縮:HPACKアルゴリズムを使用してリクエスト/レスポンスのヘッダーを圧縮し、データ送信サイズを削減します
    • サーバープッシュ:サーバーはクライアントにリソースをプッシュでき、クライアントからのリクエスト回数を減らします
    • 優先順位と依存関係:リクエストの優先順位と依存関係を指定でき、リソースの読み込み順序を最適化します
  • http3.0
    • QUICを伝送プロトコルとして使用:http3.0はQUIC(Quick UDP Internet Connections)プロトコルに基づいており、TCPを伝送層プロトコルとして置き換えます
    • 改善された輻制御:http3.0はより高度な輻制御アルゴリズムを使用し、ネットワークの安定性とパフォーマンスを向上させます
    • ハンドシェーク遅延の削減:QUICプロトコルは0-RTT(ゼロラウンドトリップタイム)ハンドシェークと高速ハンドシェークリカバリを使用し、ハンドシェークの遅延を削減します
    • パケットロス耐性:QUICプロトコルはより優れたパケットロスリカバリ能力を持ち、失われたパケットをより速く復元できます

Gitバージョン管理

1.Gitの一般的なコマンドは何ですか?

  • git clone:リモートリポジトリのコピー、つまりプロジェクトのダウンロード
  • git push:リモートコードをアップロードしてマージ
  • git add:ファイルをステージングエリアに追加
  • git commit:ステージングエリアをローカルリポジトリにコミット
  • git checkout:ブランチの切り替え
  • git pull:リモートコードをダウンロードしてマージ

2.現在の作業をコミットせずに他のブランチに移動する方法は何ですか?

  • git stash:未コミットの変更を一時的に削除
  • git stash pop:保存された最後の作業状態を復元し、ストレージから削除
  • git stash list:保存されたすべての作業を表示
  • git stash apply <ストレージ名>:保存された対応する作業状態を復元し、ストレージを削除しない
  • git stash clear:保存されたすべての作業をクリア
  • git stash drop <ストレージ名>:対応する特定のストレージを削除

データ構造とアルゴリズム

1.どのようなデータ構造を理解していますか?Vueではどこで使用されていますか?

データ構造:

  • 配列
  • スタック
  • キュー
  • リンクリスト
  • グラフ

Vueでは主にルーティングの遷移でスタックが使用されています:

  • this.$router.push():指定URLに遷移し、historyスタックに新しいレコードを追加し、戻るボタンで前のページに戻ります
  • this.$router.replace():指定URLに遷移し、historyスタックの最後のレコードを置き換え、戻るボタンで前の前のページに戻ります
  • this.$router.go():window.history.go(n)に似ており、nページ前に(nが負の場合)または後(nが正の場合)に遷移します

デザインパターン

1.どのようなデザインパターンを理解していますか?

  • パブリッシュ/サブスクライブパターン
  • オブザーバーパターン
  • シングルトンパターン
  • ファクトリパターン
  • デコレータパターン

MySQL

1.charとvarcharの違いは何ですか?

  1. charは固定の長さを持ち、varcharは可変長の文字型です
  2. ストレージ容量が異なります:charは最大255文字まで保存でき、エンコーディングに関係ありませんが、varcharは最大65532文字まで保存できます。varcharの最大有効長さは最大行サイズと使用されている文字セットによって決まり、全体の最大長さは65532文字です

その他

1.自己紹介。

2.会社についてどのようなことを知っていますか?

3.なぜ遠くの実習先を希望しましたか?

4.いつから働けますか?どれくらいの期間実習できますか?

5.普段どのような方法で学習していますか?

6.希望給与はどれくらいですか?

7.プロジェクト開発でどのような困難に直面しましたか?どのように克服しましたか?

8.なぜフロントエンドの仕事に興味がありますか?

9.サークルや学生会に参加したことはありますか?具体的な業務内容は何ですか?指導的な立場に立ったことはありますか?

10.最も印象に残ったまたは達成感を感じたプロジェクトについて説明してください。

11.互換性の問題に遭遇したことはありますか?

12.どのような最適化を行いましたか?

13.他に質問はありますか?

タグ: フロントエンド Web開発 javascript vue.js CSS

6月5日 16:26 投稿