你應該知道25道JavaScript面試題

2021-02-19 UI設計自學平臺

這種模式對前端童鞋要求不是特別高,會設計,切圖,就差不多了,什麼前端組件化,模塊化,自動化這些概念都沒有,可能是小公司沒有接觸到,大公司應該很早就開始實踐了。那個時候常用的就是yahoo的yui,和jquery ui還有jquery一系列插件了等等

What is a potential pitfall with using typeof bar === "object" to determine if bar is an object? How can this pitfall be avoided?

老生常談的問題,用 typeof 是否能準確判斷一個對象變量,答案是否定的,null 的結果也是 object,Array 的結果也是 object,有時候我們需要的是 「純粹」 的 object 對象。

如何規避這個問題?

var obj = {};

// 1

console.log((obj !== null) & (typeof obj === "object") && (toString.call(obj) !== "[object Array]"));

// 2

console.log(Object.prototype.toString.call(obj) === "[object Object]");

What will the code below output to the console and why?

(function(){

var a = b = 3;

})();

console.log("a defined? " + (typeof a !== 'undefined'));

console.log("b defined? " + (typeof b !== 'undefined'));

這題不難,IIFE 中的賦值過程其實是(賦值過程從右到左):

(function(){

b = 3;

var a = b;

})();

接下去就不難了,a 是局部變量,b 是全局變量。

What will the code below output to the console and why?

var myObject = {

foo: "bar",

func: function() {

var self = this;

console.log("outer func: this.foo = " + this.foo);

console.log("outer func: self.foo = " + self.foo);

(function() {

console.log("inner func: this.foo = " + this.foo);

console.log("inner func: self.foo = " + self.foo);

}());

}

};

myObject.func();

前面兩個輸出沒有問題,都是 bar,問題出在後面兩個。用了 IIFE 後,匿名函數內的 this 其實已經指到了 window,所以第三個輸出 this.foo 其實是 window.foo,而全局對象並沒有 foo 這個 key,所以輸出 undefined,而第四個輸出,因為 self 引用了 myObject,所以還是 bar。

What is the significance of, and reason for, wrapping the entire content of a JavaScript source file in a function block?

為什麼要用 IIFE?

簡單來說就是為了能模塊化,創建私有變量等等,很多類庫(比如 jQuery)都用了這樣的寫法。

可以參考我以前翻譯的一篇文章 詳解javascript立即執行函數表達式(IIFE)

What is the significance, and what are the benefits, of including 『use strict』 at the beginning of a JavaScript source file?

嚴格模式下進行 Javascript 開發有啥好處?

這個就不展開來了,可以參考阮一峰老師的 Javascript 嚴格模式詳解 或者自行谷歌百度。

Consider the two functions below. Will they both return the same thing? Why or why not?

function foo1()

{

return {

bar: "hello"

};

}

function foo2()

{

return

{

bar: "hello"

};

}

執行以上兩個函數,會返回相同的東西嗎?

不會,第二個函數會返回 undefined。這是由於 Javascript 的封號插入機制決定的,如果某行代碼,return 關鍵詞後沒有任何東西了,將會自動插入一個封號,顯然 foo2 函數中,當 return 後被插入一個封號後,儘管後面的語句不符合規定,但是因為沒有執行到,所以也不會報錯了。沒有 return 任何東西的函數,默認返回 undefined。

