(JS)_javascript スキルが軽視されることが多い、Web フロントエンドの面接でよくある質問
面試題是招募公司和開發者都非常關心的話題,公司希望透過它了解開發者的真實水平和細節處理能力,而開發者希望能夠最大程度地展示自己的水平(甚至超常發揮)。本文提供了眾多前端開發面試題,無論是招募方或應徵者都值得一看!
前言
年前剛剛離職了,分享下我曾經出過的一道面試題,此題是我出的一套前端面試題中的最後一題,用來考核面試者的JavaScript的綜合能力,很可惜到目前為止的將近兩年中,幾乎沒有人能夠完全答對,並非多難只是因為大多面試者過於輕視他。
題目如下:
function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);} //请写出以下输出结果: Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();
答案是:
function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);} //答案: Foo.getName();//2 getName();//4 Foo().getName();//1 getName();//1 new Foo.getName();//2 new Foo().getName();//3 new new Foo().getName();//3
此題是我綜合之前的開發經驗以及遇到的JS各種坑匯集而成。此題涉及的知識點眾多,包括變數定義提升、this指標指向、運算子優先權、原型、繼承、全域變數污染、物件屬性及原型屬性優先權等等。
此題包含7小問,分別說下。
第一問
先看此題的上半部做了什麼,首先定義了一個叫Foo的函數,之後為Foo創建了一個叫getName的靜態屬性存儲了一個匿名函數,之後為Foo的原型對像新創建了一個叫getName的匿名函數。之後又透過函數變數表達式建立了一個getName的函數,最後再宣告一個叫getName函數。
第一問的 Foo.getName 自然是存取Foo函數上儲存的靜態屬性,自然是2,沒什麼好說的。
第二問
第二問,直接呼叫 getName 函數。既然是直接呼叫就是存取目前上文作用域內的叫getName的函數,所以跟1 2 3都沒什麼關係。此題有無數面試者回答為5。此處有兩個坑,一是變數宣告提升,二是函數表達式。
變數宣告提升
即所有宣告變數或宣告函數都會被提升到目前函數的頂端。
例如下碼:
console.log('x' in window);//true var x; x = 0;
程式碼執行時js引擎會將宣告語句提升至程式碼最上方,變成:
var x; console.log('x' in window);//true x = 0;
函數表達式
var getName 與 function getName 都是宣告語句,差別在於 var getName 是函數表達式,而 function getName 是函數宣告。關於JS中的各種函數創建方式可以看 大部分人都會做錯的經典JS閉包面試題 這篇文章有詳細說明。
函數表達式最大的問題,在於js會將此程式碼拆分為兩行程式碼分別執行。
例如下碼:
console.log(x);//输出:function x(){} var x=1; function x(){}
實際執行的程式碼為,先將var x=1 拆分為var x; 和x = 1; 兩行,再將var x; 和function x(){} 兩行提升至最上方變成:
var x; function x(){} console.log(x); x=1;
所以最終函數宣告的x覆蓋了變數宣告的x,log輸出為x函數。
同理,原題程式碼最終執行時的是:
function Foo() { getName = function () { alert (1); }; return this; } var getName;//只提升变量声明 function getName() { alert (5);}//提升函数声明,覆盖var的声明 Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明 getName();//最终输出4
3 番目の質問
3 番目の質問 Foo().getName(); は、まず Foo 関数を実行し、次に Foo 関数の戻り値オブジェクトの getName 属性関数を呼び出します。
Foo 関数 getName = function () {alert (1) }; の最初の文は、var 宣言がないことに注意してください。そのため、最初に現在の Foo で getName 変数を探します。関数スコープは存在しません。次に、現在の関数スコープの上位層、つまり外側のスコープを調べて、getName 変数が含まれているかどうかを確認します。これが、2 番目の質問のalert(4) 関数です。 function(){alert(1) } への変数。
ここでは、実際に変更された外側スコープの getName 関数を示します。
注: ここでまだ見つからない場合は、ウィンドウ オブジェクトまで検索します。ウィンドウ オブジェクトに getName 属性がない場合は、ウィンドウ オブジェクトに getName 変数を作成します。
その後、Foo関数の戻り値はこうなります。JSのこの問題についてはブログガーデンにすでにたくさんの記事があるので、ここでは詳しく説明しません。
簡単に言うと、関数の呼び出し方法でポイントが決まります。ここでの直接呼び出しメソッドでは、this は window オブジェクトを指します。
Foo 関数は window オブジェクトを返します。これは window.getName() を実行するのと同じであり、ウィンドウ内の getName はalert(1) に変更されているため、最後に 1 が出力されます
ここでは 2 つの知識ポイントを検討します。1 つは変数スコープの問題、もう 1 つはこのポインティングの問題です。
4 番目の質問
getName 関数を直接呼び出します。これは window.getName() と同等です。この変数は Foo 関数の実行時に変更されているため、結果は 3 番目の質問と同じになります。
5 番目の質問
5 番目の質問は new Foo.getName(); で、ここで調べられるのは js の演算子の優先順位の問題です。
js 演算子の優先順位:
上記の表を調べると、ポイント (.) の優先順位が新しい操作よりも高いことがわかります。これは、以下と同等です。
new (Foo.getName)();
です。
コンストラクターの戻り値
最初に Foo のインスタンス化されたオブジェクトを初期化し、次にそのプロトタイプで getName 関数を新しいコンストラクターとして再度使用します。
最終結果は 3 です
ついに
就答案狀況而言,第一問100%都可以回答正確,第二問大概只有50%正確率,第三問能回答正確的就不多了,第四問再正確就非常非常少了。其實此題並沒有太多刁鑽匪夷所思的用法,都是一些可能會遇到的場景,而大多數人但凡有1年到2年的工作經驗都應該完全正確才對。
只能說有些人太急躁太輕視了,希望大家透過此文了解js一些特性。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

