每個前端開發者必會的 20 個 JavaScript 面試題
問題1:JavaScript 中 undefined
和 not defined
的區別
JavaScript 未宣告變數直接使用會丟擲異常:var name is not defined
,如果沒有處理異常,程式碼就停止執行了。
但是,使用typeof undeclared_variable
並不會產生異常,會直接返回 undefined
。
var x; // 宣告 x console.log(x); //output: undefined console.log(typeof y); //output: undefined console.log(z); // 丟擲異常: ReferenceError: z is not defined
問題2:下面的程式碼輸出什麼?
var y = 1; if (function f(){}) { y += typeof f; } console.log(y);
正確的答案應該是 1undefined
。
JavaScript中if語句求值其實使用eval
函式,eval(function f(){})
返回 function f(){}
也就是 true
。
下面我們可以把程式碼改造下,變成其等效程式碼。
var k = 1; if (1) { eval(function foo(){}); k += typeof foo; } console.log(k);
上面的程式碼輸出其實就是 1undefined
。為什麼那?我們檢視下 eval()
說明文件即可獲得答案
該方法只接受原始字串作為引數,如果 string 引數不是原始字串,那麼該方法將不作任何改變地返回。
恰恰 function f(){}
語句的返回值是 undefined
,所以一切都說通了。
注意上面程式碼和以下程式碼不同。
var k = 1; if (1) { function foo(){}; k += typeof foo; } console.log(k); // output 1function
問題3:在JavaScript中建立一個真正的private方法有什麼缺點?
每一個物件都會建立一個private方法的方法,這樣很耗費記憶體
觀察下面程式碼
var Employee = function (name, company, salary) { this.name = name || ""; this.company = company || ""; this.salary = salary || 5000; // Private method var increaseSalary = function () { this.salary = this.salary + 1000; }; // Public method this.dispalyIncreasedSalary = function() { increaseSlary(); console.log(this.salary); }; }; // Create Employee class object var emp1 = new Employee("John","Pluto",3000); // Create Employee class object var emp2 = new Employee("Merry","Pluto",2000); // Create Employee class object var emp3 = new Employee("Ren","Pluto",2500);
在這裡 emp1,emp2,emp3都有一個increaseSalary私有方法的副本。
所以我們除非必要,非常不推薦使用私有方法。
問題4:JavaScript中什麼是閉包?寫出一個例子
老生常談的問題了,閉包是在一個函式裡宣告瞭另外一個函式,並且這個函式訪問了父函式作用域裡的變數。
下面給出一個閉包例子,它訪問了三個域的變數
- 它自己作用域的變數
- 父函式作用域的變數
- 全域性作用域的變數
var globalVar = "abc"; // Parent self invoking function (function outerFunction (outerArg) { // begin of scope outerFunction // Variable declared in outerFunction function scope var outerFuncVar = 'x'; // Closure self-invoking function (function innerFunction (innerArg) { // begin of scope innerFunction // variable declared in innerFunction function scope var innerFuncVar = "y"; console.log( "outerArg = " + outerArg + "\n" + "outerFuncVar = " + outerFuncVar + "\n" + "innerArg = " + innerArg + "\n" + "innerFuncVar = " + innerFuncVar + "\n" + "globalVar = " + globalVar); }// end of scope innerFunction)(5); // Pass 5 as parameter }// end of scope outerFunction )(7); // Pass 7 as parameter innerFunction is closure that is defined inside outerFunc
輸出很簡單:
outerArg = 7 outerFuncVar = x innerArg = 5 innerFuncVar = y globalVar = abc
問題5:寫一個mul函式,使用方法如下。
console.log(mul(2)(3)(4)); // output : 24 console.log(mul(4)(3)(4)); // output : 48
答案直接給出:
function mul (x) { return function (y) { // anonymous function return function (z) { // anonymous function return x * y * z; }; }; }
簡單說明下: mul 返回一個匿名函式,執行這個匿名函式又返回一個匿名函式,最裡面的匿名函式可以訪問 x,y,z 進而算出乘積返回即可。
對於JavaScript中的函式一般可以考察如下知識點:
- 函式是一等公民
- 函式可以有屬性,並且能連線到它的構造方法
- 函式可以像一個變數一樣存在記憶體中
- 函式可以當做引數傳給其他函式
- 函式可以返回其他函式
問題6:JavaScript怎麼清空陣列?
如
var arrayList = ['a','b','c','d','e','f'];
怎麼清空 arrayList
方法1
arrayList = [];
直接改變arrayList所指向的物件,原物件並不改變。
方法2
arrayList.length = 0;
這種方法通過設定length=0 使原陣列清除元素。
方法3
arrayList.splice(0, arrayList.length);
和方法2相似
問題7:怎麼判斷一個object是否是陣列(array)?
方法1
使用 Object.prototype.toString 來判斷是否是陣列
function isArray(obj){ return Object.prototype.toString.call( obj ) === '[object Array]'; }
這裡使用call來使 toString 中 this 指向 obj。進而完成判斷
方法二
使用 原型鏈 來完成判斷
function isArray(obj){ return obj.__proto__ === Array.prototype; }
基本思想是利用 例項如果是某個建構函式構造出來的那麼 它的 __proto__
是指向建構函式的 prototype
屬性。
方法3
利用JQuery
function isArray(obj){ return $.isArray(obj) }
JQuery isArray 的實現其實就是方法1
問題8:下面程式碼輸出什麼?
var output = (function(x){ delete x; return x; })(0); console.log(output);
輸出是 0
。 delete
操作符是將object的屬性刪去的操作。但是這裡的 x
是並不是物件的屬性, delete
操作符並不能作用。
問題9:下面程式碼輸出什麼?
var x = 1; var output = (function(){ delete x; return x; })(); console.log(output);
輸出是 1
。delete
操作符是將object的屬性刪去的操作。但是這裡的 x
是並不是物件的屬性, delete
操作符並不能作用。
問題10:下面程式碼輸出什麼?
var x = { foo : 1}; var output = (function(){ delete x.foo; return x.foo; })(); console.log(output);
輸出是 undefined
。x雖然是全域性變數,但是它是一個object。delete
作用在x.foo
上,成功的將x.foo
刪去。所以返回undefined
問題11:下面程式碼輸出什麼?
var Employee = { company: 'xyz' } var emp1 = Object.create(Employee); delete emp1.company console.log(emp1.company);
輸出是 xyz
,這裡的 emp1 通過 prototype 繼承了 Employee的 company。emp1自己並沒有company屬性。所以delete操作符的作用是無效的。
問題12:什麼是 undefined x 1
?
在chrome下執行如下程式碼,我們就可以看到undefined x 1
的身影。
var trees = ["redwood","bay","cedar","oak","maple"]; delete trees[3]; console.log(trees);
當我們使用 delete 操作符刪除一個陣列中的元素,這個元素的位置就會變成一個佔位符。列印出來就是undefined x 1
。
注意如果我們使用trees[3] === 'undefined × 1'
返回的是 false
。因為它僅僅是一種列印表示,並不是值變為undefined x 1
。
問題13:下面程式碼輸出什麼?
var trees = ["xyz","xxxx","test","ryan","apple"]; delete trees[3]; console.log(trees.length);
輸出是5。因為delete操作符並不是影響陣列的長度。
問題14:下面程式碼輸出什麼?
var bar = true; console.log(bar + 0); console.log(bar + "xyz"); console.log(bar + true); console.log(bar + false);
輸出是
1 truexyz 2 1
下面給出一個加法操作表
- Number + Number -> 加法
- Boolean + Number -> 加法
- Boolean + Boolean -> 加法
- Number + String -> 連線
- String + Boolean -> 連線
- String + String -> 連線
問題15:下面程式碼輸出什麼?
var z = 1, y = z = typeof y; console.log(y);
輸出是 undefined
。js中賦值操作結合律是右至左的 ,即從最右邊開始計算值賦值給左邊的變數。
上面程式碼等價於
var z = 1 z = typeof y; var y = z; console.log(y);
問題16:下面程式碼輸出什麼?
var foo = function bar(){ return 12; }; typeof bar();
輸出是丟擲異常,bar is not defined。如果想讓程式碼正常執行,需要這樣修改程式碼:
var bar = function(){ return 12; }; typeof bar();
或者是
function bar(){ return 12; }; typeof bar();
明確說明這個下問題
var foo = function bar(){ // foo is visible here // bar is visible here console.log(typeof bar()); // Work here : ) }; // foo is visible here // bar is undefined here
問題17:兩種函式宣告有什麼區別?
var foo = function(){ // Some code }; function bar(){ // Some code };
foo的定義是在執行時。想系統說明這個問題,我們要引入變數提升的這一概念。
我們可以執行下如下程式碼看看結果。
console.log(foo) console.log(bar) var foo = function(){ // Some code }; function bar(){ // Some code };
輸出為
undefined function bar(){ // Some code };
為什麼那?為什麼 foo 列印出來是 undefined,而 bar列印出來卻是函式?
JavaScript在執行時,會將變數提升。
所以上面程式碼JavaScript 引擎在實際執行時按這個順序執行。
// foo bar的定義位置被提升 function bar(){ // Some code }; var foo; console.log(foo) console.log(bar) foo = function(){ // Some code };
原始碼的輸出合理解釋了。
問題18:下面程式碼輸出什麼?
var salary = "1000$"; (function () { console.log("Original salary was " + salary); var salary = "5000$"; console.log("My New Salary " + salary); })();
輸出是
Original salary was undefined My New Salary 5000$
這題同樣考察的是變數提升。等價於以下程式碼
var salary = "1000$"; (function () { var salary ; console.log("Original salary was " + salary); salary = "5000$"; console.log("My New Salary " + salary); })();
問題19:什麼是 instanceof
操作符?下面程式碼輸出什麼?
function foo(){ return foo; } console.log(new foo() instanceof foo);
instanceof
操作符用來判斷是否當前物件是特定類的物件。
如
function Animal(){ //或者不寫return語句 return this; } var dog = new Animal(); dog instanceof Animal // Output : true
但是,這裡的foo定義為
function foo(){ return foo; }
所以
// here bar is pointer to function foo(){return foo}. var bar = new foo();
所以 new foo() instanceof foo
返回 false
問題20: 如果我們使用JavaScript的”關聯陣列”,我們怎麼計算”關聯陣列”的長度?
var counterArray = { A : 3, B : 4 }; counterArray["C"] = 1;
其實答案很簡單,直接計算key的數量就可以了。
Object.keys(counterArray).length // Output 3
面試題參考自: 21 Essential JavaScript Interview Questions | Codementor
本文給出的面試題答案只是很多合理答案中的幾個,可能會不全面,歡迎大家補充。
由於個人疏忽等原因,本文中難免會存在少量錯誤,歡迎大家批評指正。
相關文章
- 高階前端開發者必會的34道Vue面試題系列(二)前端Vue面試題
- 高階前端開發者必會的34道Vue面試題解析(三)前端Vue面試題
- 每個 Kubernetes 應聘者應該知道的 5 個面試題面試題
- 每個開發者都應該知道的33個JavaScript概念JavaScript
- 必須要會的 50 個 React 面試題React面試題
- 前端必備,JavaScript面試問題及答案前端JavaScript面試
- 2023秋招前端面試必會的面試題前端面試題
- 24 個必知必會的系統管理員面試問題面試
- 前端開發者務必知道的JavaScript技巧前端JavaScript
- 面試:Redis必知必會20問面試Redis
- java面試題總結(開發者必備)Java面試題
- 常見的前端開發:Javascript 面試題及回答策略前端JavaScript面試題
- Java開發者必須掌握的15個框架(20k是小問題)Java框架
- 前端開發面試題前端面試題
- web前端工程師面試題10條必會筆試題Web前端工程師面試題筆試
- 提高前端開發者效率的11個必備的網站前端網站
- 每個 JavaScript 開發者都該瞭解的 ES2018 新特性JavaScript
- Flutter開發者必備面試問題與答案05Flutter面試
- Flutter開發者必備面試問題與答案02Flutter面試
- 26個精選的JavaScript面試問題JavaScript面試
- 20道JavaScript經典面試題JavaScript面試題
- 7個 Javascript 面試題及回答策略JavaScript面試題
- 20道你必須要背會的微服務面試題,面試一定會被問到微服務面試題
- 【分享】每個 Web 開發者在 2021 年必須擁有 15 個 VSCode 擴充套件WebVSCode套件
- 被難倒了! 針對高階前端的8個級JavaScript面試問題前端JavaScript面試
- web前端開發面試題分享Web前端面試題
- Mysql中的筆試和麵試---20個經典面試題MySql筆試面試題
- JavaScript面試的完美指南(開發者視角)JavaScript面試
- 每個 Java 開發者都應該知道的 5 個註解Java
- leetcode我們必知必會的SQL面試題LeetCodeSQL面試題
- 面試常問的20個資料庫高頻面試題詳解!資料庫面試題
- 面試題-JavaScript交換兩個變數的方法面試題JavaScript變數
- 前端高頻面試題JavaScript篇前端面試題JavaScript
- 50個你必須瞭解的Kubernetes面試問題面試
- 24個必須掌握的資料庫面試問題~資料庫面試
- iOS高階開發者面試必過技巧iOS面試
- Redis的三個必知必會的問題Redis
- java開發必須要掌握的20個核心技術Java
- 面試小冊:面試官經常問的十個棘手的 JavaScript 問題面試JavaScript