所以很多 Javascript 規範建議把 { 寫在一行中,而不是另起一行。

What is NaN? What is its type? How can you reliably test if a value is equal to NaN?

NaN 是什麼鬼?typeof 的結果是?如果一個變量的值是 NaN,怎麼確定?

NaN 是 『not a number』 的縮寫,表示 「不是一個數字」,通常會在運算過程中產生:

console.log('abc' / 4);

console.log(4 * 'a');

雖然它 「不是一個數字」,但是 NaN 的 typeof 結果卻是 number:

console.log(typeof (4 * 'a')); // number

NaN 和任何變量都不相等,包括 NaN 自己:

console.log(NaN === NaN); // false

判斷一個變量是不是 NaN 可以用 isNaN() 函數,但是這 並不是一個完美的函數,有些時候用 value !== value 似乎更準確,幸運的是,ES6 已經有 Number.isNaN() 方法,將比 isNaN() 準確的多。

What will the code below output? Explain your answer.

console.log(0.1 + 0.2);

console.log(0.1 + 0.2 == 0.3);

上面代碼的輸出結果是什麼?

這個問題正好我之前研究過,有興趣的可以參考下 【0.1 + 0.2 = 0.30000000000000004】該怎樣理解?,看懂了還有興趣的可以看下這篇 玉伯的一道課後題題解(關於 IEEE 754 雙精度浮點型精度損失)

Discuss possible ways to write a function isInteger(x) that determines if x is an integer.

寫一個方法 isInterger(x),可以用來判斷一個變量是否是整數。

ES6 中自帶了 Number.isInteger() 方法。但是目前 ES5 中沒有自帶的方法,可以把一個數去掉小數點後和原數進行比較,判斷是否相等,那麼問題就演變成如何對一個數進行取整了。

var a = -1.2223;

console.log(a ^ 0); // -1

console.log(a | 0); // -1

console.log(a > 0); // -1

console.log(Math.round(a)); // -1

console.log(Math.floor(a)); // -2

console.log(Math.ceil(a)); // -1

In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?

(function() {

console.log(1);

setTimeout(function(){console.log(2)}, 1000);

setTimeout(function(){console.log(3)}, 0);

console.log(4);

})();

以上代碼的輸出結果是?

這題不難,只要知道 Javascript 是單線程的語言, 一些異步事件是在主體 js 執行完之後執行即可,所以主體的 1、4 先輸出,而後是 3、2,沒有問題,因為 3 的定時設置比 2 早。

具體可以參考我之前的文章 從setTimeout談JavaScript運行機制

十一

Write a simple function (less than 80 characters) that returns a boolean indicating whether or not a string is a palindrome.

判斷一個字符串是不是回文。

function isPalindrome(str) {

str = str.replace(/W/g, '').toLowerCase();

return (str == str.split('').reverse().join(''));

}

這裡想到一個進階題,求字符串最長回文子串,可以參考 求最長回文子串 – leetcode 5. Longest Palindromic Substring

十二

Write a sum method which will work properly when invoked using either syntax below.

console.log(sum(2,3)); // Outputs 5

console.log(sum(2)(3)); // Outputs 5

寫一個 sum 方法,使得以上代碼得到預期結果。這題可以參考我以前的文章 湯姆大叔的6道javascript編程題題解 中的最後一題,理論上此題更簡單,因為它沒要求能擴展(比如 sum(2)(3)(4)),甚至可以這樣:

function sum(x) {

if (arguments.length == 2) {

return arguments[0] + arguments[1];

} else {

return function(y) { return x + y; };

}

}

或者這樣:

function sum(x, y) {

if (y !== undefined) {

return x + y;

} else {

return function(y) { return x + y; };

}

}

十三

Consider the following code snippet:

for (var i = 0; i < 5; i++) {

var btn = document.createElement('button');

btn.appendChild(document.createTextNode('Button ' + i));

btn.addEventListener('click', function(){ console.log(i); });

document.body.appendChild(btn);

}

(a) What gets logged to the console when the user clicks on 「Button 4」 and why?

(b) Provide one or more alternate implementations that will work as expected.

點擊 『Button 4′ 後輸出什麼?如何使得輸出能跟預期相同?

答案是輸出 5,事實上點擊任意的 button,輸出都是 5。因為循環結束後,i 值變成了 5。如何改,使得輸出分別是 0, 1, 2, 3, 4?用閉包在內存中保存變量,可以參考我之前的文章 這10道javascript筆試題你都會麼 中的第 8 題。

十四

What will the code below output to the console and why?

var arr1 = "john".split('');

var arr2 = arr1.reverse();

var arr3 = "jones".split('');

arr2.push(arr3);

console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));

