10道典型的JavaScript面試題
問(wèn)題1: 作用域(Scope)
考慮以下代碼:
(function() { var a = b = 5; })(); console.log(b);
控制臺(tái)(console)會(huì)打印出什么?
答案:5
如果 嚴(yán)格模式開(kāi)啟,那么代碼就會(huì)報(bào)錯(cuò) ” Uncaught ReferenceError: b is not defined” 。請(qǐng)記住,如果這是預(yù)期的行為,嚴(yán)格模式要求你顯式地引用全局作用域。所以,你需要像下面這么寫(xiě):
(function() { 'use strict'; var a = window.b = 5; })(); console.log(b);
問(wèn)題2: 創(chuàng)建 “原生(native)” 方法
在 String 對(duì)象上定義一個(gè) repeatify 函數(shù)。這個(gè)函數(shù)接受一個(gè)整數(shù)參數(shù),來(lái)明確字符串需要重復(fù)幾次。這個(gè)函數(shù)要求字符串重復(fù)指定的次數(shù)。舉個(gè)例子:
console.log('hello'.repeatify(3));
應(yīng)該打印出hellohellohello.
答案:
String.prototype.repeatify = String.prototype.repeatify || function(times) { var str = ''; for (var i = 0; i < times; i++) { str += this; } return str; };
在這里,另一個(gè)關(guān)鍵點(diǎn)是,看你怎樣避免重寫(xiě)可能已經(jīng)定義了的方法。這可以通過(guò)在定義自己的方法之前,檢測(cè)方法是否已經(jīng)存在。
String.prototype.repeatify = String.prototype.repeatify || function(times) {/* code here */};
問(wèn)題3: 變量提升(Hoisting)
執(zhí)行以下代碼的結(jié)果是什么?為什么?
function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();
答案:
這段代碼的執(zhí)行結(jié)果是undefined 和 2。
這個(gè)結(jié)果的原因是,變量和函數(shù)都被提升(hoisted) 到了函數(shù)體的頂部。因此,當(dāng)打印變量a時(shí),它雖存在于函數(shù)體(因?yàn)閍已經(jīng)被聲明),但仍然是undefined。換言之,上面的代碼等同于下面的代碼:
function test() { var a; function foo() { return 2; } console.log(a); console.log(foo()); a = 1; } test();
問(wèn)題4: 在javascript中,`this`是如何工作的
以下代碼的結(jié)果是什么?請(qǐng)解釋你的答案。
var fullname = 'John Doe'; var obj = { fullname: 'Colin Ihrig', prop: { fullname: 'Aurelio De Rosa', getFullname: function() { return this.fullname; } } }; console.log(obj.prop.getFullname()); var test = obj.prop.getFullname; console.log(test());
答案:
這段代碼打印結(jié)果是:Aurelio De Rosa 和 John Doe 。原因是,JavaScript中關(guān)鍵字this所引用的是函數(shù)上下文,取決于函數(shù)是如何調(diào)用的,而不是怎么被定義的。
在第一個(gè)console.log(),getFullname()是作為obj.prop對(duì)象的函數(shù)被調(diào)用。因此,當(dāng)前的上下文指代后者,并且函數(shù)返回這個(gè)對(duì)象的fullname屬性。相反,當(dāng)getFullname()被賦值給test變量時(shí),當(dāng)前的上下文是全局對(duì)象window,這是因?yàn)閠est被隱式地作為全局對(duì)象的屬性。基于這一點(diǎn),函數(shù)返回window的fullname,在本例中即為第一行代碼設(shè)置的。
問(wèn)題5: call() 和 apply()
修復(fù)前一個(gè)問(wèn)題,讓最后一個(gè)console.log() 打印輸出Aurelio De Rosa.
答案:
這個(gè)問(wèn)題可以通過(guò)運(yùn)用call()或者apply()方法強(qiáng)制轉(zhuǎn)換上下文環(huán)境。
console.log(test.call(obj.prop));
問(wèn)題6: 閉包(Closures)
考慮下面的代碼:
var nodes = document.getElementsByTagName('button'); for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', function() { console.log('You clicked element #' + i); }); }
請(qǐng)問(wèn),如果用戶點(diǎn)擊第一個(gè)和第四個(gè)按鈕的時(shí)候,控制臺(tái)分別打印的結(jié)果是什么?為什么?
答案:
兩次打印都是nodes.length的值。
問(wèn)題7: 閉包(Closures)
修復(fù)上題的問(wèn)題,使得點(diǎn)擊第一個(gè)按鈕時(shí)輸出0,點(diǎn)擊第二個(gè)按鈕時(shí)輸出1,依此類推。
答案:
有多種辦法可以解決這個(gè)問(wèn)題,下面主要使用兩種方法解決這個(gè)問(wèn)題。
第一個(gè)解決方案使用立即執(zhí)行函數(shù)表達(dá)式(IIFE)再創(chuàng)建一個(gè)閉包,從而得到所期望的i的值。實(shí)現(xiàn)此方法的代碼如下:
var nodes = document.getElementsByTagName('button'); for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', (function(i) { return function() { console.log('You clicked element #' + i); } })(i)); }
另一個(gè)解決方案不使用IIFE,而是將函數(shù)移到循環(huán)的外面。這種方法由下面的代碼實(shí)現(xiàn):
function handlerWrapper(i) { return function() { console.log('You clicked element #' + i); } } var nodes = document.getElementsByTagName('button'); for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', handlerWrapper(i)); }
問(wèn)題8:數(shù)據(jù)類型
考慮如下代碼:
console.log(typeof null); console.log(typeof {}); console.log(typeof []); console.log(typeof undefined);
答案:
object object object undefined
問(wèn)題9:事件循環(huán)
下面代碼運(yùn)行結(jié)果是什么?請(qǐng)解釋。
function printing() { console.log(1); setTimeout(function() { console.log(2); }, 1000); setTimeout(function() { console.log(3); }, 0); console.log(4); } printing();
答案:
1 4 3 2
想知道為什么輸出順序是這樣的,你需要弄了解setTimeout()做了什么,以及瀏覽器的事件循環(huán)原理。瀏覽器有一個(gè)事件循環(huán)用于檢查事件隊(duì)列,處理延遲的事件。UI事件(例如,點(diǎn)擊,滾動(dòng)等),Ajax回調(diào),以及提供給setTimeout()和setInterval()的回調(diào)都會(huì)依次被事件循環(huán)處理。因此,當(dāng)調(diào)用setTimeout()函數(shù)時(shí),即使延遲的時(shí)間被設(shè)置為0,提供的回調(diào)也會(huì)被排隊(duì)?;卣{(diào)會(huì)呆在隊(duì)列中,直到指定的時(shí)間用完后,引擎開(kāi)始執(zhí)行動(dòng)作(如果它在當(dāng)前不執(zhí)行其他的動(dòng)作)。因此,即使setTimeout()回調(diào)被延遲0毫秒,它仍然會(huì)被排隊(duì),并且直到函數(shù)中其他非延遲的語(yǔ)句被執(zhí)行完了之后,才會(huì)執(zhí)行。
問(wèn)題10:算法
寫(xiě)一個(gè)isPrime()函數(shù),當(dāng)其為質(zhì)數(shù)時(shí)返回true,否則返回false。
答案:
我認(rèn)為這是面試中最常見(jiàn)的問(wèn)題之一。然而,盡管這個(gè)問(wèn)題經(jīng)常出現(xiàn)并且也很簡(jiǎn)單,但是從被面試人提供的答案中能很好地看出被面試人的數(shù)學(xué)和算法水平。
首先, 因?yàn)镴avaScript不同于C或者Java,因此你不能信任傳遞來(lái)的數(shù)據(jù)類型。如果面試官?zèng)]有明確地告訴你,你應(yīng)該詢問(wèn)他是否需要做輸入檢查,還是不進(jìn)行檢查直接寫(xiě)函數(shù)。嚴(yán)格上說(shuō),應(yīng)該對(duì)函數(shù)的輸入進(jìn)行檢查。
第二點(diǎn)要記?。贺?fù)數(shù)不是質(zhì)數(shù)。同樣的,1和0也不是,因此,首先測(cè)試這些數(shù)字。此外,2是質(zhì)數(shù)中唯一的偶數(shù)。沒(méi)有必要用一個(gè)循環(huán)來(lái)驗(yàn)證4,6,8。再則,如果一個(gè)數(shù)字不能被2整除,那么它不能被4,6,8等整除。因此,你的循環(huán)必須跳過(guò)這些數(shù)字。如果你測(cè)試輸入偶數(shù),你的算法將慢2倍(你測(cè)試雙倍數(shù)字)。可以采取其他一些更明智的優(yōu)化手段,我這里采用的是適用于大多數(shù)情況的。例如,如果一個(gè)數(shù)字不能被5整除,它也不會(huì)被5的倍數(shù)整除。所以,沒(méi)有必要檢測(cè)10,15,20等等。
最后一點(diǎn),你不需要檢查比輸入數(shù)字的開(kāi)方還要大的數(shù)字。我感覺(jué)人們會(huì)遺漏掉這一點(diǎn),并且也不會(huì)因?yàn)榇硕@得消極的反饋。但是,展示出這一方面的知識(shí)會(huì)給你額外加分。
現(xiàn)在你具備了這個(gè)問(wèn)題的背景知識(shí),下面是總結(jié)以上所有考慮的解決方案:
function isPrime(number) { // If your browser doesn't support the method Number.isInteger of ECMAScript 6, // you can implement your own pretty easily if (typeof number !== 'number' || !Number.isInteger(number)) { // Alternatively you can throw an error. return false; } if (number < 2) { return false; } if (number === 2) { return true; } else if (number % 2 === 0) { return false; } var squareRoot = Math.sqrt(number); for(var i = 3; i <= squareRoot; i += 2) { if (number % i === 0) { return false; } } return true; }
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
- 13道關(guān)于JavaScript正則表達(dá)式的面試題
- 詳解JS中的this、apply、call、bind(經(jīng)典面試題)
- 關(guān)于javascript作用域的常見(jiàn)面試題分享
- 面試常見(jiàn)的js算法題
- 80%應(yīng)聘者都不及格的JS面試題
- Javascript前端經(jīng)典的面試題及答案
- JavaScript中最常見(jiàn)的三個(gè)面試題解析
- 一篇文章搞定JavaScript類型轉(zhuǎn)換(面試常見(jiàn))
- 總結(jié)幾道關(guān)于Node.js的面試問(wèn)題
- 「中高級(jí)前端面試」JavaScript手寫(xiě)代碼無(wú)敵秘籍(推薦)
相關(guān)文章
JavaScript function函數(shù)種類詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript function函數(shù)種類,包括普通函數(shù)、匿名函數(shù)、閉包函數(shù),感興趣的小伙伴們可以參考一下2016-02-02Javascript 拖拽雛形中的一些問(wèn)題(逐行分析代碼,讓你輕松了拖拽的原理)
這篇文章主要介紹了Javascript 拖拽雛形中的一些問(wèn)題(逐行分析代碼,讓你輕松了拖拽的原理),需要的朋友可以參考下2015-01-01JS實(shí)現(xiàn)textarea通過(guò)換行或者回車把多行數(shù)字分割成數(shù)組并且去掉數(shù)組中空的值
這篇文章主要介紹了JS實(shí)現(xiàn)textarea通過(guò)換行或者回車把多行數(shù)字分割成數(shù)組并且去掉數(shù)組中空的值的相關(guān)資料,需要的朋友可以參考下2018-10-10javascript瀏覽器用戶代理檢測(cè)腳本實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇javascript瀏覽器用戶代理檢測(cè)腳本實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10實(shí)現(xiàn)png圖片和png背景透明(支持多瀏覽器)的方法
Firefox和Opera對(duì)PNG的支持非常的好,都是IE卻無(wú)視PNG圖片這一特性的“存在”,雖然IE7已經(jīng)支持都是IE6還是不行。2009-09-09什么是cookie?js手動(dòng)創(chuàng)建和存儲(chǔ)cookie
cookie 是存儲(chǔ)于訪問(wèn)者的計(jì)算機(jī)中的變量,在這個(gè)例子中我們要?jiǎng)?chuàng)建一個(gè)存儲(chǔ)訪問(wèn)者名字的 cookie,需要的朋友可以參考下2014-05-05