JavaScript 進階問題列表,你掌握了多少?

常常寫業務就容易忽視對基礎知識的補充和增強,但在面試中,基礎知識點是很是重要的考覈部分。本文要分享的是,一位開發者天天都會發布的 JavaScript 問題。有的容易,有的會有難度,對基礎知識的查缺補漏很是有幫助,也是你進階路上必然要掌握的知識。javascript

如下挑選了10個問題,緊跟其後的就是對這道題的詳細解答。若是你想看全部的題目,最後有連接直達。前端

1. for循環中套定時器

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1)
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1)
}
  • A: 0 1 20 1 2
  • B: 0 1 23 3 3
  • C: 3 3 30 1 2

答案: Cjava

因爲 JavaScript 的事件循環,setTimeout 回調會在遍歷結束後才執行。由於在第一個遍歷中遍歷 i 是經過 var 關鍵字聲明的,因此這個值是全局做用域下的。在遍歷過程當中,咱們經過一元操做符 ++ 來每次遞增 i 的值。當 setTimeout 回調執行的時候,i 的值等於 3。git

在第二個遍歷中,遍歷 i 是經過 let 關鍵字聲明的:經過 letconst 關鍵字聲明的變量是擁有塊級做用域(指的是任何在 {} 中的內容)。在每次的遍歷過程當中,i 都有一個新值,而且每一個值都在循環內的做用域中。github

2. 標記模板字面量

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`
  • A: "Lydia" 21 ["", " is ", " years old"]
  • B: ["", " is ", " years old"] "Lydia" 21
  • C: "Lydia" ["", " is ", " years old"] 21

答案: B面試

若是使用標記模板字面量,第一個參數的值老是包含字符串的數組。其他的參數獲取的是傳遞的表達式的值!數組

3. typeof 運算符返回值

function sayHi() {
  return (() => 0)()
}

typeof sayHi()
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"

答案: B函數

sayHi 方法返回的是當即執行函數(IIFE)的返回值.此當即執行函數的返回值是 0, 類型是 numberui

參考:只有7種內置類型:nullundefinedbooleannumberstringobjectsymbolfunction 不是一種類型,函數是對象,它的類型是objectthis

4. 對象做爲key值的問題

const a = {}
const b = { key: 'b' }
const c = { key: 'c' }

a[b] = 123
a[c] = 456

console.log(a[b])
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError

答案: B

對象的鍵被自動轉換爲字符串。咱們試圖將一個對象 b 設置爲對象 a 的鍵,且相應的值爲 123

然而,當字符串化一個對象時,它會變成 "[object Object]"。所以這裏說的是,a["[object Object]"] = 123。而後,咱們再一次作了一樣的事情,c 是另一個對象,這裏也有隱式字符串化,因而,a["[object Object]"] = 456

而後,咱們打印 a[b],也就是 a["[object Object]"]。以前剛設置爲 456,所以返回的是 456

5. call和bind的使用

const person = { name: 'Lydia' }

function sayHi(age) {
  console.log(`${this.name} is ${age}`)
}

sayHi.call(person, 21)
sayHi.bind(person, 21)
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function

答案: D

使用這兩種方法,咱們均可以傳遞咱們但願 this 關鍵字引用的對象。可是,.call當即執行的。

.bind 返回函數的副本,但帶有綁定上下文!它不是當即執行的。

6. reduce 方法的使用

[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
  • A: 1 2 and 3 3 and 6 4
  • B: 1 2 and 2 3 and 3 4
  • C: 1 undefined and 2 undefined and 3 undefined and 4 undefined
  • D: 1 2 and undefined 3 and undefined 4

答案: D

reducer 函數接收4個參數:

  1. Accumulator (acc) (累計器)
  2. Current Value (cur) (當前值)
  3. Current Index (idx) (當前索引)
  4. Source Array (src) (源數組)

reducer 函數的返回值將會分配給累計器,該返回值在數組的每一個迭代中被記住,並最後成爲最終的單個結果值。

reducer 函數還有一個可選參數initialValue, 該參數將做爲第一次調用回調函數時的第一個參數的值。若是沒有提供initialValue,則將使用數組中的第一個元素。

在上述例子,reduce方法接收的第一個參數(Accumulator)是x, 第二個參數(Current Value)是y

在第一次調用時,累加器x1,當前值「y」2,打印出累加器和當前值:12

例子中咱們的回調函數沒有返回任何值,只是打印累加器的值和當前值。若是函數沒有返回值,則默認返回undefined。 在下一次調用時,累加器爲undefined,當前值爲「3」, 所以undefined3被打印出。

在第四次調用時,回調函數依然沒有返回值。 累加器再次爲 undefined ,當前值爲「4」。 undefined4被打印出。

7. Promise.race的用法

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));
  • A: "one"
  • B: "two"
  • C: "two" "one"
  • D: "one" "two"

答案: B

當咱們向Promise.race方法中傳入多個Promise時,會進行 優先 解析(注:只要有一個成功或失敗,就立馬結束)。在這個例子中,咱們用setTimeoutfirstPromisesecondPromise分別設定了500ms和100ms的定時器。這意味着secondPromise會首先解析出字符串two。那麼此時res參數即爲two,是爲輸出結果。

8. try...catch 捕獲錯誤

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();
  • A: "It worked! Hello world!"
  • B: "Oh no an error: undefined
  • C: SyntaxError: can only throw Error objects
  • D: "Oh no an error: Hello world!

答案: D

經過throw語句,我麼能夠建立自定義錯誤。 而經過它,咱們能夠拋出異常。異常能夠是一個字符串, 一個 數字, 一個 布爾類型 或者是一個 對象。在本例中,咱們的異常是字符串'Hello world'.

經過 catch語句,咱們能夠設定當try語句塊中拋出異常後應該作什麼處理。在本例中拋出的異常是字符串'Hello world'. e就是這個字符串,所以被輸出。最終結果就是'Oh an error: Hello world'.

9. import 執行順序問題

// 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;
  • A: running index.js, running sum.js, 3
  • B: running sum.js, running index.js, 3
  • C: running sum.js, 3, running index.js
  • D: running index.js, undefined, running sum.js

答案: B

import命令是編譯階段執行的,在代碼運行以前。所以這意味着被導入的模塊會先運行,而導入模塊的文件會後執行。

這是CommonJS中require()import之間的區別。使用require(),您能夠在運行代碼時根據須要加載依賴項。 若是咱們使用require而不是importrunning index.jsrunning sum.js3會被依次打印。

10. JSON.stringify 過濾須要的字段

const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);
  • A: "{"level":19, "health":90}"
  • B: "{"username": "lydiahallie"}"
  • C: "["level", "health"]"
  • D: "{"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

若是對你有幫助,請關注【前端技能解鎖】:
qrcode_for_gh_d0af9f92df46_258.jpg

相關文章
相關標籤/搜索