console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));

上面代碼輸出是?

這道題我答錯了,忽略了 reverse() 方法的一個要重性質,reverse() 方法執行的結果並不是創建一個副本,而是在原數組上直接操作,並返回該數組的引用。

知道了這一點,該題也就迎刃而解了。arr2 其實和 arr1 引用了同一個對象,所以在 arr2 上的操作也會同時反映到 arr1 上。

十五

What will the code below output to the console and why ?

console.log(1 + "2" + "2");

console.log(1 + +"2" + "2");

console.log(1 + -"1" + "2");

console.log(+"1" + "1" + "2");

console.log( "A" - "B" + "2");

console.log( "A" - "B" + 2);

以上代碼輸出什麼?

+」2″ 能將字符串 「2″ 轉換成整數 2,-」2″ 同理,而兩個變量進行 「+」 運算時,如果都是數字和字符串,則分別進行數字相加和字符串拼接,如果一個是數字一個是字符串,則將數字轉為字符串,如果是 「-」 運算呢?則將字符串轉為數字。

「A」 – 「B」 會返回 NaN,因為 「A」 和 「B」 無法轉成數字進行運算,這裡不要以為 「A」 和 「B」 能轉為 ASCII碼 進行運算(不要和 C 語言搞混了)。而 NaN 和字符串相加,會轉成 「NaN」 和字符串去拼接,NaN 和任何數字相加結果還是 NaN。

十六

The following recursive code will cause a stack overflow if the array list is too large. How can you fix this and still retain the recursive pattern?

var list = readHugeList();

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item...

nextListItem();

}

};

以上代碼可能會由於遞歸調用導致棧溢出,如何規避這個問題?

首先,任何遞歸都可以用迭代來代替,所以改寫成迭代方式肯定沒有問題。

而原文給的解答令人深思:

var list = readHugeList();

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item...

setTimeout( nextListItem, 0);

}

};

利用 setTimeout 的異步性質,完美地去除了這個調用棧。

如果你還是摸不著頭腦,簡單舉個慄子:

var list = [0, 1];

var nextListItem = function() {

var item = list.pop();

if (item) {

nextListItem();

}

console.log(item);

};

nextListItem();

上面的代碼會依次輸出 0 和 1,因為程序中形成了一個調用棧,1 被壓到了棧底,最後出棧。

把程序改成這樣:

var list = [0, 1];

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item...

setTimeout( nextListItem, 0);

}

console.log(item);

};

nextListItem();

這回就是 1 和 0 了,因為 setTimeout 的回調只有當主體的 js 執行完後才會去執行,所以先輸出了 1,自然也就沒有棧這一說法了。

事實上,並不是所有遞歸都能這樣改寫,如果下一次遞歸調用依賴於前一次遞歸調用返回的值,就不能這麼改了。

十七

What is a 「closure」 in JavaScript? Provide an example.

談談閉包。

以前也寫過幾篇文章,可以參考下 閉包初窺 以及 閉包拾遺 & 垃圾回收機制。

十八

What will be the output of the following code:

for (var i = 0; i < 5; i++) {

setTimeout(function() { console.log(i); }, i * 1000 );

}

以上代碼輸出什麼?如何能輸出期望值?

很顯然,輸出都是 5。這題和第十三題有些類似,用立即執行函數+閉包即可。

for (var i = 0; i < 5; i++) {

!function(i) {

setTimeout(function() { console.log(i); }, i * 1000 );

}(i)

}

還有種優雅的解法,使用 bind:

for(var i = 0; i < 5; i++) {

setTimeout(console.log.bind(console, i), i * 1000);

}

十九

What would the following lines of code output to the console?

console.log("0 || 1 = "+(0 || 1));

console.log("1 || 2 = "+(1 || 2));