この記事では、ブラウザでJavaScriptのパフォーマンスを最適化するための戦略について説明し、実行時間の短縮、ページの負荷速度への影響を最小限に抑えることに焦点を当てています。

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

この記事では、ブラウザ開発者ツールを使用した効果的なJavaScriptデバッグについて説明し、ブレークポイントの設定、コンソールの使用、パフォーマンスの分析に焦点を当てています。

この記事では、ソースマップを使用して、元のコードにマッピングすることにより、Minified JavaScriptをデバッグする方法について説明します。ソースマップの有効化、ブレークポイントの設定、Chrome DevtoolsやWebpackなどのツールの使用について説明します。

エントリーレベルのタイプスクリプトチュートリアルをマスターしたら、TypeScriptをサポートするIDEで独自のコードを作成し、JavaScriptにコンパイルできるはずです。このチュートリアルは、TypeScriptのさまざまなデータ型に飛び込みます。 JavaScriptには、NULL、未定義、ブール値、数字、文字列、シンボル(ES6によって導入)とオブジェクトの7つのデータ型があります。 TypeScriptはこれに基づいてより多くのタイプを定義し、このチュートリアルではすべてを詳細に説明します。 ヌルデータ型 JavaScriptのように、Typescriptのnull

この記事では、Javaのコレクションフレームワークの効果的な使用について説明します。 データ構造、パフォーマンスのニーズ、スレッドの安全性に基づいて、適切なコレクション(リスト、セット、マップ、キュー)の選択を強調しています。 コレクションの使用を効率的に最適化します

このチュートリアルでは、chart.jsを使用してパイ、リング、およびバブルチャートを作成する方法について説明します。以前は、4つのチャートタイプのchart.js:ラインチャートとバーチャート(チュートリアル2)、およびレーダーチャートと極地域チャート(チュートリアル3)を学びました。 パイとリングチャートを作成します パイチャートとリングチャートは、さまざまな部分に分かれている全体の割合を示すのに理想的です。たとえば、パイチャートを使用して、サファリの男性ライオン、女性ライオン、若いライオンの割合、または異なる候補者が選挙で受け取る票の割合を示すことができます。 パイチャートは、単一のパラメーターまたはデータセットの比較にのみ適しています。パイチャートのファンの角度はデータポイントの数値サイズに依存するため、パイチャートは値のあるエンティティをゼロ値で描画できないことに注意してください。これは、割合がゼロのエンティティを意味します
