譯者按: 從各個平臺精選整理出26道由淺入深的題目助你面試javascript
爲了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原做者全部,翻譯僅用於學習。html
根據Stack Overflow 2018年年度調查報告,JavaScript已經連續6年保持最經常使用的編程語言的記錄。對於一個全棧工程師,JavaScript能夠說是一項必備語言,在面試中總會被問到。我整理了一下FullStack.Cafe上全部常見的JavaScript面試問題供你們參考:java
Q1: JavaScript中類型轉換是怎樣的?
話題: JavaScript 難度: 0git
在JavaScript中,在兩個不一樣類型之間的轉換叫作coercion
。在JavaScript中有兩種形式:顯示轉換和隱式轉換。github
下面是一個顯示轉換的例子:面試
var a = "42"; var b = Number( a ); a; // "42" b; // 42 -- the number!
下面是一個隱式轉換的例子:算法
var a = "42"; var b = a * 1; // "42" implicitly coerced to 42 here a; // "42" b; // 42 -- the number!
來源: FullStack.Cafe編程
Q2: JavaScript中的做用域是怎樣的?
話題: JavaScript 難度: ⭐小程序
在JavaScript中,每個函數都有各自的做用域(scope
)。做用域能夠理解爲是一個變量的集合以及相應的如何訪問它的規則。只有在函數內部的變量才能夠訪問到該函數域的變量。微信小程序
在同一個做用域內部,變量名必需要惟一。做用域能夠嵌套。在最內部的做用域中,能夠訪問任何外部的做用域中的變量。
Q3: 請解釋JavaScript中的相等判斷
話題: JavaScript 難度: ⭐
JavaScript中的相等判斷有嚴格判斷和帶隱式轉換的判斷兩種:
- 嚴格判斷(strict comparision): 好比
===
,比較的時候不會隱式轉換類型; - 抽象判斷(abstract comparasion):好比
==
,比較的時候會隱式轉換類型。
var a = "42"; var b = 42; a == b; // true a === b; // false
一些簡單的規則:
- 若是兩邊都是布爾類型的值,使用
===
; - 若是兩邊是0,
""
,[]
,使用===
; - 全部其它類型,使用
==
是安全的。並且在不少狀況下會簡化代碼、增長可讀性。
Q4: 請解釋什麼叫作回調函數並提供一個簡單的例子
話題: JavaScript 難度: ⭐⭐
回調函數是一個函數,它被做爲參數傳入另外一個函數,當某些操做結束後,該函數被調用。下面是一個簡單的例子,當數組被修改後,調用回調函數打印一行日誌。
function modifyArray(arr, callback) { // do something to arr here arr.push(100); // then execute the callback function that was passed callback(); } var arr = [1, 2, 3, 4, 5]; modifyArray(arr, function() { console.log("array has been modified", arr); });
Q5: "use strict"到底有何用處?
話題: JavaScript 難度: ⭐⭐
use strict
放在文件的頂部或則函數的第一行來啓動更加嚴格的檢查來避免失誤引發的錯誤。好比,下面的代碼會拋出錯誤:
function doSomething(val) { "use strict"; x = val + 10; }
由於x沒有定義,若是使用了use strict
,x是不會被當作全局的變量來看待。下面的代碼修復了這個BUG:
function doSomething(val) { "use strict"; var x = val + 10; }
Q6: 請解釋Null和Undefined
話題: JavaScript 難度: ⭐⭐
JavaScript和TypeScript有兩個最基本的類型null
和undefined
。它們的含義是不一樣的:
- 若是尚未被初始化,則是
undefined
; - 若是不可用,則能夠用
null
來表示;
Q7: 請實現以下函數
話題: JavaScript 難度: ⭐⭐
var addSix = createBase(6); addSix(10); // returns 16 addSix(21); // returns 27
addSix
是一個函數,也就是說createBase函數的返回是一個函數。
function createBase(baseNumber) { return function(N) { // we are referencing baseNumber here even though it was declared // outside of this function. Closures allow us to do this in JavaScript return baseNumber + N; } } var addSix = createBase(6); addSix(10); addSix(21);
Q8: 請解釋JavaScript中的值和類型
話題: JavaScript 難度: ⭐⭐
下面是JavaScript內置的可用類型:
- string
- number
- boolean
- null和undefined
- object
- symbol (ES6的新語法)
Q9: 請解釋事件冒泡以及如何阻止它?
話題: JavaScript 難度: ⭐⭐
事件冒泡的概念是指:在最內層的元素上綁定的事件被觸發後,會按照嵌套的層次由內向外逐步觸發。所以,點擊某個孩子節點可能會觸發父節點的事件。
一個阻止事件冒泡的辦法就是使用event.stopPropagation()
,在IE<9的瀏覽器上使用event.cancelBubble()
。
來源:https://github.com/kennymkchan
Q10. 請解釋JavaScript中的let關鍵字
話題: JavaScript 難度: ⭐⭐
ES6容許你使用let關鍵字來申明塊做用域({...}
)的變量。
Q11: 如何檢查一個數字是不是整數?
話題: JavaScript 難度: ⭐⭐
一個最簡單的方法是判斷除以1的餘數是否爲0.
function isInt(num) { return num % 1 === 0; } console.log(isInt(4)); // true console.log(isInt(12.2)); // false console.log(isInt(0.3)); // false
來源: coderbyte.com
Q12: 什麼叫IIFEs(Immediately Invoked Function Expressions)?
話題: JavaScript 難度: ⭐⭐
IIFE叫作當即執行表達式,顧名思義,該表達式一被建立就當即執行。
(function IIFE(){ console.log( "Hello!" ); })(); // "Hello!"
該方法經常使用語避免污染全局的命名空間,由於因此在IIFE中使用的變量外部都沒法訪問。
Q13: 若是比較JavaScript中的兩個對象?
話題: JavaScript 難度: ⭐⭐
兩個非基本類型的值,好比對象(包括函數和數組)都是經過引用的形式來訪問。若是直接經過==
和===
來判斷,那麼只會簡單的判斷其引用地址是否相同,而不是它們實際對應的值。
若是數組和字符串作比較,那麼數組會經過逗號拼接轉換爲字符串。經過等號判斷的時候,兩個相同的數組不會相等,可是和相同數據的字符串比較反而相等。
var a = [1,2,3]; var b = [1,2,3]; var c = "1,2,3"; a == c; // true b == c; // true a == b; // false
若是要深度比較,可使用第三方庫,好比deep-equal
或則你本身實現一個比較算法。
Q14: 請解釋ES5和ES6的不一樣點
話題: JavaScript 難度: ⭐⭐⭐
- ECMAScript 5 (ES5): 第5個ECMAScript版本,於2009年標準化。該標準幾乎全部的瀏覽器都徹底支持。
- ECMAScript 6 (ES6)/ECMAScript 2015 (ES2015): 第6個ECMAScript版本,於2015年標準化。目前各大瀏覽器還只是部分支持。
接下來介紹它們主要的區別:
- 箭頭函數和字符串嵌入:
const greetings = (name) => { return `hello ${name}`; }
甚至:
const greetings = name => `hello ${name}`;
- 常量聲明(Const): 如同其它編程語言中的常量同樣,但又有不一樣。這裏的
const
表明了constant reference
。也就是說,你能夠修改其指向的對象的值。可是你不能修改其reference的值。
const NAMES = []; NAMES.push("Jim"); console.log(NAMES.length === 1); // true NAMES = ["Steve", "John"]; // error
- 塊做用域變量:ES6中的新關鍵字
let
容許容許開發者將變量的做用域限定在塊級別。不會像var
同樣變量提高。 - 參數默認值:容許在函數定義的時候指定默認的值。
// Basic syntax function multiply (a, b = 2) { return a * b; } multiply(5); // 10
- 類定義和繼承
ES6開始支持定義類(使用class
關鍵字),構造函數(使用constructor
關鍵字),和extend
關鍵字來實現繼承。
- for-of操做
for...of
語句用來迭代訪問一個對象的全部屬性。
- Spread操做符:用於對象合併
const obj1 = { a: 1, b: 2 } const obj2 = { a: 2, c: 3, d: 4} const obj3 = {...obj1, ...obj2}
- Promise: Promises提供了一個處理異步操做的方法。你能夠用回調函數來實現,可是Promise更加簡潔和可讀。
const isGreater = (a, b) => { return new Promise ((resolve, reject) => { if(a > b) { resolve(true) } else { reject(false) } }) } isGreater(1, 2) .then(result => { console.log('greater') }) .catch(result => { console.log('smaller') })
- 模塊的export和import。
const myModule = { x: 1, y: () => { console.log('This is ES5') }} export default myModule;
import myModule from './myModule';
來源: Bulby.io
Q15: 請解釋undefined
和not defined
的區別
話題: JavaScript 難度: ⭐⭐⭐
在JavaScript中,若是你嘗試使用不存在的還未申明的變量,JavaScript會拋出錯誤var name is not defined
。可是若是你用typeof
來查看其類型,會返回undefined
。
咱們先來澄清一下聲明和定義的區別:var x
是一個聲明,由於你並無定義其具體的值,你只是聲明其存在性。
var x; // declaring x console.log(x); //output: undefined
var x = 1
同時兼具聲明和定義,咱們也能夠叫它初始化。在JavaScript中,每個變量和函數聲明都會被提高到頂部。
若是咱們訪問一個聲明瞭可是未定義的變量,會返回undefined
。
var x; // Declaration if(typeof x === 'undefined') // Will return true
訪問一個未聲明未定義的變量,會返回not defined錯誤。
console.log(y); // Output: ReferenceError: y is not defined
Q16: 匿名函數和命名函數的區別?
話題: JavaScript 難度: ⭐⭐⭐
var foo = function() { // anonymous function assigned to variable foo // .. }; var x = function bar(){ // named function (bar) assigned to variable x // .. }; foo(); // actual function execution x();
譯者補充:匿名函數若是不賦值給某個變量,則沒法被調用了;命名函數再次被賦值不是畫蛇添足麼。
Q17: JavaScript中閉包是什麼?請提供一個例子
話題: 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
是一個閉包,定義在outerFunction
中,它能夠訪問outerFunction
做用域的全部變量。固然,它還能夠訪問全局變量。
輸出結果以下:
outerArg = 7 outerFuncVar = x innerArg = 5 innerFuncVar = y globalVar = abc
Q18: 在JavaScript中如何建立私有變量?
話題: JavaScript 難度: ⭐⭐⭐⭐
你能夠經過在函數中聲明變量來建立私有變量。由於在函數中,外部沒法直接訪問。
function func() { var priv = "secret code"; } console.log(priv); // throws error
爲了訪問該變量,能夠構造一個幫助函數來返回該值。
function func() { var priv = "secret code"; return function() { return priv; } } var getPriv = func(); console.log(getPriv()); // => secret code
Q19: 請解釋原型模式(Prototype Design Pattern)
話題: JavaScript 難度: ⭐⭐⭐⭐
原型模式會建立一個新的對象,但不是建立一個未初始化的對象,而是經過拷貝原型鏈上的值或則被拷貝對象的值來完成初始化。傳統的語言不多使用原型模式,可是JavaScript做爲一個基於原型的語言,使用原型模式來建立新的對象。
來源: dofactory.com
Q20: 判斷給定的字符串是否同態(isomorphic)
話題: JavaScript 難度: ⭐⭐⭐⭐
首先介紹什麼叫作同態:兩個字符串,若是A字符串中的每個字符均可以在B字符串中找到惟一對應,而且順序一一對應;若是存在這樣的函數,那麼A和B同態。
paper
和title
同態egg
和sad
不一樣態dgg
和add
同態
isIsomorphic("egg", 'add'); // true isIsomorphic("paper", 'title'); // true isIsomorphic("kick", 'side'); // false function isIsomorphic(firstString, secondString) { // Check if the same length. If not, they cannot be isomorphic if (firstString.length !== secondString.length) return false var letterMap = {}; for (var i = 0; i < firstString.length; i++) { var letterA = firstString[i], letterB = secondString[i]; // If the letter does not exist, create a map and map it to the value // of the second letter if (letterMap[letterA] === undefined) { letterMap[letterA] = letterB; } else if (letterMap[letterA] !== letterB) { // Eles if letterA already exists in the map, but it does not map to // letterB, that means that A is mapping to more than one letter. return false; } } // If after iterating through and conditions are satisfied, return true. // They are isomorphic return true; }
來源: https://github.com/kennymkchan
Q21: Transpiling
表明了什麼意思?
話題: JavaScript 難度: ⭐⭐⭐⭐
Transpiling
是transforming + compiling
的合成詞。對於一些新的語法,瀏覽器還不支持。最好的辦法就是將其變換到舊的等價的代碼,這個過程一般叫作transpiling
。
典型的,你能夠在build
的過程當中加入transpiler
,就如同code linter
和minifier
同樣。
已經有不少知名的transpilers可供使用:
- Babel: 將ES6編譯到ES5
- Traceur:將ES6,ES7等編譯到ES5
來源: You Don't Know JS, Up &going
Q22: this
關鍵字如何工做?請提供一些例子
話題: JavaScript 難度: ⭐⭐⭐⭐
在JavaScript中,this老是指向函數的「擁有者」(也就是指向該函數的對象),或則擁有該函數的對象。
function foo() { console.log( this.bar ); } var bar = "global"; var obj1 = { bar: "obj1", foo: foo }; var obj2 = { bar: "obj2" }; foo(); // "global" obj1.foo(); // "obj1" foo.call( obj2 ); // "obj2" new foo(); // undefined
來源: quirksmode.org
Q23: 如何爲Array對象添加你自定義的函數,使得以下代碼能夠正常工做。
話題: JavaScript 難度: ⭐⭐⭐⭐
var arr = [1, 2, 3, 4, 5]; var avg = arr.average(); console.log(avg);
JavaScript是一個基於原型的語言。也就是說對象之間經過原型連接,並繼承其函數。爲了給Array對象添加函數,咱們能夠修改其原型定義Array prorotype
。
Array.prototype.average = function() { // calculate sum var sum = this.reduce(function(prev, cur) { return prev + cur; }); // return sum divided by number of elements return sum / this.length; } var arr = [1, 2, 3, 4, 5]; var avg = arr.average(); console.log(avg); // => 3
來源: coderbyte.com
Q24: JavaScript中提高(hoisting)是什麼意思?
話題: JavaScript 難度: ⭐⭐⭐⭐
提高(hoisting)是指JavaScript的解釋器將全部的變量和函數聲明都提高到該做用域的頂部,有兩種提高類型:
- 變量提高
- 函數提高
在一個做用域中經過聲明的變量和函數在整個做用域中均可以使用。
var a = 2; foo(); // works because `foo()` // declaration is "hoisted" function foo() { a = 3; console.log( a ); // 3 var a; // declaration is "hoisted" // to the top of `foo()` } console.log( a ); // 2
雖然foo()
函數在後面定義,可是在前面也能夠調用。
Q25: 以下代碼會返回什麼結果?
話題: JavaScript 難度: ⭐⭐⭐⭐
0.1 + 0.2 === 0.3
不要驚訝,其結果是false。由於浮點數在系統內的精確度問題,0.1+0.2的結果並非0.3,而是0.30000000000000004。 要避免這個問題的方法是指定返回結果的小數位數。
來源: coderbyte.com
Q26: 請描述一下揭示模式(Revealing Module Pattern)
話題: JavaScript 難度: ⭐⭐⭐⭐⭐
Module pattern的一個變種是Revealing Module Pattern
。該設計模式的目的是作到很好的代碼隔離,只是將須要對外公開的變量和函數暴露出來。一個直接的實現以下所示:
var Exposer = (function() { var privateVariable = 10; var privateMethod = function() { console.log('Inside a private method!'); privateVariable++; } var methodToExpose = function() { console.log('This is a method I want to expose!'); } var otherMethodIWantToExpose = function() { privateMethod(); } return { first: methodToExpose, second: otherMethodIWantToExpose }; })(); Exposer.first(); // Output: This is a method I want to expose! Exposer.second(); // Output: Inside a private method! Exposer.methodToExpose; // undefined
來源: scotch.io
關於Fundebug
Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了7億+錯誤事件,獲得了Google、360、金山軟件、百姓網等衆多知名用戶的承認。歡迎免費試用!
版權聲明
轉載時請註明做者Fundebug以及本文地址: https://blog.fundebug.com/2018/10/18/top-26-js-interview-questions/