譯者按: 從各個平臺精選整理出26道由淺入深的題目助你面試javascript
爲了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原做者全部,翻譯僅用於學習。html
根據Stack Overflow 2018年年度調查報告,JavaScript已經連續6年保持最經常使用的編程語言的記錄。對於一個全棧工程師,JavaScript能夠說是一項必備語言,在面試中總會被問到。我整理了一下FullStack.Cafe上全部常見的JavaScript面試問題供你們參考:java
話題: 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編程
話題: JavaScript 難度: ⭐小程序
在JavaScript中,每個函數都有各自的做用域(scope
)。做用域能夠理解爲是一個變量的集合以及相應的如何訪問它的規則。只有在函數內部的變量才能夠訪問到該函數域的變量。微信小程序
在同一個做用域內部,變量名必需要惟一。做用域能夠嵌套。在最內部的做用域中,能夠訪問任何外部的做用域中的變量。
話題: JavaScript 難度: ⭐
JavaScript中的相等判斷有嚴格判斷和帶隱式轉換的判斷兩種:
===
,比較的時候不會隱式轉換類型;==
,比較的時候會隱式轉換類型。var a = "42";
var b = 42;
a == b; // true
a === b; // false
複製代碼
一些簡單的規則:
===
;""
,[]
,使用===
;==
是安全的。並且在不少狀況下會簡化代碼、增長可讀性。話題: 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);
});
複製代碼
話題: 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;
}
複製代碼
話題: JavaScript 難度: ⭐⭐
JavaScript和TypeScript有兩個最基本的類型null
和undefined
。它們的含義是不一樣的:
undefined
;null
來表示;話題: 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);
複製代碼
話題: JavaScript 難度: ⭐⭐
下面是JavaScript內置的可用類型:
話題: JavaScript 難度: ⭐⭐
事件冒泡的概念是指:在最內層的元素上綁定的事件被觸發後,會按照嵌套的層次由內向外逐步觸發。所以,點擊某個孩子節點可能會觸發父節點的事件。
一個阻止事件冒泡的辦法就是使用event.stopPropagation()
,在IE<9的瀏覽器上使用event.cancelBubble
。
function stopPropagation(evt) {
if (typeof evt.stopPropagation === "function") {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
}
複製代碼
話題: JavaScript 難度: ⭐⭐
ES6容許你使用let關鍵字來申明塊做用域({...}
)的變量。
話題: 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
話題: JavaScript 難度: ⭐⭐
IIFE叫作當即執行表達式,顧名思義,該表達式一被建立就當即執行。
(function IIFE(){
console.log( "Hello!" );
})();
// "Hello!"
複製代碼
該方法經常使用語避免污染全局的命名空間,由於因此在IIFE中使用的變量外部都沒法訪問。
來源: http://www.javashuo.com/tag/stackoverflow.com
話題: 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
或則你本身實現一個比較算法。
話題: JavaScript 難度: ⭐⭐⭐
接下來介紹它們主要的區別:
const greetings = (name) => {
return `hello ${name}`;
}
複製代碼
甚至:
const greetings = name => `hello ${name}`;
複製代碼
const
表明了constant reference
。也就是說,你能夠修改其指向的對象的值。可是你不能修改其reference的值。const NAMES = [];
NAMES.push("Jim");
console.log(NAMES.length === 1); // true
NAMES = ["Steve", "John"]; // error
複製代碼
let
容許容許開發者將變量的做用域限定在塊級別。不會像var
同樣變量提高。// Basic syntax
function multiply (a, b = 2) {
return a * b;
}
multiply(5); // 10
複製代碼
ES6開始支持定義類(使用class
關鍵字),構造函數(使用constructor
關鍵字),和extend
關鍵字來實現繼承。
for...of
語句用來迭代訪問一個對象的全部屬性。
const obj1 = { a: 1, b: 2 }
const obj2 = { a: 2, c: 3, d: 4}
const obj3 = {...obj1, ...obj2}
複製代碼
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')
})
複製代碼
const myModule = { x: 1, y: () => { console.log('This is ES5') }}
export default myModule;
複製代碼
import myModule from './myModule';
複製代碼
來源: Bulby.io
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
複製代碼
話題: 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();
複製代碼
譯者補充:匿名函數若是不賦值給某個變量,則沒法被調用了;命名函數再次被賦值不是畫蛇添足麼。
話題: 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
複製代碼
話題: 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
複製代碼
話題: JavaScript 難度: ⭐⭐⭐⭐
原型模式會建立一個新的對象,但不是建立一個未初始化的對象,而是經過拷貝原型鏈上的值或則被拷貝對象的值來完成初始化。傳統的語言不多使用原型模式,可是JavaScript做爲一個基於原型的語言,使用原型模式來建立新的對象。
來源: dofactory.com
話題: 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;
}
複製代碼
Transpiling
表明了什麼意思?話題: JavaScript 難度: ⭐⭐⭐⭐
Transpiling
是transforming + compiling
的合成詞。對於一些新的語法,瀏覽器還不支持。最好的辦法就是將其變換到舊的等價的代碼,這個過程一般叫作transpiling
。
典型的,你能夠在build
的過程當中加入transpiler
,就如同code linter
和minifier
同樣。
已經有不少知名的transpilers可供使用:
來源: You Don't Know JS, Up &going
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
話題: 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
話題: 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()
函數在後面定義,可是在前面也能夠調用。
話題: JavaScript 難度: ⭐⭐⭐⭐
0.1 + 0.2 === 0.3
複製代碼
不要驚訝,其結果是false。由於浮點數在系統內的精確度問題,0.1+0.2的結果並非0.3,而是0.30000000000000004。 要避免這個問題的方法是指定返回結果的小數位數。
來源: coderbyte.com
話題: 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專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網等衆多品牌企業。歡迎你們免費試用!
轉載時請註明做者Fundebug以及本文地址:
blog.fundebug.com/2018/10/18/…