console.log("0 & 1 = "+(0 && 1));

console.log("1 & 2 = "+(1 && 2));

以上代碼輸出什麼?

|| 和 && 是短路運算符。先說說 ||,如果前面變量值為 false(包括 0、null、undefined、flase、空字符串等等),則返回後面變量值,否則返回前面變量值。&& 恰恰相反,如果前面變量為 false,則返回前面變量值,否則返回後面變量值。

注意不要和位運算操作符 | 以及 & 搞混淆了。

二十

What will be the output when the following code is executed? Explain.

console.log(false == '0')

console.log(false === '0')

== 和 === 的區別, 後者是全等,只有兩個值完全相同(或者兩個對象引用相同)時,才會返回 true,而前者在比較時會進行隱式的轉換。

二十一

What is the output out of the following code? Explain your answer.

var a={},

b={key:'b'},

c={key:'c'};

a[b]=123;

a[c]=456;

console.log(a[b]);

一道有趣的題目,答案是 456。

我們知道,Javascript 中對象的 key 值,一定會是一個 string 值,如果不是,則會隱式地進行轉換。當執行到 a[b]=123] 時,b 並不是一個 string 值,將 b 執行 toString() 方法轉換(得到 「[object Object]「),a[c] 也是相同道理。所以代碼其實可以看做這樣執行:

var a={},

b={key:'b'},

c={key:'c'};

// a[b]=123;

a["[object Object]"]=123;

// a[c]=456;

a["[object Object]"]=456;

console.log(a["[object Object]"]);

這樣就一目了然了。

二十二

What will the following code output to the console:

console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10))

輸出什麼?

其實可以寫成這樣,清楚些:

var ans = (function f(n){

return ((n > 1) ? n * f(n-1) : n)

})(10);

console.log(ans);

其實就是一個立即執行函數+遞歸,求個階乘而已(10!)。給立即執行函數加了個名字 f,方便在遞歸裡調用,其實完全可以用 arguments.callee 代替:

var ans = (function(n){

return ((n > 1) ? n * arguments.callee(n-1) : n)

})(10);

console.log(ans);

二十三

Consider the code snippet below. What will the console output be and why?

(function(x) {

return (function(y) {

console.log(x);

})(2)

})(1);

輸出什麼?

顯然是 1,閉包,能引用函數外的變量。

改成這樣呢?

(function(y) {

return (function(y) {

console.log(y);

})(2)

})(1);

二十四

What will the following code output to the console and why:

var hero = {

_name: 'John Doe',

getSecretIdentity: function (){

return this._name;

}

};

var stoleSecretIdentity = hero.getSecretIdentity;

console.log(stoleSecretIdentity());

console.log(hero.getSecretIdentity());

What is the issue with this code and how can it be fixed.

執行第一次輸出時,this 指向了 window,如何規避這個問題?用 bind 綁定 this 指向,具體可以參考 ECMAScript 5(ES5)中bind方法簡介備忘,注意低版本 IE 的兼容。

var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);

二十五

Create a function that, given a DOM Element on the page, will visit the element itself and all of its descendents (not just its immediate children). For each element visited, the function should pass that element to a provided callback function.

The arguments to the function should be:

遍歷 DOM 樹,不難,深度優先搜索即可。

function Traverse(p_element,p_callback) {

p_callback(p_element);

var list = p_element.children;

for (var i = 0; i < list.length; i++) {

Traverse(list[i],p_callback); // recursive call

}

}

這道題可以拓展,先序遍歷 DOM樹,中序遍歷,甚至後序遍歷的結果是?具體可以參考前文 二叉樹三種遍歷的遞歸和迭代解法,都是樹,原理是一樣一樣的。

想認識志同道合的朋友一起學習web

加入我們的學習QQ群 190166743

豐富的學習資源,周一到周四免費直播公開課


長按圖片,識別二維碼即可入群


