常常寫業務就容易忽視對基礎知識的補充和增強,但在面試中,基礎知識點是很是重要的考覈部分。本文要分享的是,一位開發者天天都會發布的 JavaScript 問題。有的容易,有的會有難度,對基礎知識的查缺補漏很是有幫助,也是你進階路上必然要掌握的知識。javascript
如下挑選了10個問題,緊跟其後的就是對這道題的詳細解答。若是你想看全部的題目,最後有連接直達。前端
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) } for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) }
0 1 2
和 0 1 2
0 1 2
和 3 3 3
3 3 3
和 0 1 2
答案: Cjava
因爲 JavaScript 的事件循環,setTimeout
回調會在遍歷結束後才執行。由於在第一個遍歷中遍歷 i
是經過 var
關鍵字聲明的,因此這個值是全局做用域下的。在遍歷過程當中,咱們經過一元操做符 ++
來每次遞增 i
的值。當 setTimeout
回調執行的時候,i
的值等於 3。git
在第二個遍歷中,遍歷 i
是經過 let
關鍵字聲明的:經過 let
和 const
關鍵字聲明的變量是擁有塊級做用域(指的是任何在 {} 中的內容)。在每次的遍歷過程當中,i
都有一個新值,而且每一個值都在循環內的做用域中。github
function getPersonInfo(one, two, three) { console.log(one) console.log(two) console.log(three) } const person = 'Lydia' const age = 21 getPersonInfo`${person} is ${age} years old`
"Lydia"
21
["", " is ", " years old"]
["", " is ", " years old"]
"Lydia"
21
"Lydia"
["", " is ", " years old"]
21
答案: B面試
若是使用標記模板字面量,第一個參數的值老是包含字符串的數組。其他的參數獲取的是傳遞的表達式的值!數組
function sayHi() { return (() => 0)() } typeof sayHi()
"object"
"number"
"function"
"undefined"
答案: B函數
sayHi
方法返回的是當即執行函數(IIFE)的返回值.此當即執行函數的返回值是 0
, 類型是 number
ui
參考:只有7種內置類型:null
,undefined
,boolean
,number
,string
,object
和 symbol
。 function
不是一種類型,函數是對象,它的類型是object
。this
const a = {} const b = { key: 'b' } const c = { key: 'c' } a[b] = 123 a[c] = 456 console.log(a[b])
123
456
undefined
ReferenceError
答案: B
對象的鍵被自動轉換爲字符串。咱們試圖將一個對象 b
設置爲對象 a
的鍵,且相應的值爲 123
。
然而,當字符串化一個對象時,它會變成 "[object Object]"
。所以這裏說的是,a["[object Object]"] = 123
。而後,咱們再一次作了一樣的事情,c
是另一個對象,這裏也有隱式字符串化,因而,a["[object Object]"] = 456
。
而後,咱們打印 a[b]
,也就是 a["[object Object]"]
。以前剛設置爲 456
,所以返回的是 456
。
const person = { name: 'Lydia' } function sayHi(age) { console.log(`${this.name} is ${age}`) } sayHi.call(person, 21) sayHi.bind(person, 21)
undefined is 21
Lydia is 21
function
function
Lydia is 21
Lydia is 21
Lydia is 21
function
答案: D
使用這兩種方法,咱們均可以傳遞咱們但願 this
關鍵字引用的對象。可是,.call
是當即執行的。
.bind
返回函數的副本,但帶有綁定上下文!它不是當即執行的。
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
1
2
and 3
3
and 6
4
1
2
and 2
3
and 3
4
1
undefined
and 2
undefined
and 3
undefined
and 4
undefined
1
2
and undefined
3
and undefined
4
答案: D
reducer
函數接收4個參數:
reducer
函數的返回值將會分配給累計器,該返回值在數組的每一個迭代中被記住,並最後成爲最終的單個結果值。
reducer
函數還有一個可選參數initialValue
, 該參數將做爲第一次調用回調函數時的第一個參數的值。若是沒有提供initialValue
,則將使用數組中的第一個元素。
在上述例子,reduce
方法接收的第一個參數(Accumulator)是x
, 第二個參數(Current Value)是y
。
在第一次調用時,累加器x
爲1
,當前值「y」
爲2
,打印出累加器和當前值:1
和2
。
例子中咱們的回調函數沒有返回任何值,只是打印累加器的值和當前值。若是函數沒有返回值,則默認返回undefined
。 在下一次調用時,累加器爲undefined
,當前值爲「3」, 所以undefined
和3
被打印出。
在第四次調用時,回調函數依然沒有返回值。 累加器再次爲 undefined
,當前值爲「4」。 undefined
和4
被打印出。
const firstPromise = new Promise((res, rej) => { setTimeout(res, 500, "one"); }); const secondPromise = new Promise((res, rej) => { setTimeout(res, 100, "two"); }); Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
"one"
"two"
"two" "one"
"one" "two"
答案: B
當咱們向Promise.race
方法中傳入多個Promise
時,會進行 優先 解析(注:只要有一個成功或失敗,就立馬結束)。在這個例子中,咱們用setTimeout
給firstPromise
和secondPromise
分別設定了500ms和100ms的定時器。這意味着secondPromise
會首先解析出字符串two
。那麼此時res
參數即爲two
,是爲輸出結果。
function greeting() { throw "Hello world!"; } function sayHi() { try { const data = greeting(); console.log("It worked!", data); } catch (e) { console.log("Oh no an error!", e); } } sayHi();
"It worked! Hello world!"
"Oh no an error: undefined
SyntaxError: can only throw Error objects
"Oh no an error: Hello world!
答案: D
經過throw
語句,我麼能夠建立自定義錯誤。 而經過它,咱們能夠拋出異常。異常能夠是一個字符串, 一個 數字, 一個 布爾類型 或者是一個 對象。在本例中,咱們的異常是字符串'Hello world'
.
經過 catch
語句,咱們能夠設定當try
語句塊中拋出異常後應該作什麼處理。在本例中拋出的異常是字符串'Hello world'
. e
就是這個字符串,所以被輸出。最終結果就是'Oh an error: Hello world'
.
// index.js console.log('running index.js'); import { sum } from './sum.js'; console.log(sum(1, 2)); // sum.js console.log('running sum.js'); export const sum = (a, b) => a + b;
running index.js
, running sum.js
, 3
running sum.js
, running index.js
, 3
running sum.js
, 3
, running index.js
running index.js
, undefined
, running sum.js
答案: B
import
命令是編譯階段執行的,在代碼運行以前。所以這意味着被導入的模塊會先運行,而導入模塊的文件會後執行。
這是CommonJS中require()
和import
之間的區別。使用require()
,您能夠在運行代碼時根據須要加載依賴項。 若是咱們使用require
而不是import
,running index.js
,running sum.js
,3
會被依次打印。
const settings = { username: "lydiahallie", level: 19, health: 90 }; const data = JSON.stringify(settings, ["level", "health"]); console.log(data);
"{"level":19, "health":90}"
"{"username": "lydiahallie"}"
"["level", "health"]"
"{"username": "lydiahallie", "level":19, "health":90}"
答案: A
JSON.stringify
的第二個參數是 _替代者(replacer)_. 替代者(replacer)能夠是個函數或數組,用以控制哪些值如何被轉換爲字符串。
若是替代者(replacer)是個 數組 ,那麼就只有包含在數組中的屬性將會被轉化爲字符串。在本例中,只有名爲"level"
和 "health"
的屬性被包括進來, "username"
則被排除在外。 data
就等於 "{"level":19, "health":90}"
.
而若是替代者(replacer)是個 _函數_,這個函數將被對象的每一個屬性都調用一遍。
函數返回的值會成爲這個屬性的值,最終體如今轉化後的JSON字符串中(譯者注:Chrome下,通過實驗,若是全部屬性均返回同一個值的時候有異常,會直接將返回值做爲結果輸出而不會輸出JSON字符串),而若是返回值爲undefined
,則該屬性會被排除在外。
題目來源:https://github.com/lydiahallie/javascript-questions/blob/master/README-zh_CN.md
若是對你有幫助,請關注【前端技能解鎖】: