
この記事では、経験豊富な開発者でさえ答えることができないJavaScriptに関する12の質問について説明します。 最初に、インタビューでよく出てくる質問を含む10の典型的な質問を扱います。 残りの2つの質問は、より複雑で物議を醸すもの、特にWebページのパフォーマンスを改善するJSの使用と、時間の経過とともに関連性を失わないアプリケーションの開発に当てられます。
質問番号1。 プロトタイプ継承とは何ですか?
JavaScriptのほとんどすべてがオブジェクトです。 各オブジェクトには、プロパティとメソッドを継承するプロトタイプがあります。 オブジェクトに要求されたプロパティが含まれていない場合、JavaScriptはオブジェクトのプロトタイプでこのプロパティを検索します。 この場合、必要なものが見つかるまで、プロトタイプチェーンに沿って検索が実行されます。 検索が失敗すると、エラーが返されます。
プロトタイプは、同じプロパティとメソッドを持つオブジェクトを作成するのに非常に役立ちます。 これらすべてをプロトタイプレベルで定義すると、そのようなエンティティのコピーが1つだけ必要になり、メモリを効率的に使用できます。
var parent = {inherit: true} var childA = Object.create(parent); var childB = {}; Object.setPrototypeOf(childB, parent); class childC extends parent {}
Object.create()
コマンドを使用してこれらのオブジェクトを作成するとき、または
Object.create()
コマンドを使用して作成後にオブジェクトにプロトタイプを追加できます。 ES2015標準では、classキーワードが提供されます。また、
extends
コマンドもあり、オブジェクトのプロトタイプとして呼び出されたときに指定された値を使用できます。
質問番号2。 JavaScriptを使用してWebプロジェクトのアクセシビリティを高めるにはどうすればよいですか?
障害を持つ人々がウェブサイトのアクセシビリティを確保するための最新のツールは 、JavaScriptとページの動的コンテンツの処理方法をよく知っています。 JSと動的データの両方をアクセシビリティツールと組み合わせることができますが、この場合は、たとえば、適切な操作に絶対に必要な機能ではなく、プロジェクトの機能を拡張する手段としてスクリプトを使用することが最適であることに留意してください。
ユーザーがサイトで作業できるようにする通常の方法は、対話できるページのオブジェクトをナビゲートする便利な手段を提供することです。 それはフォーカス制御についてです。 たとえば、カレンダーがページに表示される場合、ユーザーは、特に矢印キーを使用して、マウスなしでカレンダーを使用できる必要があります。 つまり、左右の矢印キーを使用して(画面上のカレンダー表示の1行に7日が表示されている場合)日ごとに移動し、キーを上下に移動して週を切り替えることができます。 これは、カレンダーがフォーカスを受けている間にキーボードイベントをリッスンすることで実現されます。
重要なデータの変更がJavaScriptを使用して実装されている場合、たとえば、フィードバックフォームへの入力時に、新しいデータをスクリーンリーダーに送信する必要があります。 多くの場合、これは、対応するコンテナをインタラクティブな領域としてマークすることで実現されます。
質問番号3。 イベントバブリングとは何ですか?また、イベントキャプチャとはどう違いますか?