相關焦點

  • 你必須要知道的JavaScript數據結構與面試題解答
    也許你只是從數據結構入手,或者你已經編碼多年,只需要複習一下。今天,我們將帶你了解JS開發人員都需要知道的7個JavaScript數據結構。高層數據結構是用於存儲和組織數據的技術,這些數據使修改,導航和訪問變得更加容易。數據結構決定了如何收集數據,我們可以用來訪問數據的功能以及數據之間的關係。數據結構幾乎用於計算機科學和編程的所有領域,從作業系統到基本的編碼再到人工智慧。
  • 你有必要知道的 25 個 JavaScript 面試題
    如果你知道閉包,也很容易解決的:(function(test) {            console.log("inner func:  this.foo = " + test.foo);  //'bar'            console.log("inner func:  self.foo = " + self.foo);}(self));
  • 這10個JavaScript面試題,看看你會幾個?
    英文| https://medium.com/javascript-in-plain-english/10-javascript-interview-questions-for
  • iOS 面試之道:117 道 iOS 面試題全解析
    對於讀者而言,購買一本實體技術書,除了攜帶不方便,代碼閱讀困難外,還幾乎和書籍作者隔絕了交流,大家都知道任何一本技術書籍都無法做到 100% 完美,而一本實體書一旦印刷出來就註定無法更新。《iOS 面試之道》分為三個部分,其中面試準備部分由唐巧老師創作,算法和 iOS 專業問答部分則是故胤道長完成,全書通過 117 道 iOS 面試題全解析系統的整理了 iOS
  • 2020國家公務員面試一般幾道題 多長時間
    四、海事局基本考情1.面試形式:結構化面試。2.面試題量:每天一套題,每套4—5道題目。3.面試時間:一般為20—25分鐘,提前5分鐘提醒。4.考查方式:一般採用聽題,大材料題場外看材料,微材料題場內看題,視頻題目會提供電腦設備進行觀看。
  • leetcode 刷500道題,筆試/面試穩嗎?
    如果我在 leetcode 堅持刷它個 500 道題,以後筆試/面試穩嗎?這裡我說下我的個人看法,我認為不穩。下面說說為啥不穩以及算法題應該如何刷、如何學才比較好,當然,也會推薦自己學過的資料。一、先說說筆試題在刷 leetcode 的時候,你會發現,每道題的題意都很短,你只需要花十幾秒的時間,就知道這道題是要你幹嘛了,並且每道題所用道的算法思想都很明確,動態規劃、遞歸、二分查找等,你可能很快就知道該用哪種方法,只是你不懂如何把代碼寫出來而已。
  • 一道面試題,看一線碼農應該具備的基本素質
    面試官出一道題目,候選人 A 可能曾經做過或見過, 所以比較輕鬆地回答出這個問題,而候選人 B 沒有做過,雖然不能給出讓面試官滿意的答案,但 B 提供了一些解題的思路。雖然最終並沒有答出這道題目, 但並不能說 B 的能力就比 A 差。額, 發現編不下去了,直接上本文 title 裡所指的題目吧, 這道題目是我經常出的一道面試題。
  • 從一道面試題談談一線大廠碼農應該具備的基本能力
    剛開始看這個條件當然好,但如果這個不等式沒有思路可以先放一放,沒必要在那苦熬。面試官:這樣吧,如果我問題 根號10 等於多少?你怎麼回答?求職者:3點幾吧。面試官:你怎麼知道是3 點幾,因為你知道9開根號是3,想像一下,你也可以完全用程序幫忙模擬你大腦思考的過程。求職者: 我再想想……其實這裡是希望提醒候選人,我們首先是要解題,然後才考慮效率。
  • 答對這40道經典web前端面試題,想不拿到offer都難!
    想成功就業web前端工程師,想要能高薪就業,那麼除了好的web前端技能以外,還得有好的面試技巧,如果提前就了解更多企業的面試要求及面試題目,那麼可以讓我們的面試成功的機率大大的提高。今天小編就整理了一些經典的web前端面試題,希望可以祝大家一臂之力。一、HTML常見題目01、Doctype作用?嚴格模式與混雜模式如何區分?它們有何意義?02、HTML5為什麼只需要寫?
  • leetcode 刷500道題,筆試/面試穩嗎?別以為你自己穩了
    來源公眾號:苦逼的碼農作者:帥地想要學習算法、應付筆試或者應付面試手撕算法題,相信大部分人都會去刷 Leetcode,有讀者問?如果我在 leetcode 堅持刷它個 500 道題,以後筆試/面試穩嗎?
  • 2021國家公務員面試形式是什麼 國考面試一般幾道題內容
    2021國家公務員面試形式是什麼 國考面試一般幾道題內容 2021國家公務員面試形式是什麼 國考面試一般幾道題內容對於接下來的2021國家公務員面試,各位考生是否充滿了疑惑
  • 你應該收藏的web前端面試題
    最新前端開發工程師面試題——HTML部分1、Doctype作用?
  • JavaScript面試的10個經典面試題
    JavaScript面試的10個經典面試題 工程師3 發表於 2018-04-20 15:50:00 對大部分公司來說,招聘技術人員這種事情,管理層就應該放手交給技術團隊,只有他們才能夠準確地判斷應聘者的技術實力
  • 這些燒腦的牛津大學面試題,你能答出幾道?
    ✩解答提示:這是道標準的邏輯考題,同時教授們還將注重你解決問題和溝通能力。 這道題關注學生如何跟著引導走,是否能將大問題切分成小問題,用算法方式化解複雜的概念。如有問題,學生應該立即提出,而非悶聲冥思苦想。
  • 2020Web前端面試題匯總-開課吧
    Web前端面試題說說前端中的事件流?HTML中與javascript交互是通過事件驅動來實現的,例如滑鼠點擊事件onclick、頁面的滾動事件onscroll等等,可以向文檔或者文檔中的元素添加事件偵聽器來預訂事件。想要知道這些事件是在什麼時候進行調用的,就需要了解一下「事件流」的概念。
  • 「Spring 全家桶」70 道高頻面試題
    這裡說「天方夜譚」並不是說算法沒用,不切實際,而是想說算法平時其實很少用到,甚至面試官都對自己出的算法題一知半解。這裡總結了 70 道 Spring 相關面試題,有的很基礎,有的很細節,大家可以評估一下自己掌握的情況。
  • 你知道現在的面試有多難嗎?不服來看這三道大廠面試題……
    本文轉載自【微信公眾號:網羅燈下黑,ID:wldxh8】經微信公眾號授權轉載,如需轉載與原文作者聯繫快來看看這三道大廠面試題,你知道現在的面試有多難嗎???各種同步器在大廠面試中的綜合運用怎麼做?(首次公開)通過阿里一道面試題理解大廠面試多線程代碼題的要求第二天:贏在 2021 年金三銀四的起跑線上線程的本質 (作業系統與 CPU 是如何執行線程的)
  • 2021國考面試考什麼?幾道題?答題時間多長?
    國考面試有幾道題?面試形式面試的形式主要有三種,即結構化,無領導和半結構化。結構化:這是最廣泛的面試考察形式。一般考試時間15-25分鐘,題量3-5題,考察題型包括:人際關係,綜合分析,計劃組織協調等。
  • jQuery經典面試題及答案精選
    jQuery是一款非常流行的Javascript框架,如果你想要從事Web前端開發這個崗位,那麼jQuery是你必須掌握而且能夠熟練應用的一門技術
  • 被這10道Java面試題虐哭了
    整整 10 道 Java 面試題,小王一道也沒答正確。他沮喪地給我說,「哥,說點我的情況,你願意聽嗎?我和一個女孩相處,女孩大我兩歲,我非科班。本來打算國慶換一家薪水高點的,好確認關係。借這個機會,我就把小王遇到的這 10 道面試題分享出來,希望能對其他小夥伴一些幫助。