フロントエンドJSの面接で高頻度の質問まとめに対応した動画解説位置
2023 フロントエンドの高頻度面接の質問 - JS の高頻度面接の質問 (パート 1)_bilibili_bilibili
目次
2. JavaScript にはどのような基本データ型がありますか?
5. if で判定すると js 内のデータが false になる
20. forEach メソッドと map メソッドの違いは何ですか?
1. var let const の違いは何ですか?
- const は定数を定義するため、繰り返し割り当てることはできません。ブロックレベルのスコープでは変数の昇格は許可されません。
- var は変数を定義し、繰り返し宣言できます。var にはグローバル スコープまたは関数スコープがあり、変数のプロモーションもあります。
- Let は変数を定義しますが、それらを繰り返し宣言することはできません。ブロックレベルのスコープでは変数の昇格はありません。
2. JavaScript にはどのような基本データ型がありますか?
- 基本データ型 文字列、数値、ブール値、未定義、Null
- 参照データ型: オブジェクト、配列、関数、日付など。
- Symbol と BigInt は ES6 以降に新たに追加された基本データ型です。
- シンボル
一意の値を指します
-
- BigInt
任意の精度形式で整数を表現できる数値型のデータです。
3. null と未定義の違い
- まず、Unknown と Null はどちらも基本的なデータ型であり、これら 2 つの基本的なデータ型にはそれぞれ、unknown と null という値が 1 つだけあります。
- 未定義の意味は、
未定義: 一般に、変数が宣言されていてもまだ定義されていない場合は、未定義が返されます。
- ヌルの意味は、
空のオブジェクト。Null は主に、初期化としてオブジェクトを返す可能性のあるいくつかの変数に値を割り当てるために使用されます。
4. == と === の違いは何ですか?
- 等号判定に二重等号(==)を使用した場合、両辺の型が不一致の場合、比較前に強制的に型変換が行われます。
- 等しいかどうかを判断するために 3 つの等号 (===) が使用される場合、両側の型が矛盾している場合、型変換は強制されず、直接 false が返されます。
オブジェクト.is()
[]==[]
5. if で判定すると js 内のデータが false になる
- 0、""、false、null、未定義、NaNはfalseと判定される (6)
- 他はすべて真実です
[]==false 和 ![]==false true
最初の []==false は数値 0==0 に変換されます。
2 番目の ![]==false はブール値 false==false に変わります。
[]==[] -- >false
js でブール値が false になる 6 つの状況
以下の6つの値をブール値に変換するとfalse、その他の変換はtrueとなります。
1.未定義 (未定義、値が見つからない場合に表示されます)
2. null (空の値を表します)
3. false (ブール値は false、文字列「false」、ブール値は true)
4. 0 (数値 0、文字列 "0" ブール値は true)
5. NaN (結果が計算できない場合に発生し、「非数値」を示します。ただし、typeof NaN=== 「数値」)
6. ""(ダブルクォーテーション)または''(シングルクォーテーション)(空文字列、途中にスペースがある場合も同様)
空の配列は空のオブジェクトであり、負の値はブール値に変換されて true になることに注意してください。
6. データ型を決定する方法とその違いは何ですか?
データ型の確認方法 |
説明する |
の種類 |
基本データ型を決定する(配列、オブジェクト、nullはオブジェクトと判定される) |
インスタンスの |
参照データ型を決定しますが、基本データ型を決定できません |
constructor |
データの種類を決定する |
Object.prototype.toString.call() |
Object オブジェクトのプロトタイプ メソッド toString を使用してデータ型を決定します。 |
JavaScriptの型判定の4つの方法
一、typeof
typeof は関数ではなく演算子で、その右側に単項式が続き、この式のデータ型を返します。
返される結果は、このタイプの文字列 (すべて小文字) です。
データ型を決定するために使用され、戻り値は 6 [文字列] で、文字列、ブール値、数値、関数、オブジェクト、および未定義です。
console.log(typeof undefined) // undefind
console.log(typeof null) // object
console.log(typeof true) // boolean
console.log(typeof 43) // number
console.log(typeof '21') // string
console.log(typeof {a:1}) // object
console.log(typeof Symbol()) // symbol
console.log(typeof 123n) // bigint
function a() {}
console.log(typeof a) // function
var date = new Date()
var error = new Error()
console.log(typeof date) // object
console.log(typeof error) // object
二、instanceof
instanceof は、A が B のインスタンスであるかどうかを判断するために使用されます。式は次のとおりです: Ainstanceof B。A が B のインスタンスの場合は true を返し、それ以外の場合は false を返します。ここで特に注意が必要なのは、instanceof がプロトタイプを検出することです。
Instanceof はオブジェクトを決定するために使用されます。コード形式は obj1、instanceof obj2 (obj1 が obj2 のインスタンスかどうか) です。Obj2 はオブジェクトでなければなりません。そうでない場合はエラーが報告されます。戻り値はブール値です
平たく言えば、instanceof は、オブジェクトが特定のコンストラクターのインスタンスであるかどうかを比較するために使用されます。instanceof は複雑なデータ型を正確に決定できますが、基本的なデータ型を正確に決定できないことに注意してください。
console.log(12 instanceof Number) // false
console.log('22' instanceof String) // false
console.log(true instanceof Boolean) // false
console.log(null instanceof Object) // false
console.log(undefined instanceof Object) // false
console.log([] instanceof Array) // true
console.log({a: 1} instanceof Object) // true
console.log(json instanceof Object) // true
function a() { }
console.log(a instanceof Function) // true
console.log(new Date() instanceof Date) //true
let reg=new RegExp()
console.log(reg instanceof RegExp) //true
let error=new Error()
console.log(error instanceof Error) // true
3、Object.prototype.toString.call()
toString() は Object のプロトタイプ メソッドであり、このメソッドが呼び出されると、デフォルトで現在のオブジェクトの [[Class]] が返されます。これは [object Xxx] という形式の内部プロパティです。Xxx はオブジェクトのタイプです。
Object オブジェクトの場合、toString() を直接呼び出すと [object Object] が返されます。他のオブジェクトの場合は、正しい型情報を返すために / apply を呼び出す必要があります。
console.log(Object.prototype.toString.call(1)) // [object Number]
console.log(Object.prototype.toString.call(1n)) // [object BigInt]
console.log(Object.prototype.toString.call('123')) // [object String]
console.log(Object.prototype.toString.call(true)) // [object Boolean]
console.log(Object.prototype.toString.call(undefined)) // [object Undefined]
console.log(Object.prototype.toString.call(null)) // [object Null]
console.log(Object.prototype.toString.call({})) // [object Object]
console.log(Object.prototype.toString.call([])) // [object Array]
console.log(Object.prototype.toString.call(function a() {})) // [object Function]
console.log(Object.prototype.toString.call(Symbol())) // [object Symbol]
console.log(Object.prototype.toString.call(Math)) // [object Math]
console.log(Object.prototype.toString.call(JSON)) // [object JSON]
console.log(Object.prototype.toString.call(new Date())) // [object Date]
console.log(Object.prototype.toString.call(new RegExp())) // [object RegExp]
console.log(Object.prototype.toString.call(new Error)) // [object Error]
console.log(Object.prototype.toString.call(window) // [object Window]
console.log(Object.prototype.toString.call(document) // [object HTMLD
四、コンストラクター
コンストラクター属性を使用すると、どのコンストラクターがインスタンス オブジェクトを生成したかを知ることができます。コンストラクタ属性は、プロトタイプ オブジェクトとコンストラクタ関数の関係を表し、プロトタイプ オブジェクトが変更された場合、参照時のエラーを防ぐために、通常はコンストラクタ属性も同時に変更されます。したがって、プロトタイプ オブジェクトを変更するときは、通常、コンストラクター属性のポインティングも同時に変更する必要があります。
constructor属性,可以得知某个实例对象,到底是哪一个构造函数产生的。
constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。所以,修改原型对象时,一般要同时修改constructor属性的指向。
console.log('22'.constructor === String) // true
console.log(true.constructor === Boolean) // true
console.log([].constructor === Array) // true
console.log(document.constructor === HTMLDocument) // true
console.log(window.constructor === Window) // true
console.log(new Number(22).constructor === Number) // true
console.log(new Function().constructor === Function) // true
console.log((new Date()).constructor === Date) // true
console.log(new RegExp().constructor === RegExp) // true
console.log(new Error().constructor === Error) // true
知らせ:
1. Nullとunknownは無効なオブジェクトなのでコンストラクタは存在せず、これら2種類のデータは別の方法で判定する必要があります。
2. 関数のコンストラクターが不安定です。これは主にカスタム オブジェクトに反映されます。開発者がプロトタイプを書き直すと、元のコンストラクターの参照が失われ、コンストラクターはデフォルトのオブジェクトになります。
7. JSガベージコレクション
ガベージ コレクション戦略には 2 つあります。
- マークをクリアします:
マーキング フェーズではすべてのアクティブなオブジェクトにマークが付けられ、クリア フェーズではマークされていないオブジェクト (つまり、非アクティブなオブジェクト) が破棄されます。
- 参照数:
これにより、オブジェクトがオブジェクトとして不要になったかどうか、つまり、そのオブジェクトを参照している他のオブジェクトが存在するかどうかの定義が簡素化されます。オブジェクトを指す参照がない場合 (参照カウントが 0 の場合)、オブジェクトはガベージ コレクション メカニズムによってリサイクルされます。
8. this指向
9. コール、適用、バインド
3つの違い
- 3 つすべてが関数の this オブジェクトを変更できます
- 3 つのうち最初のパラメータは、このオブジェクトが指すオブジェクトです。そのようなパラメータが存在しない場合、またはパラメータが未定義または null の場合、デフォルトでグローバル ウィンドウを指します。
- 3 つともパラメータを渡すことができます。
- call はパラメータ リスト、apply は配列、call と apply は一度に渡されるパラメータです。
- binding はパラメータリストですが、複数の受信パラメータに分割できます。
- バインドはこれをバインドした後に関数を返し、適用してすぐに実行を呼び出します
アプリケーションシナリオ
- call は多くの場合継承を行います。
- apply は、数学的オブジェクトを使用して配列の最大値と最小値を取得するなど、配列に関連することがよくあります。
- bind は関数を呼び出しませんが、タイマー内の this ポインターを変更するなど、this ポインターを変更したい場合があります。
10. クロージャとクロージャの使用シナリオ
クロージャの概念:
クロージャ: 別の関数のスコープ内の変数にアクセスする権利を持つ関数を指します。クロージャを作成する最も一般的な方法は、関数内に別の関数を作成し、別の関数を通じてこの関数のローカル変数にアクセスすることです。クロージャ スコープ チェーンのスコープを突破して、関数内の変数やメソッドを外部に渡すことができます。
クロージャのプロパティ
1. 関数内で関数をネストする 2. 内部関数は外部のパラメーターと変数を参照できる 3. パラメーターと変数はガベージ コレクション メカニズムによってリサイクルされない
閉鎖のメリットとデメリット
- 利点: 変数のライフサイクルを延長し、変数をプライベート化する
- 欠点: クロージャが多すぎるとメモリ リークが発生する可能性があります
クロージャの適用シナリオ
- Ajaxリクエストの成功コールバック
- イベントバインディングコールバックメソッド
- setTimeout のコールバックを遅延する
- 関数内では別の匿名関数が返されます
- 機能制限、手ぶれ補正パッケージモジュール
11. イベントプロキシ/イベント委任とは何ですか?
イベント プロキシ/イベント委任は、イベント バブリングの機能を使用して、複数の要素にバインドされる必要があるイベントをその祖先要素にバインドします。特に子要素を動的に追加する場合、プログラムのパフォーマンスを向上させ、メモリ領域を削減するのに非常に便利です。
12. イベントの勃発を止めるにはどうすればよいですか?
w3c メソッドは e.stopPropagation() です。
e.stopPropagation();
デフォルトイベントを防ぐにはどうすればよいですか?
w 3c のメソッドは e.preventDefault() です
function stopDefault( e ) { e.preventDefault(); }
13. 新しいオペレータの実装原理
- まず、新しい空のオブジェクトが作成されます
- プロトタイプを設定し、オブジェクトのプロトタイプを関数のプロトタイプ オブジェクトに設定します。
- 関数の this がこのオブジェクトを指すようにし、コンストラクターのコードを実行します (この新しいオブジェクトに属性を追加します)。
- 関数の戻り値の型を判定し、値型の場合は作成したオブジェクトを返します。参照型の場合は、この参照型のオブジェクトが返されます。
14. リフローと再描画
要素のサイズ、レイアウト、非表示などの変更により、レンダリング ツリーの一部(またはすべて)を再構築する必要がある場合。これをリフローといいます。すべてのページを少なくとも 1 回リフローする必要があります。これは、ページが初めて読み込まれるときです。リフロー中、ブラウザはレンダー ツリーの影響を受ける部分を無効にし、レンダー ツリーのその部分を再構築します。リフローが完了すると、ブラウザは影響を受けた部分を画面に再描画します。このプロセスを再描画と呼びます。
15. JavaScript プロトタイプ チェーン
まず、次の 3 つの概念を理解します。
- プロトタイプ: プロトタイプ オブジェクト。各関数にはプロトタイプ属性があります。新しいコマンドを通じてオブジェクトがインスタンス化されると、この属性がインスタンスのプロトタイプ オブジェクトになります。
- コンストラクター: コンストラクター。プロトタイプオブジェクトを指すコンストラクター
- __proto__: インスタンス オブジェクトのプロトタイプ
JavaScript では、インスタンス オブジェクトとプロトタイプ間のリンクをプロトタイプ チェーンと呼びます。Javascript 解析エンジンは、オブジェクト プロパティの値を読み取ると、プロトタイプ チェーンに沿って上方向に検索します。最後に見つからなかった場合、プロパティ値は未定義です。最終的にプロパティ値が見つかった場合は、結果が返されます。
16. ディープコピーとシャローコピー
浅いコピーでは、オブジェクトへのポインタのみがコピーされ、オブジェクト自体はコピーされません。古いオブジェクトと新しいオブジェクトは依然として同じメモリを共有します。ただし、ディープ コピーでは同一のオブジェクトが作成され、新しいオブジェクトは元のオブジェクトとメモリを共有せず、新しいオブジェクトを変更しても元のオブジェクトは変更されません。
浅いコピー
//最初のレベルはディープコピーです Object.assign() Array.prototype.slice() //拡張演算子...
ディープコピー
JSON.parse(JSON.stringify())
再帰関数
let obj = {
a: 'hello',
b: [10, 20],
c: { name: 'admin',age:{xx:''} }
}
//定义函数实现深层拷贝
function deepCopy(obj) {
//1. 先判断obj是否存在 是否是对象格式
if (obj === null || typeof obj !== 'object') {
return obj;
}
//2. 创建一个新的容器存储拷贝的数据
let newObj = Array.isArray(obj) ? [] : {};
//3. 遍历对象for循环可以 获取所有的下标keys
let temp=null;// temp键值
//遍历下标 --获取元素的值
for(let key in obj){
temp=obj[key];//键值
//获取键值 存储新的容器里--需要判断当前的键值的类型是不是对象
if(temp && typeof temp ==='object'){
newObj[key]=deepCopy(temp)
//newObject={a:hello,b}
}else{
//键值是基本数据类型可以直接存储
newObj[key]=temp;
}
}
return newObj;
}
let obj2=deepCopy(obj)
17. アレイの重複排除
- es6 setメソッドを使用する
[...新しいセット(arr)]
arr = [1,2,3,4,3,2,3,4,6,7,6] とします。let unique =(arr)=>[...newSet(arr); unique(arr);//[1,2,3,4,6,7]
- 新しい配列 IndexOf を使用して ind exOf() メソッドを見つけ、配列内で指定された要素が最初に出現する位置を返します。そうでない場合は、-1 を返します。
- for 二重ループは、第 2 レベルのループに重複排除された配列内の要素が含まれているかどうかを判断します。含まれている場合は、第 2 レベルのループを終了します。j==result.length がない場合は等しくなります。その後、対応する要素を最終配列に追加します。
18. 配列メソッド
配列メソッド |
説明する |
地図 |
配列を走査し、コールバックの戻り値で構成される新しい配列を返します。 |
それぞれに |
ブレークできません。try/catch で throw new Error を使用して停止できます。 |
フィルター |
フィルター |
いくつかの |
1 つの項目が true を返した場合、全体は「true」になります |
毎 |
1 つの項目が false を返した場合、全体は「false」になります |
参加する |
連結文字を指定して文字列を生成する |
プッシュ/ポップ |
最後にプッシュおよびポップすると、元の配列が変更されます。Push は配列の長さを返し、pop は元の配列の最後の項目を返します。 |
シフトを解除する / シフトする |
ヘッドをプッシュおよびポップして元の配列を変更し、unshift は配列の長さを返し、shift は元の配列の最初の項目を返します。 |
並べ替え(fn) / 逆順 |
並べ替えと反転、元の配列の変更 |
連結 |
元の配列に影響を与えずに配列を接続、浅いコピー |
スライス(開始、終了) |
元の配列を変更せずに、新しい切り詰められた配列を返します。 |
splice(開始、番号、値...) |
削除された要素で構成される配列を返します。値は挿入された項目で、元の配列を変更します。 |
IndexOf / lastIndexOf(値, fromIndex) |
配列項目を検索し、対応する添字を返します。 |
Reduce / ReduceRight(fn(prev, cur),defaultPrev) |
ペアで実行します。prev は最後の簡易関数の戻り値、cur は現在の値です。defaultPrev が渡された場合は最初の項目から開始され、渡されなかった場合は 2 番目の項目から開始されます。 |
19. アロー関数と通常の関数の違い
- アロー関数は通常の関数よりも簡潔です
- アロー関数には独自の this がありません。
- アロー関数によって継承されるこの点は決して変更されません。
- アロー関数はコンストラクターとして使用できません
- アロー関数には独自の引数がありません
- アロー関数にはプロトタイプがありません
- call()、apply()、bind() などのメソッドは、アロー関数でこの方向を変更できません。
20. forEach メソッドと map メソッドの違いは何ですか?
- forEach() メソッドは、各要素に対して提供された関数を実行し、データに対する操作により元の配列が変更されます。このメソッドには戻り値がありません。
- map() メソッドは元の配列の値を変更せず、新しい配列を返します。新しい配列の値は、関数呼び出し後の元の配列の値です。
知らせ:
- forEach() は元の配列のメソッドを変更します
- パラメータ: 項目配列内の現在の項目、現在の項目のインデックス、配列の元の配列。
- 配列には複数の項目があるため、渡された匿名コールバック関数を数回実行する必要があります。
使用シナリオ: 配列の要素を処理するとき (例: 要素の追加、要素値の変更)、この関数を使用できます。
知らせ:
項目配列内の現在の項目、現在の項目のインデックス、配列の元の配列
Map のコールバック関数は戻り値をサポートしています。返される内容は、配列内の項目を変更するのと同等です (元の配列には影響しませんが、元の配列を複製するのと同等です。複製された項目は、配列内の対応する項目です)コピーは変更されました);
map は元の配列のメソッドを変更します。
マップの実行速度は速く、forEach よりも 70% 高速です。
使用するシーン:
Map はデータ値を変更する場合に適しており、高速であるだけでなく、新しい配列を返すため、再利用性 (map()、filter()、reduce()) およびその他の組み合わせが向上します。
var arr = [1, 2, 3, 4, 5]; var newArr = arr.map(num => num * 2).filter(num => num > 5); // newArr = [6, 8, 10]
要約:
- forEach()でできることはmap()でもできます。その逆もまた真です
- map() は新しい配列を格納するためのメモリ領域を割り当ててそれを返しますが、forEach() は配列を返しません。
- forEach() を使用すると、コールバックで元の配列の要素を変更できます。そして、map() は新しい配列を返します
21. for...in と for...of の違い
- for...of はオブジェクトのキー値を取得するために走査し、for...in はオブジェクトのキー名を取得します。
- for... in はオブジェクトのプロトタイプ チェーン全体を走査しますが、パフォーマンスが非常に低いため推奨されません。一方、 for... of は現在のオブジェクトのみを走査し、プロトタイプ チェーンを走査しません。
- 配列トラバーサルの場合、for...in は配列内のすべての列挙可能な属性 (プロトタイプ チェーン上の列挙可能な属性を含む) を返しますが、for...of は配列の添字に対応する属性値のみを返します。