イベントバブリングは、イベント委任を実装するときに使用されます。 親要素のイベントをサブスクライブすると、その子孫のイベントに関する情報を取得できます
イベントのインターセプトとバブリングはどちらも、イベント配信と呼ばれるプロセスの一部であり、その間にブラウザーはページで発生するイベントに応答します。 古いブラウザはどちらか一方を実行していましたが、最近ではすべてのブラウザがインターセプトとイベントバブリングの両方をサポートしています。
最初のフェーズであるインターセプトフェーズは、イベントが発生した直後に実行されます。 イベントは、イベントに応じて
document
オブジェクトまたは
window
オブジェクトのいずれかである最高レベルで開始され
window
。 ここから、
<html>
とこのタグにあるものを通過し、発生した要素に到達するまで落下します。
次に、第2フェーズ-イベントの上昇が発生します。 その過程で、同じプロセスが繰り返されますが、逆も同様です。 すべてはイベントをトリガーした要素から始まり、ルートの
<html>
要素に「ポップアップ」します。 イベントリスナを追加する場合、これはシステムの動作が予想されるとおりです。
質問番号4。 イベントの委任は、多くのインタラクティブな要素を持つサイトのコードをどのように改善しますか?
多くの場合、Webサイトは常に変化する動的な要素に満ちています。 そのような要素も対話型である必要がある場合、ユーザーが要素と対話するときに発生するイベントを監視する方法が必要になります。 各要素に独自のイベントリスナーが必要な場合、これによりコードが散らばり、ブラウザの負荷が増加します。
イベント委任は、イベントバブリングメカニズムを使用する手法です。 親要素にリスナーを追加することにより、開発者は自分の子孫のイベント処理を設定できます。
parentEl.addEventListener('click', function(e) { if(e.target && e.target.nodeName == 'BUTTON') { // } });
イベントリスナーコールバック関数の内部では、ターゲットイベント要素は
target
パラメーターで表され、これを使用して追加のアクションを決定できます。 たとえば、このパラメーター
data
属性には、オブジェクトのプロパティにアクセスするための識別子を
data
できます。
質問番号5。 クロージャーとは何ですか?また、クロージャーはどのようにコードを整理するのに役立ちますか
JavaScriptの関数は、「レキシカルスコープ」と呼ばれるものを使用します。 これは、それらが含まれるスコープで定義された変数にアクセスできることを意味しますが、関数内で宣言された変数は外部からアクセスできません。
function outer() { let x = 'Web Designer'; function shout() { alert(`I love ${x}!`); } shout(); }
outer()
関数を呼び出すと、「I love Web Designer!」というメッセージが表示されますが、
shout()
関数または
outer()
関数の
outer()
x
変数にアクセスしようとすると、両方とも未定義になります。 クロージャは、関数とその語彙環境の組み合わせです。 この例では、クロージャは
outer()
関数です。
クロージャーは、1つのクロージャー内で宣言されたすべてが他のクロージャーに影響を与えないため、コンポーネントの大きなセットを作成するときに役立ちます。 クロージャーを使用して、Pythonなどの他のオブジェクト指向言語で使用されているものを思い起こさせる方法で、プライベート関数と変数を作成できます。 モジュールモジュールは、クロージャーを広範囲に使用して、モジュールが相互作用する構造化された方法を提供します。
質問番号6。 コードブロックの上部にある「use strict」行の意味は何ですか?
ES5では、strictモードと呼ばれるJavaScriptの特別なバージョンについて説明しています。 厳格モードでは、以前のバージョンの言語のあいまいな構成体を使用すると、予期しない動作が発生する代わりにエラーが発生します。
function strictFunction() { 'use strict'; myVar = 4; //ReferenceError }
上記のコードスニペットでは、未宣言の変数に値を割り当てようとしています。 ストリクトモード以外では、このようなコマンドを実行すると、変数
myVar
がグローバルスコープに追加され
myVar
。これに十分な注意を払わないと、スクリプトの機能が完全に変更される可能性があります。 厳格モードでは、これによりエラーメッセージが表示され、プログラムの誤動作を防ぐことができます。 ES2015モジュールはデフォルトで厳密な厳密モードを使用しますが、関数を使用して作成されたクロージャーでは、
'use strict'
コマンドを関数レベルとファイルレベル全体で使用できます。
質問番号7。 JavaScriptに適用される場合、「変数を上げる」という用語は何を意味しますか?
JavaScriptの機能の1つは、JavaScriptで記述されたプログラムがコンパイルされていない形式で配布されるという事実です。 ブラウザは、「オンザフライ」で言うようにスクリプトをコンパイルし、このプロセス中に、これらのスクリプトで宣言された関数と変数について「メモ」を取ります。
コードを最初に表示した後、ブラウザーは2番目のパスを実行します。これは、プログラムの実行であり、関数と変数が適用される場所を既に認識しています。 コードフラグメントが実行されると、関数と変数の宣言がこのフラグメントの先頭に「上昇」します。
welcome("Matt"); //"Welcome, Matt." function welcome(name) { return `Welcome, ${name}.`; }
この例では、スクリプトの先頭に「上昇」するため、コードで宣言される前に
welcome()
関数を使用できます。
質問番号8。 矢印関数は通常の関数とどのように違いますか?
ES2015は多くの変更を導入しましたが、そのうちの1つは矢印関数の導入でした。
function CountUp() { this.x = 0; setInterval(() => console.log(++this.x), 1000); } var a = new CountUp();
矢印関数と通常の関数の主な違いは、それらがより短いという事実を見ていない場合でも、矢印関数は
this
独自の値を設定しない
this
です。 代わりに、それらは含まれている
this
ブロックの値を使用します。 上記の例では、
this.x
にアクセスすると、1
this.x
ごとに
this.x
数字が表示されます。 同様の状況で通常の関数を使用する場合、値は
undefined
、
NaN
の結論になります。 矢印関数の本体は戻り値です。 これにより、プロミスで矢印関数を使用することが特に便利になります。 通常の関数は、矢印の関数とは異なり、特定の値を明示的に返す必要があります。そうで
undefined
場合は、
undefined
が自動的に返されます。
質問番号9。 どのような状況でletおよびconstキーワードを使用する必要がありますか?
ES2015のもう1つの基本的な革新は、変数を宣言する別の方法として
let
および
const
キーワードを導入したことです。 そのような変数のスコープは、変数が宣言されたブロックに制限されます。 これにより、異なるコードブロックで作成された変数がこれらのブロックの外にあるものに影響を与えないという確信が得られます。
for(let x=1; x<=3; x++) { console.log(x); // 1, 2, 3} console.log(x); // "x is not defined"
プログラムの実行中に変数の値が変わらない場合は、
let
ではなく
const
を使用します。 より正確に「定数」と呼ばれるこのような変数をオーバーライドしようとすると、エラーが生成されます。 このアプローチでは、定数で記述された参照のオブジェクトと配列の内部コンテンツは変更できますが、新しいオブジェクトに置き換えることはできません。
var
キーワードを使用して宣言された変数とは異なり、
let
および
const
を使用して宣言された変数は
const
れないため、初期化される前にアクセスできません。 コードブロックの先頭と変数が初期化される場所の間のスペースは、「一時的なデッドゾーン」と呼ばれ、多くの場合、混乱の原因になります。
質問番号10。 関数型プログラミングとは何ですか?その機能は何ですか?

ネット機能
関数型プログラミングはプログラム開発へのアプローチであり、その本質は、アプリケーションの状態を表すデータが関数のみを使用して処理されることです。 そのような関数が副作用を引き起こさない場合、結果は扱いやすく理解しやすいコードになります。
通常、JSプロジェクトは、オブジェクト指向プログラミングの原則を使用して構築されます。 プログラムの現在の状態に関する情報はオブジェクトに保存され、ページで何かが変更されると、変更に関する情報がこれらのオブジェクトに書き込まれます。
実際、関数型プログラミングは別の考え方です。 F#のような言語は、これらの原則を非常に長い間使用してきたと言わなければなりません。 同時に、ES2015では、JSでの関数型プログラミングの可能性を広げる重要なメカニズムがいくつか登場しました。
Webプロジェクトの開発時に関数型プログラミングの規則に従う場合、すべての操作はいわゆる「純粋な」関数内で実行する必要があることを考慮する必要があります。 これらは、これらの関数の範囲外にあるデータの影響を受けない関数です。 つまり、同じデータがそのような関数を裏切る場合、常に同じ結果を返す必要があります。
さらに、これは、たとえば、アプリケーションの状態を表すなど、関数の外部の特定のデータへの共有アクセスを関数に持たせないことを意味します。 アプリケーションが状態を変更する必要がある場合、パラメータとして関数に渡す必要があります。
最後に、コードでは、既存の値を変更しないようにする必要があります。 たとえば、オブジェクトの変更を伴う操作を実行する場合、値が変更されたこれらのオブジェクトのコピーを返す必要があります。 これは、エラーやコードテストの複雑化につながる副作用を取り除くのに役立ちます。
質問11。 JavaScriptを使用してWebページのパフォーマンスを向上させる方法
現在、ほとんどのWebブラウジングはスマートフォンまたはタブレットから実行されています。 ただし、誰もが最先端のデバイスを持っているわけではありません。 したがって、ページがユーザーのアクションにどれだけ迅速に応答するかが非常に重要です。 サイトの作業における「ブレーキ」は、クライアントを失う可能性があります。 幸いなことに、JavaScriptにはこれを回避するのに役立つツールがあります。
unnecessary不要なスクロール効果を避ける
引き裂かれたスクロールは、ページでいくつかのプログラムアクションが実行されていることを示す明確な兆候です。 場合によっては、ページ上にイベントリスナーが存在するため、ブラウザは強制的に待機します。 そのため、
wheel
や
touchmove
などのイベントはスクロールをキャンセルできます。その結果、標準のスクロール動作が開始される前に、イベントが終了するまでページが強制的に待機されます。
これにより、ページをスクロールするときにジャンプが発生し、速度が一定しなくなるため、ユーザーがページを操作する印象が悪くなります。
document.addEventListener('touchmove', handler, {passive: true});
これを回避するには、イベントリスナーを追加し、3番目のパラメーターとして、
passive
プロパティが
true
設定されたオブジェクトを渡し
true
。 このようなイベントを処理するブラウザは、スクロールに影響を与えないと見なす場合があります。その結果、ページのスクロールは不必要な遅延なしに開始できます。
3番目のパラメーターは、古いブラウザーの
useCapture
オプションを置き換えるため、
useCapture
アプローチまたはそのアプローチを適用する前に、ブラウザーがサポートするものを確認する必要があります。 特定の領域とユーザーとの対話を意図的に無効にするために、ほとんどのブラウザーでは、CSSで
touch-action: none
使用できます。
▍調整イベント
スクロールや要素のサイズ変更などのイベントはできるだけ早く発生するため、すべてのリスナーが関連データを受信します。 各イベントの処理中にリソースを大量に消費する操作が実行されると、すぐにページがフリーズする可能性があります。
const resizeDebounce = debounce(() => { // }, 200); window.addEventListener('resize', resizeDebounce);
イベントの「チャタリング」をなくすことで、頻繁に発生するイベント処理関数を呼び出す頻度を減らすことができます。 このメカニズムの実装と、さまざまなプロジェクトで関数を呼び出す頻度は異なりますが、たとえば、イベント処理の頻度を1秒あたり5回に減らすと、ページのパフォーマンスが即座に向上することがわかります。
▍表示ページエリア
スクロールイベントを使用する一般的な方法は、特定のアイテムがページに表示されるタイミングを検出することです。 「バウンス」を排除する手法を使用しても、
getBoundingClientRect()
呼び出すには、ブラウザーがページ全体のレイアウトを分析する必要があります。
IntersectionObserver
と呼ばれる新しいブラウザーAPIがあります。これは、それによって監視される要素の状態の変化を報告し、表示領域に入るか出るたびに特定の関数を呼び出します。 無限スクロールのページの場合、このAPIを使用して、廃止された視覚要素を削除または再利用に適したものとしてマークできます。
IntersectionObserver
APIは、Safariを除く最近のすべてのブラウザーで使用できます。 同時に、ページ表示領域を操作するための新しい方法論を使用することと、要素の可視性を決定するための古いアプローチとの違いは非常に顕著です。
resourceリソースを集中的に使用する操作を別々のスレッドに割り当てる
大きなデータセットを使用する場合、または画像などの大きなファイルを処理する場合、JavaScriptがブラウザウィンドウをブロックする場合があります。 デフォルトでは、すべてのタスクは単一のスレッドで実行されるため、このスレッドが過負荷になると、アプリケーションインターフェイスはユーザーの影響に応答しなくなります。
特定の操作を完了するのに時間がかかることがわかっている場合は、Webワーカーに配置することを検討するとよいでしょう。 これは、別々のスレッドで実行されるスクリプトの名前です。これらのスクリプトがリソースを大量に消費する操作を実行しても、Webアプリケーションのユーザーインターフェイスは引き続き機能します。 このようなスクリプトは、特別なメッセージングエンジンを使用して相互にデータを送信できます。 WebワーカーはDOMおよび
window
オブジェクトの一部のプロパティにアクセスできません;メッセージングメカニズムは、メインストリームにデータを転送するためにも使用され、インターフェイスに影響を与える可能性があります。
質問番号12。 時間の経過とともに関連性を失わないJSコードを記述する方法
JavaScriptの基本原則の1つは、開発中に、実行可能であれば、以前のバージョン用に記述されたコードを実行できないような変更を行わないことです。 その結果、たとえば、今日開発されたほとんどすべてのコードは、Web開発の世界の多様性を考慮しても、10年後には機能します。
ただし、特定のコードが実行されるということは、時間の経過とともにその関連性が失われないという意味ではありません。 ここで、今日書いたものが数年後にどのように見えるかについて疑問に思う時が来ました。 将来のためにテストする準備ができているプログラムを作成できるようにするいくつかの提案があります。
spaスパゲッティコードを避ける
特定のプロジェクトでの作業の初期段階では、アイデアを魅力的に思えるかもしれません。いわば、コードを小さく独立した部分に分割することなく「すべてを一緒に積み重ねる」ことです。 このアプローチでは、特定のコードで何が行われているのかを簡単に理解できますが、これはプログラムの機能が互いに密接に関連していることも意味します。 そのため、プログラムのどこかで他の部分に実装されているものが必要な場合、コードの対応するセクションがコピーされ、新しいニーズを考慮して書き換えられる可能性があります。 , , , , , , -, .
, , , . , . , «», , , .
▍
, React Polymer, . .
, « »? , , . , , .
, , , , , JavaScript. . , , , .
, . , , , API, , , , Node.
▍
, , , . , , , , , , .
let activeUsers = users.filter(user => user.active === true);
, , , . , , , -
i
j
, .
, , . , . , ESLint, .
▍
, , . . , , , .
, , , . , , , .
, , , . , , , . , , ,
users
, . , , , . , , . , - . — «» , .
▍ ,

Jest , ,
React , . , , , , . — , , , .
. Mocha Jest , . .
, . , , , .
, , . , . — .
▍

Babel
, — . , « », , , , .
, , Babel — , JavaScript . , JS.
ES2015 JS , , . — , . , ES2017, , , , . Babel, , , .
, JS , , , , , .
まとめ
JavaScript, - , , , , . , , , .
親愛なる読者! , JS-, , , . -, ?