主頁 > 企業開發 > 【備戰面試】JavaScript 進階問題串列

【備戰面試】JavaScript 進階問題串列

2023-03-08 08:33:27 企業開發

在原博主Instagram 上每天都會發布 JavaScript 的多選問題,并且同時也會在這個倉庫中發布,

從基礎到進階,測驗你有多了解 JavaScript,重繪你的知識,或者幫助你的 coding 面試!
?? ?? 博主每周都會在這個倉庫下更新新的問題,

答案在問題下方的折疊部分,點擊即可展開問題,祝你好運 ??


1. 輸出是什么?
function sayHi() {
  console.log(name)
  console.log(age)
  var name = 'Lydia'
  let age = 21
}

sayHi()
  • A: Lydiaundefined
  • B: LydiaReferenceError
  • C: ReferenceError21
  • D: undefinedReferenceError
答案

答案: D

在函式內部,我們首先通過 var 關鍵字宣告了 name 變數,這意味著變數被提升了(記憶體空間在創建階段就被設定好了),直到程式運行到定義變數位置之前默認值都是 undefined,因為當我們列印 name 變數時還沒有執行到定義變數的位置,因此變數的值保持為 undefined

通過 letconst 關鍵字宣告的變數也會提升,但是和 var 不同,它們不會被初始化,在我們宣告(初始化)之前是不能訪問它們的,這個行為被稱之為暫時性死區,當我們試圖在宣告之前訪問它們時,JavaScript 將會拋出一個 ReferenceError 錯誤,


2. 輸出是什么?
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
答案

答案: C

由于 JavaScript 的事件回圈,setTimeout 回呼會在遍歷結束后才執行,因為在第一個遍歷中遍歷 i 是通過 var 關鍵字宣告的,所以這個值是全域作用域下的,在遍歷程序中,我們通過一元運算子 ++ 來每次遞增 i 的值,當 setTimeout 回呼執行的時候,i 的值等于 3,

在第二個遍歷中,遍歷 i 是通過 let 關鍵字宣告的:通過 letconst 關鍵字宣告的變數是擁有塊級作用域(指的是任何在 {} 中的內容),在每次的遍歷程序中,i 都有一個新值,并且每個值都在回圈內的作用域中,


3. 輸出是什么?
const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2
  },
  perimeter: () => 2 * Math.PI * this.radius
}

shape.diameter()
shape.perimeter()
  • A: 20 and 62.83185307179586
  • B: 20 and NaN
  • C: 20 and 63
  • D: NaN and 63
答案

答案: B

注意 diameter 的值是一個常規函式,但是 perimeter 的值是一個箭頭函式,

對于箭頭函式,this 關鍵字指向的是它當前周圍作用域(簡單來說是包含箭頭函式的常規函式,如果沒有常規函式的話就是全域物件),這個行為和常規函式不同,這意味著當我們呼叫 perimeter 時,this 不是指向 shape 物件,而是它的周圍作用域(在例子中是 window),

window 中沒有 radius 這個屬性,因此回傳 undefined


4. 輸出是什么?
+true;
!"Lydia";
  • A: 1 and false
  • B: false and NaN
  • C: false and false
答案

答案: A

一元運算子加號嘗試將 bool 轉為 number,true 轉換為 number 的話為 1false0

字串 'Lydia' 是一個真值,真值取反那么就回傳 false


5. 哪一個是正確的?
const bird = {
  size: 'small'
}

const mouse = {
  name: 'Mickey',
  small: true
}
  • A: mouse.bird.size是無效的
  • B: mouse[bird.size]是無效的
  • C: mouse[bird["size"]]是無效的
  • D: 以上三個選項都是有效的
答案

答案: A

在 JavaScript 中,所有物件的 keys 都是字串(除非物件是 Symbol),盡管我們可能不會定義它們為字串,但它們在底層總會被轉換為字串,

當我們使用括號語法時([]),JavaScript 會解釋(或者 unboxes)陳述句,它首先看到第一個開始括號 [ 并繼續前進直到找到結束括號 ],只有這樣,它才會計算陳述句的值,

mouse[bird.size]:首先計算 bird.size,這會得到 smallmouse["small"] 回傳 true

然后使用點語法的話,上面這一切都不會發生,mouse 沒有 bird 這個 key,這也就意味著 mouse.birdundefined,然后當我們使用點語法 mouse.bird.size 時,因為 mouse.birdundefined,這也就變成了 undefined.size,這個行為是無效的,并且會拋出一個錯誤類似 Cannot read property "size" of undefined


6. 輸出是什么?
let c = { greeting: 'Hey!' }
let d

d = c
c.greeting = 'Hello'
console.log(d.greeting)
  • A: Hello
  • B: undefined
  • C: ReferenceError
  • D: TypeError
答案

答案: A

在 JavaScript 中,當設定兩個物件彼此相等時,它們會通過參考進行互動,

首先,變數 c 的值是一個物件,接下來,我們給 d 分配了一個和 c 物件相同的參考,

因此當我們改變其中一個物件時,其實是改變了所有的物件,


7. 輸出是什么?
let a = 3
let b = new Number(3)
let c = 3

console.log(a == b)
console.log(a === b)
console.log(b === c)
  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true
答案

答案: C

new Number() 是一個內建的函式構造器,雖然它看著像是一個 number,但它實際上并不是一個真實的 number:它有一堆額外的功能并且它是一個物件,

當我們使用 == 運算子時,它只會檢查兩者是否擁有相同的,因為它們的值都是 3,因此回傳 true

然后,當我們使用 === 運算子時,兩者的值以及型別都應該是相同的,new Number() 是一個物件而不是 number,因此回傳 false


8. 輸出是什么?
class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor
    return this.newColor
  }

  constructor({ newColor = 'green' } = {}) {
    this.newColor = newColor
  }
}

const freddie = new Chameleon({ newColor: 'purple' })
freddie.colorChange('orange')
  • A: orange
  • B: purple
  • C: green
  • D: TypeError
答案

答案: D

colorChange 是一個靜態方法,靜態方法被設計為只能被創建它們的構造器使用(也就是 Chameleon),并且不能傳遞給實體,因為 freddie 是一個實體,靜態方法不能被實體使用,因此拋出了 TypeError 錯誤,


9. 輸出是什么?
let greeting
greetign = {} // Typo!
console.log(greetign)
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined
答案

答案: A

代碼列印出了一個物件,這是因為我們在全域物件上創建了一個空物件!當我們將 greeting 寫錯成 greetign 時,JS 解釋器實際在上瀏覽器中將它視為 global.greetign = {}(或者 window.greetign = {}),

為了避免這個為題,我們可以使用 `"use strict",這能確保當你宣告變數時必須賦值,


10. 當我們這么做時,會發生什么?
function bark() {
  console.log('Woof!')
}

bark.animal = 'dog'
  • A: 正常運行!
  • B: SyntaxError. 你不能通過這種方式給函式增加屬性,
  • C: undefined
  • D: ReferenceError
答案

答案: A

這在 JavaScript 中是可以的,因為函式是物件!(除了基本型別之外其他都是物件)

函式是一個特殊的物件,你寫的這個代碼其實不是一個實際的函式,函式是一個擁有屬性的物件,并且屬性也可被呼叫,


11. 輸出是什么?
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}

console.log(member.getFullName());
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined
答案

答案: A

你不能像常規物件那樣,給建構式添加屬性,如果你想一次性給所有實體添加特性,你應該使用原型,因此本例中,使用如下方式:

Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}

這才會使 member.getFullName() 起作用,為什么這么做有益的?假設我們將這個方法添加到建構式本身里,也許不是每個 Person 實體都需要這個方法,這將浪費大量記憶體空間,因為它們仍然具有該屬性,這將占用每個實體的記憶體空間,相反,如果我們只將它添加到原型中,那么它只存在于記憶體中的一個位置,但是所有實體都可以訪問它!


12. 輸出是什么?
function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

const lydia = new Person('Lydia', 'Hallie')
const sarah = Person('Sarah', 'Smith')

console.log(lydia)
console.log(sarah)
  • A: Person {firstName: "Lydia", lastName: "Hallie"} and undefined
  • B: Person {firstName: "Lydia", lastName: "Hallie"} and Person {firstName: "Sarah", lastName: "Smith"}
  • C: Person {firstName: "Lydia", lastName: "Hallie"} and {}
  • D:Person {firstName: "Lydia", lastName: "Hallie"} and ReferenceError
答案

答案: A

對于 sarah,我們沒有使用 new 關鍵字,當使用 new 時,this 參考我們創建的空物件,當未使用 new 時,this 參考的是全域物件(global object),

我們說 this.firstName 等于 "Sarah",并且 this.lastName 等于 "Smith",實際上我們做的是,定義了 global.firstName = 'Sarah'global.lastName = 'Smith',而 sarah 本身是 undefined


13. 事件傳播的三個階段是什么?
  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling
答案

答案: D

捕獲(capturing)階段中,事件從祖先元素向下傳播到目標元素,當事件達到目標(target)元素后,冒泡(bubbling)才開始,


14. 所有物件都有原型,
  • A: 對
  • B: 錯
答案

答案: B

除了基本物件(base object),所有物件都有原型,基本物件可以訪問一些方法和屬性,比如 .toString,這就是為什么你可以使用內置的 JavaScript 方法!所有這些方法在原型上都是可用的,雖然 JavaScript 不能直接在物件上找到這些方法,但 JavaScript 會沿著原型鏈找到它們,以便于你使用,


15. 輸出是什么?
function sum(a, b) {
  return a + b
}

sum(1, '2')
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3
答案

答案: C

JavaScript 是一種動態型別語言:我們不指定某些變數的型別,值可以在你不知道的情況下自動轉換成另一種型別,這種型別稱為隱式型別轉換(implicit type coercion),Coercion 是指將一種型別轉換為另一種型別,

在本例中,JavaScript 將數字 1 轉換為字串,以便函式有意義并回傳一個值,在數字型別(1)和字串型別('2')相加時,該數字被視為字串,我們可以連接字串,比如 "Hello" + "World",這里發生的是 "1" + "2",它回傳 "12"


16. 輸出是什么?
let number = 0
console.log(number++)
console.log(++number)
console.log(number)
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2
答案

答案: C

一元后自增運算子 ++

  1. 回傳值(回傳 0
  2. 值自增(number 現在是 1

一元前自增運算子 ++

  1. 值自增(number 現在是 2
  2. 回傳值(回傳 2

結果是 0 2 2.


17. 輸出是什么?
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

如果使用標記模板字面量,第一個引數的值總是包含字串的陣列,其余的引數獲取的是傳遞的運算式的值!


18. 輸出是什么?
function checkAge(data) {
  if (data =https://www.cnblogs.com/mosaicMask/archive/2023/03/07/== { age: 18 }) {
    console.log('You are an adult!')
  } else if (data =https://www.cnblogs.com/mosaicMask/archive/2023/03/07/= { age: 18 }) {
    console.log('You are still an adult.')
  } else {
    console.log(`Hmm.. You don't have an age I guess`)
  }
}

checkAge({ age: 18 })
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess
答案

答案: C

在測驗相等性時,基本型別通過它們的值(value)進行比較,而物件通過它們的參考(reference)進行比較,JavaScript 檢查物件是否具有對記憶體中相同位置的參考,

題目中我們正在比較的兩個物件不是同一個參考:作為引數傳遞的物件參考的記憶體位置,與用于判斷相等的物件所參考的記憶體位置并不同,

這也是 { age: 18 } === { age: 18 }{ age: 18 } == { age: 18 } 都回傳 false 的原因,


19. 輸出是什么?
function getAge(...args) {
  console.log(typeof args)
}

getAge(21)
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"
答案

答案: C

擴展運算子(...args)會回傳實參組成的陣列,而陣列是物件,因此 typeof args 回傳 "object"


20. 輸出是什么?
function getAge() {
  'use strict'
  age = 21
  console.log(age)
}

getAge()
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError
答案

答案: C

使用 "use strict",你可以確保不會意外地宣告全域變數,我們從來沒有宣告變數 age,因為我們使用 "use strict",它將拋出一個參考錯誤,如果我們不使用 "use strict",它就會作業,因為屬性 age 會被添加到全域物件中了,


21. 輸出是什么?
const sum = eval('10*10+5')
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"
答案

答案: A

代碼以字串形式傳遞進來,eval 對其求值,如果它是一個運算式,就像本例中那樣,它對運算式求值,運算式是 10 * 10 + 5,這將回傳數字 105


22. cool_secret 可訪問多長時間?
sessionStorage.setItem('cool_secret', 123)
  • A: 永遠,資料不會丟失,
  • B: 當用戶關掉標簽頁時,
  • C: 當用戶關掉整個瀏覽器,而不只是關掉標簽頁,
  • D: 當用戶關閉電腦時,
答案

答案: B

關閉 tab 標簽頁 后,sessionStorage 存盤的資料才會洗掉,

如果使用 localStorage,那么資料將永遠在那里,除非呼叫了 localStorage.clear()


23. 輸出是什么?
var num = 8
var num = 10

console.log(num)
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError
答案

答案: B

使用 var 關鍵字,你可以用相同的名稱宣告多個變數,然后變數將保存最新的值,

你不能使用 letconst 來實作這一點,因為它們是塊作用域的,


24. 輸出是什么?
const obj = { 1: 'a', 2: 'b', 3: 'c' }
const set = new Set([1, 2, 3, 4, 5])

obj.hasOwnProperty('1')
obj.hasOwnProperty(1)
set.has('1')
set.has(1)
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true
答案

答案: C

所有物件的鍵(不包括 Symbol)在底層都是字串,即使你自己沒有將其作為字串輸入,這就是為什么 obj.hasOwnProperty('1') 也回傳 true

對于集合,它不是這樣作業的,在我們的集合中沒有 '1'set.has('1') 回傳 false,它有數字型別為 1set.has(1) 回傳 true


25. 輸出是什么?
const obj = { a: 'one', b: 'two', a: 'three' }
console.log(obj)
  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError
答案

答案: C

如果你有兩個名稱相同的鍵,則鍵會被替換掉,它仍然位于第一個鍵出現的位置,但是值是最后出現那個鍵的值,


26. JavaScript 全域執行背景關系為你做了兩件事:全域物件和 this 關鍵字,
  • A: 對
  • B: 錯
  • C: 看情況
答案

答案: A

基本執行背景關系是全域執行背景關系:它是代碼中隨處可訪問的內容,


27. 輸出是什么?
for (let i = 1; i < 5; i++) {
  if (i === 3) continue
  console.log(i)
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4
答案

答案: C

如果某個條件回傳 true,則 continue 陳述句跳過本次迭代,


28. 輸出是什么?
String.prototype.giveLydiaPizza = () => {
  return 'Just give Lydia pizza already!'
}

const name = 'Lydia'

name.giveLydiaPizza()
  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined
答案

答案: A

String 是內置的建構式,我們可以向它添加屬性,我只是在它的原型中添加了一個方法,基本型別字串被自動轉換為字串物件,由字串原型函式生成,因此,所有 string(string 物件) 都可以訪問該方法!


29. 輸出是什么?
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


30. 輸出是什么?
const foo = () => console.log('First')
const bar = () => setTimeout(() => console.log('Second'))
const baz = () => console.log('Third')

bar()
foo()
baz()
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First
答案

答案: B

我們有一個 setTimeout 函式,并首先呼叫它,然而,它是最后列印日志的,

這是因為在瀏覽器中,我們不僅有運行時引擎,還有一個叫做 WebAPI 的東西,WebAPI 提供了 setTimeout 函式,也包含其他的,例如 DOM,

callback 推送到 WebAPI 后,setTimeout 函式本身 (但不是回呼!) 將從堆疊中彈出,

現在,foo 被呼叫,列印 "First"

foo 從堆疊中彈出,baz 被呼叫,列印 "Third"

WebAPI 不能隨時向堆疊內添加內容,相反,它將回呼函式推到名為 queue 的地方,

這就是事件回圈開始作業的地方,一個事件回圈查看堆疊和任務佇列,如果堆疊是空的,它接受佇列上的第一個元素并將其推入堆疊,

bar 被呼叫,列印 "Second",然后它被堆疊彈出,


31. 當點擊按鈕時,event.target 是什么?
<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
  • A: Outer div
  • B: Inner div
  • C: button
  • D: 一個包含所有嵌套元素的陣列,
答案

答案: C

導致事件的最深嵌套的元素是事件的 target,你可以通過 event.stopPropagation 來停止冒泡,


32. 當您單擊該段落時,日志輸出是什么?
<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div
答案

答案: A

如果我們點擊 p,我們會看到兩個日志:pdiv,在事件傳播期間,有三個階段:捕獲、目標和冒泡,默認情況下,事件處理程式在冒泡階段執行(除非將 useCapture 設定為 true),它從嵌套最深的元素向外傳播,


33. 輸出是什么?
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 回傳函式的副本,但帶有系結背景關系!它不是立即執行的,


34. 輸出是什么?
function sayHi() {
  return (() => 0)()
}

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

答案: B

sayHi 方法回傳的是立即執行函式 (IIFE) 的回傳值,此立即執行函式的回傳值是 0, 型別是 number

參考:只有 7 種內置型別:nullundefinedbooleannumberstringobject, symbolbigintfunction 不是一種型別,函式是物件,它的型別是object


35. 下面哪些值是 falsy?
0
new Number(0)
('')
(' ')
new Boolean(false)
undefined
  • A: 0, '', undefined
  • B: 0, new Number(0), '', new Boolean(false), undefined
  • C: 0, '', new Boolean(false), undefined
  • D: All of them are falsy
答案

答案: A

只有 8 種 falsy 值:

  • undefined
  • null
  • NaN
  • false
  • '' (empty string)
  • 0
  • -0
  • 0n (BigInt(0))

Function 建構式,比如 new Numbernew Boolean,是 truthy,


36. 輸出是什么?
console.log(typeof typeof 1)
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"
答案

答案: B

typeof 1 回傳 "number"
typeof "number" 回傳 "string"


37. 輸出是什么?
const numbers = [1, 2, 3]
numbers[10] = 11
console.log(numbers)
  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError
答案

答案: C

當你為陣列設定超過陣列長度的值的時候, JavaScript 會創建名為 "empty slots" 的東西,它們的值實際上是 undefined,你會看到以下場景:

[1, 2, 3, 7 x empty, 11]

這取決于你的運行環境(每個瀏覽器,以及 node 環境,都有可能不同)


38. 輸出是什么?
(() => {
  let x, y
  try {
    throw new Error()
  } catch (x) {
    (x = 1), (y = 2)
    console.log(x)
  }
  console.log(x)
  console.log(y)
})()
  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined
答案

答案: A

catch 代碼塊接收引數 x,當我們傳遞引數時,這與之前定義的變數 x 不同 ,這個 x 是屬于 catch 塊級作用域的,

然后,我們將塊級作用域中的變數賦值為 1,同時也設定了變數 y 的值,現在,我們列印塊級作用域中的變數 x,值為 1

catch 塊之外的變數 x 的值仍為 undefinedy 的值為 2,當我們在 catch 塊之外執行 console.log(x) 時,回傳 undefinedy 回傳 2


39. JavaScript 中的一切都是?
  • A: 基本型別與物件
  • B: 函式與物件
  • C: 只有物件
  • D: 數字與物件

答案

答案: A

JavaScript 只有基本型別和物件,

基本型別包括 boolean, null, undefined, bigint, number, string, symbol


40. 輸出是什么?
[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur)
  },
  [1, 2]
)
  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]
答案

答案: C

[1, 2]是初始值,初始值將會作為首次呼叫時第一個引數 acc 的值,在第一次執行時, acc 的值是 [1, 2]cur 的值是 [0, 1],合并它們,結果為 [1, 2, 0, 1]
第二次執行, acc 的值是 [1, 2, 0, 1]cur 的值是 [2, 3],合并它們,最終結果為 [1, 2, 0, 1, 2, 3]


41. 輸出是什么?
!!null
!!''
!!1
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false
答案

答案: B

null 是 falsy, !null 的值是 true!true 的值是 false

"" 是 falsy, !"" 的值是 true!true 的值是 false

1 是 truthy, !1 的值是 false!false 的值是 true


42. setInterval 方法的回傳值是什么?
setInterval(() => console.log('Hi'), 1000)
  • A: 一個唯一的 id
  • B: 該方法指定的毫秒數
  • C: 傳遞的函式
  • D: undefined
答案

答案: A

setInterval 回傳一個唯一的 id,此 id 可被用于 clearInterval 函式來取消定時,


43. 輸出是什么?
[...'Lydia']
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]
答案

答案: A

string 型別是可迭代的,擴展運算子將迭代的每個字符映射成一個元素,


44. 輸出是什么?
function* generator(i) {
  yield i;
  yield i * 2;
}

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
  • A: [0, 10], [10, 20]
  • B: 20, 20
  • C: 10, 20
  • D: 0, 10 and 10, 20
答案

答案: C

一般的函式在執行之后是不能中途停下的,但是,生成器函式卻可以中途 “停下”,之后可以再從停下的地方繼續,當生成器遇到yield關鍵字的時候,會生成yield后面的值,注意,生成器在這種情況下不 回傳 (return ) 值,而是 生成 (yield) 值,

首先,我們用10作為引數i來初始化生成器函式,然后使用next()方法一步步執行生成器,第一次執行生成器的時候,i的值為10,遇到第一個yield關鍵字,它要生成i的值,此時,生成器 “暫停”,生成了10

然后,我們再執行next()方法,生成器會從剛才暫停的地方繼續,這個時候i還是10,于是我們走到了第二個yield關鍵字處,這時候需要生成的值是i*2i10,那么此時生成的值便是20,所以這道題的最終結果是10,20

45. 回傳值是什么?
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,是為輸出結果,


46. 輸出是什么?
let person = { name: "Lydia" };
const members = [person];
person = null;

console.log(members);
  • A: null
  • B: [null]
  • C: [{}]
  • D: [{ name: "Lydia" }]
答案

答案: D

首先我們宣告了一個擁有name屬性的物件 person

然后我們又宣告了一個變數members. 將首個元素賦值為變數person, 當設定兩個物件彼此相等時,它們會通過 參考 進行互動,但是當你將參考從一個變數分配至另一個變數時,其實只是執行了一個 復制 操作,(注意一點,他們的參考 并不相同!)

接下來我們讓person等于null

我們沒有修改陣列第一個元素的值,而只是修改了變數person的值,因為元素(復制而來)的參考與person不同,members的第一個元素仍然保持著對原始物件的參考,當我們輸出members陣列時,第一個元素會將參考的物件列印出來,


47. 輸出是什么?
const person = {
  name: "Lydia",
  age: 21
};

for (const item in person) {
  console.log(item);
}
  • A: { name: "Lydia" }, { age: 21 }
  • B: "name", "age"
  • C: "Lydia", 21
  • D: ["name", "Lydia"], ["age", 21]
答案

答案: B

for-in回圈中,我們可以通過物件的 key 來進行迭代,也就是這里的nameage,在底層,物件的 key 都是字串(如果他們不是 Symbol 的話),在每次回圈中,我們將item設定為當前遍歷到的 key.所以一開始,itemname,之后 item輸出的則是age


48. 輸出是什么?
console.log(3 + 4 + "5");
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"
答案

答案: B

當所有運算子的 優先級 相同時,計算運算式需要確定運算子的結合順序,即從右到左還是從左往右,在這個例子中,我們只有一類運算子+,對于加法來說,結合順序就是從左到右,

3 + 4首先計算,得到數字7.

由于型別的強制轉換,7 + '5'的結果是"75". JavaScript 將7轉換成了字串,可以參考問題 15.我們可以用+號把兩個字串連接起來, "7" + "5" 就得到了"75".


49. num的值是什么?
const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN
答案

答案: C

只回傳了字串中第一個字母,設定了 進制 后 (也就是第二個引數,指定需要決議的數字是什么進制:十進制、十六機制、八進制、二進制等等……),parseInt 檢查字串中的字符是否合法,一旦遇到一個在指定進制中不合法的字符后,立即停止決議并且忽略后面所有的字符,

*就是不合法的數字字符,所以只決議到"7",并將其決議為十進制的7. num的值即為7.


50. 輸出是什么?
[1, 2, 3].map(num => {
  if (typeof num === "number") return;
  return num * 2;
});
  • A: []
  • B: [null, null, null]
  • C: [undefined, undefined, undefined]
  • D: [ 3 x empty ]
答案

答案: C

對陣列進行映射的時候,num就是當前回圈到的元素,在這個例子中,所有的映射都是 number 型別,所以 if 中的判斷typeof num === "number"結果都是true.map 函式創建了新陣列并且將函式的回傳值插入陣列,

但是,沒有任何值回傳,當函式沒有回傳任何值時,即默認回傳undefined.對陣列中的每一個元素來說,函式塊都得到了這個回傳值,所以結果中每一個元素都是undefined.


51. 輸出的是什么?
function getInfo(member, year) {
  member.name = "Lydia";
  year = "1998";
}

const person = { name: "Sarah" };
const birthYear = "1997";

getInfo(person, birthYear);

console.log(person, birthYear);
  • A: { name: "Lydia" }, "1997"
  • B: { name: "Sarah" }, "1998"
  • C: { name: "Lydia" }, "1998"
  • D: { name: "Sarah" }, "1997"
答案

答案: A

普通引數都是 傳遞的,而物件則不同,是 參考 傳遞,所以說,birthYear是值傳遞,因為他是個字串而不是物件,當我們對引數進行值傳遞時,會創建一份該值的 復制 ,(可以參考問題 46)

變數birthYear有一個對"1997"的參考,而傳入的引數也有一個對"1997"的參考,但二者的參考并不相同,當我們通過給 year賦值"1998"來更新year的值的時候我們只是更新了year(的參考),此時birthYear仍然是"1997".

person是個物件,引數member參考與之 相同的 物件,當我們修改member所參考物件的屬性時,person的相應屬性也被修改了,因為他們參考了相同的物件,personname屬性也變成了 "Lydia".


52. 輸出是什么?
function greeting() {
  throw "Hello world!";
}

function sayHi() {
  try {
    const data = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/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'.


53. 輸出是什么?
function Car() {
  this.make = "Lamborghini";
  return { make: "Maserati" };
}

const myCar = new Car();
console.log(myCar.make);
  • A: "Lamborghini"
  • B: "Maserati"
  • C: ReferenceError
  • D: TypeError
答案

答案: B

回傳屬性的時候,屬性的值等于 回傳的 值,而不是建構式中設定的值,我們回傳了字串 "Maserati",所以 myCar.make等于"Maserati".


54. 輸出是什么?
(() => {
  let x = (y = 10);
})();

console.log(typeof x);
console.log(typeof y);
  • A: "undefined", "number"
  • B: "number", "number"
  • C: "object", "number"
  • D: "number", "undefined"
答案

答案: A

let x = y = 10; 是下面這個運算式的縮寫:

y = 10;
let x = y;

我們設定y等于10時,我們實際上增加了一個屬性y給全域物件 (瀏覽器里的window, Nodejs 里的global),在瀏覽器中, window.y等于10.

然后我們宣告了變數x等于y,也是10.但變數是使用 let宣告的,它只作用于 塊級作用域,僅在宣告它的塊中有效;就是案例中的立即呼叫運算式 (IIFE),使用typeof運算子時,操作值 x沒有被定義:因為我們在x宣告塊的外部,無法呼叫它,這就意味著x未定義,未分配或是未宣告的變數型別為"undefined". console.log(typeof x)回傳"undefined".

而我們創建了全域變數y,并且設定y等于10.這個值在我們的代碼各處都訪問的到, y已經被定義了,而且有一個"number"型別的值, console.log(typeof y)回傳"number".


55. 輸出是什么?
class Dog {
  constructor(name) {
    this.name = name;
  }
}

Dog.prototype.bark = function() {
  console.log(`Woof I am ${this.name}`);
};

const pet = new Dog("Mara");

pet.bark();

delete Dog.prototype.bark;

pet.bark();
  • A: "Woof I am Mara", TypeError
  • B: "Woof I am Mara","Woof I am Mara"
  • C: "Woof I am Mara", undefined
  • D: TypeError, TypeError
答案

答案: A

我們可以用delete關鍵字洗掉物件的屬性,對原型也是適用的,洗掉了原型的屬性后,該屬性在原型鏈上就不可用了,在本例中,函式bark在執行了delete Dog.prototype.bark后不可用,然而后面的代碼還在呼叫它,

當我們嘗試呼叫一個不存在的函式時TypeError例外會被拋出,在本例中就是 TypeError: pet.bark is not a function,因為pet.barkundefined.


56. 輸出是什么?
const set = new Set([1, 1, 2, 3, 4]);

console.log(set);
  • A: [1, 1, 2, 3, 4]
  • B: [1, 2, 3, 4]
  • C: {1, 1, 2, 3, 4}
  • D: {1, 2, 3, 4}
答案

答案: D

Set物件是獨一無二的值的集合:也就是說同一個值在其中僅出現一次,

我們傳入了陣列[1, 1, 2, 3, 4],他有一個重復值1.以為一個集合里不能有兩個重復的值,其中一個就被移除了,所以結果是 {1, 2, 3, 4}.


57. 輸出是什么?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";

myCounter += 1;

console.log(myCounter);
  • A: 10
  • B: 11
  • C: Error
  • D: NaN
答案

答案: C

引入的模塊是 只讀 的:你不能修改引入的模塊,只有匯出他們的模塊才能修改其值,

當我們給myCounter增加一個值的時候會拋出一個例外: myCounter是只讀的,不能被修改,


58. 輸出是什么?
const name = "Lydia";
age = 21;

console.log(delete name);
console.log(delete age);
  • A: false, true
  • B: "Lydia", 21
  • C: true, true
  • D: undefined, undefined
答案

答案: A

delete運算子回傳一個布林值: true指洗掉成功,否則回傳false. 但是通過 var, constlet 關鍵字宣告的變數無法用 delete 運算子來洗掉,

name變數由const關鍵字宣告,所以洗掉不成功:回傳 false. 而我們設定age等于21時,我們實際上添加了一個名為age的屬性給全域物件,物件中的屬性是可以洗掉的,全域物件也是如此,所以delete age回傳true.


59. 輸出是什么?
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;

console.log(y);
  • A: [[1, 2, 3, 4, 5]]
  • B: [1, 2, 3, 4, 5]
  • C: 1
  • D: [1]
答案

答案: C

我們可以通過解構賦值來決議來自物件的陣列或屬性的值,比如說:

[a, b] = [1, 2];

a的值現在是1b的值現在是2.而在題目中,我們是這么做的:

[y] = [1, 2, 3, 4, 5];

也就是說,y等于陣列的第一個值就是數字1.我們輸出y, 回傳1.


60. 輸出是什么?
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };

console.log(admin);
  • A: { admin: true, user: { name: "Lydia", age: 21 } }
  • B: { admin: true, name: "Lydia", age: 21 }
  • C: { admin: true, user: ["Lydia", 21] }
  • D: { admin: true }
答案

答案: B

擴展運算子...為物件的組合提供了可能,你可以復制物件中的鍵值對,然后把它們加到另一個物件里去,在本例中,我們復制了user物件鍵值對,然后把它們加入到admin物件中,admin物件就擁有了這些鍵值對,所以結果為{ admin: true, name: "Lydia", age: 21 }.


61. 輸出是什么?
const person = { name: "Lydia" };

Object.defineProperty(person, "age", { value: 21 });

console.log(person);
console.log(Object.keys(person));
  • A: { name: "Lydia", age: 21 }, ["name", "age"]
  • B: { name: "Lydia", age: 21 }, ["name"]
  • C: { name: "Lydia"}, ["name", "age"]
  • D: { name: "Lydia"}, ["age"]
答案

答案: B

通過defineProperty方法,我們可以給物件添加一個新屬性,或者修改已經存在的屬性,而我們使用defineProperty方法給物件添加了一個屬性之后,屬性默認為 不可列舉 (not enumerable). Object.keys方法僅回傳物件中 可列舉 (enumerable) 的屬性,因此只剩下了"name".

defineProperty方法添加的屬性默認不可變,你可以通過writable, configurableenumerable屬性來改變這一行為,這樣,defineProperty方法可以讓您更好地控制要添加到物件的屬性,


62. 輸出是什么?
const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/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,則該屬性會被排除在外,


63. 輸出是什么?
let num = 10;

const increaseNumber = () => num++;
const increasePassedNumber = number => number++;

const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);

console.log(num1);
console.log(num2);
  • A: 10, 10
  • B: 10, 11
  • C: 11, 11
  • D: 11, 12
答案

答案: A

一元運算子 ++ 先回傳 操作值,再累加 操作值,num1的值是10,因為increaseNumber函式首先回傳num的值,也就是10,隨后再進行 num的累加,

num210因為我們將 num1傳入increasePassedNumber. number等于10num1的值,同樣道理,++ 先回傳 操作值,再累加 操作值,)number10,所以num2也是10.


64. 輸出什么?
const value = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/{ number: 10 };

const multiply = (x = { ...value }) => {
  console.log(x.number *= 2);
};

multiply();
multiply();
multiply(value);
multiply(value);
  • A: 20, 40, 80, 160
  • B: 20, 40, 20, 40
  • C: 20, 20, 20, 40
  • D: NaN, NaN, 20, 40
答案

答案: C

在 ES6 中,我們可以使用默認值初始化引數,如果沒有給函式傳參,或者傳的參值為 "undefined" ,那么引數的值將是默認值,上述例子中,我們將 value 物件進行了解構并傳到一個新物件中,因此 x 的默認值為 {number:10}

默認引數在呼叫時才會進行計算,每次呼叫函式時,都會創建一個新的物件,我們前兩次呼叫 multiply 函式且不傳遞值,那么每一次 x 的默認值都為 {number:10} ,因此列印出該數字的乘積值為20

第三次呼叫 multiply 時,我們傳遞了一個引數,即物件value*=運算子實際上是x.number = x.number * 2的簡寫,我們修改了x.number的值,并列印出值20

第四次,我們再次傳遞value物件, x.number之前被修改為20,所以x.number * = 2列印為40


65. 輸出什么?
[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被列印出,


66. 使用哪個建構式可以成功繼承Dog類?
class Dog {
  constructor(name) {
    this.name = name;
  }
};

class Labrador extends Dog {
  // 1 
  constructor(name, size) {
    this.size = size;
  }
  // 2
  constructor(name, size) {
    super(name);
    this.size = size;
  }
  // 3
  constructor(size) {
    super(name);
    this.size = size;
  }
  // 4 
  constructor(name, size) {
    this.name = name;
    this.size = size;
  }

};
  • A: 1
  • B: 2
  • C: 3
  • D: 4
答案

答案: B

在子類中,在呼叫super之前不能訪問到this關鍵字, 如果這樣做,它將拋出一個ReferenceError:1 和 4 將引發一個參考錯誤,

使用super關鍵字,需要用給定的引數來呼叫父類的建構式, 父類的建構式接收name引數,因此我們需要將name傳遞給super

Labrador類接收兩個引數,name引數是由于它繼承了Dogsize作為Labrador類的額外屬性,它們都需要傳遞給Labrador的建構式,因此使用建構式 2 正確完成,


67. 輸出什么?
// 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會被依次列印,


68. 輸出什么?
console.log(Number(2) === Number(2))
console.log(Boolean(false) === Boolean(false))
console.log(Symbol('foo') === Symbol('foo'))
  • A: true, true, false
  • B: false, true, false
  • C: true, false, true
  • D: true, true, true
答案

答案: A

每個Symbol都是完全唯一的,傳遞給Symbol的引數只是給Symbol的一個描述, Symbol的值不依賴于傳遞的引數, 當我們測驗相等時,我們創建了兩個全新的符號:第一個Symbol('foo'),第二個Symbol('foo'),這兩個值是唯一的,彼此不相等,因此回傳false


69. 輸出什么?
const name = "Lydia Hallie"
console.log(name.padStart(13))
console.log(name.padStart(2))
  • A: "Lydia Hallie", "Lydia Hallie"
  • B: " Lydia Hallie", " Lydia Hallie" ("[13x whitespace]Lydia Hallie", "[2x whitespace]Lydia Hallie")
  • C: " Lydia Hallie", "Lydia Hallie" ("[1x whitespace]Lydia Hallie", "Lydia Hallie")
  • D: "Lydia Hallie", "Lyd"
答案

答案: C

使用padStart方法,我們可以在字串的開頭添加填充,傳遞給此方法的引數是字串的總長度(包含填充),字串Lydia Hallie的長度為12,因此name.padStart(13)在字串的開頭只會插入 1(13 - 12 = 1)個空格,

如果傳遞給padStart方法的引數小于字串的長度,則不會添加填充,


70. 輸出什么?
console.log("??" + "??");
  • A: "????"
  • B: 257548
  • C: A string containing their code points
  • D: Error
答案

答案: A

使用+運算子,您可以連接字串, 上述情況,我們將字串“??”與字串”??“連接起來,產生”????“


71. 如何能列印出console.log陳述句后注釋掉的值?
function* startGame() {
  const 答案 = yield "Do you love JavaScript?";
  if (答案 !== "Yes") {
    return "Oh wow... Guess we're gone here";
  }
  return "JavaScript loves you back ??";
}

const game = startGame();
console.log(/* 1 */); // Do you love JavaScript?
console.log(/* 2 */); // JavaScript loves you back ??
  • A: game.next("Yes").value and game.next().value
  • B: game.next.value("Yes") and game.next.value()
  • C: game.next().value and game.next("Yes").value
  • D: game.next.value() and game.next.value("Yes")
答案

答案: C

generator函式在遇到yield關鍵字時會 “暫停” 其執行, 首先,我們需要讓函式產生字串Do you love JavaScript?,這可以通過呼叫game.next().value來完成,上述函式的第一行就有一個yield關鍵字,那么運行立即停止了,yield運算式本身沒有回傳值,或者說總是回傳undefined,這意味著此時變數 答案undefined

next方法可以帶一個引數,該引數會被當作上一個 yield 運算式的回傳值,當我們呼叫game.next("Yes").value時,先前的 yield 的回傳值將被替換為傳遞給next()函式的引數"Yes",此時變數 答案 被賦值為 "Yes"if陳述句回傳false,所以JavaScript loves you back ??被列印,


72. 輸出什么?
console.log(String.raw`Hello\nworld`);
  • A: Hello world!
  • B: Hello
         world
  • C: Hello\nworld
  • D: Hello\n
         world
答案

答案: C

String.raw函式是用來獲取一個模板字串的原始字串的,它回傳一個字串,其中忽略了轉義符(\n\v\t等),但反斜杠可能造成問題,因為你可能會遇到下面這種類似情況:

const path = `C:\Documents\Projects\table.html`
String.raw`${path}`

這將導致:

"C:DocumentsProjects able.html"

直接使用String.raw

String.raw`C:\Documents\Projects\table.html`

它會忽略轉義字符并列印:C:\Documents\Projects\table.html

上述情況,字串是Hello\nworld被列印出,


73. 輸出什么?
async function getData() {
  return await Promise.resolve("I made it!");
}

const data = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/getData();
console.log(data);
  • A: "I made it!"
  • B: Promise {<resolved>: "I made it!"}
  • C: Promise {<pending>}
  • D: undefined
答案

答案: C

異步函式始侄訓傳一個 promise,await仍然需要等待 promise 的解決:當我們呼叫getData()并將其賦值給data,此時datagetData方法回傳的一個掛起的 promise,該 promise 并沒有解決,

如果我們想要訪問已解決的值"I made it!",可以在data上使用.then()方法:

data.then(res => console.log(res))

這樣將列印 "I made it!"


74. 輸出什么?
function addToList(item, list) {
  return list.push(item);
}

const result = addToList("apple", ["banana"]);
console.log(result);
  • A: ['apple', 'banana']
  • B: 2
  • C: true
  • D: undefined
答案

答案: B

push()方法回傳新陣列的長度,一開始,陣列包含一個元素(字串"banana"),長度為 1, 在陣列中添加字串"apple"后,長度變為 2,并將從addToList函式回傳,

push方法修改原始陣列,如果你想從函式回傳陣列而不是陣列長度,那么應該在 push item之后回傳list


75. 輸出什么?
const box = { x: 10, y: 20 };

Object.freeze(box);

const shape = box;
shape.x = 100;
console.log(shape)
  • A: { x: 100, y: 20 }
  • B: { x: 10, y: 20 }
  • C: { x: 100 }
  • D: ReferenceError
答案

答案: B

Object.freeze使得無法添加、洗掉或修改物件的屬性(除非屬性的值是另一個物件),

當我們創建變數shape并將其設定為等于凍結物件box時,shape指向的也是凍結物件,你可以使用Object.isFrozen檢查一個物件是否被凍結,上述情況,Object.isFrozen(shape)將回傳true

由于shape被凍結,并且x的值不是物件,所以我們不能修改屬性xx仍然等于10{x:10,y:20}被列印,

注意,上述例子我們對屬性x進行修改,可能會導致拋出 TypeError 例外(最常見但不僅限于嚴格模式下時),


76. 輸出什么?
const { name: myName } = { name: "Lydia" };

console.log(name);
  • A: "Lydia"
  • B: "myName"
  • C: undefined
  • D: ReferenceError
答案

答案: D

當我們從右側的物件解構屬性name時,我們將其值Lydia分配給名為myName的變數,

使用{name:myName},我們是在告訴 JavaScript 我們要創建一個名為myName的新變數,并且其值是右側物件的name屬性的值,

當我們嘗試列印name,一個未定義的變數時,就會引發ReferenceError


77. 以下是個純函式么?
function sum(a, b) {
  return a + b;
}
  • A: Yes
  • B: No
答案

答案: A

純函式在相同的輸入值時,需產生相同的輸出,其輸出的結果,與輸入值以外的其他隱藏資訊或狀態無關,也和由 I/O 設備產生的外部輸出無關,
純函式不會產生副作用,

純函式與副作用的定義可參考:
https://zh.wikipedia.org/wiki/副作用_(計算機科學)


78. 輸出什么?
const add = () => {
  const cache = {};
  return num => {
    if (num in cache) {
      return `From cache! ${cache[num]}`;
    } else {
      const result = num + 10;
      cache[num] = result;
      return `Calculated! ${result}`;
    }
  };
};

const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 * 2));
  • A: Calculated! 20 Calculated! 20 Calculated! 20
  • B: Calculated! 20 From cache! 20 Calculated! 20
  • C: Calculated! 20 From cache! 20 From cache! 20
  • D: Calculated! 20 From cache! 20 Error
答案

答案: C

add函式是一個記憶函式, 通過記憶化,我們可以快取函式的結果,以加快其執行速度,上述情況,我們創建一個cache物件,用于存盤先前回傳過的值,

如果我們使用相同的引數多次呼叫addFunction函式,它首先檢查快取中是否已有該值,如果有,則回傳快取值,這將節省執行時間,如果沒有,那么它將計算該值,并存盤在快取中,

我們用相同的值三次呼叫了addFunction函式:

在第一次呼叫,num等于10時函式的值尚未快取,if 陳述句num in cache回傳false,else 塊的代碼被執行:Calculated! 20,并且其結果被添加到快取物件,cache現在看起來像{10:20}

第二次,cache物件包含10的回傳值, if 陳述句 num in cache 回傳trueFrom cache! 20被列印,

第三次,我們將5 * 2(值為 10) 傳遞給函式, cache物件包含10的回傳值, if 陳述句 num in cache 回傳trueFrom cache! 20被列印,


79. 輸出什么?
const myLifeSummedUp = ["?", "??", "??", "??"]

for (let item in myLifeSummedUp) {
  console.log(item)
}

for (let item of myLifeSummedUp) {
  console.log(item)
}
  • A: 0 1 2 3 and "?" "??" "??" "??"
  • B: "?" "??" "??" "??" and "?" "??" "??" "??"
  • C: "?" "??" "??" "??" and 0 1 2 3
  • D: 0 1 2 3 and {0: "?", 1: "??", 2: "??", 3: "??"}
答案

答案: A

通過for-in回圈,我們可以遍歷一個物件自有的繼承的可列舉的非 Symbol 的屬性, 在陣列中,可列舉屬性是陣列元素的 “鍵”, 即它們的索引, 類似于下面這個物件:

{0: "?", 1: "??", 2: "??", 3: "??"}

其中鍵則是可列舉屬性,因此 0123被記錄,

通過for-of回圈,我們可以迭代可迭代物件(包括 ArrayMapSetStringarguments等),當我們迭代陣列時,在每次迭代中,不同屬性的值將被分配給變數item,因此“?”“??”“??”“??”被列印,


80. 輸出什么?
const list = [1 + 2, 1 * 2, 1 / 2]
console.log(list)
  • A: ["1 + 2", "1 * 2", "1 / 2"]
  • B: ["12", 2, 0.5]
  • C: [3, 2, 0.5]
  • D: [1, 1, 1]
答案

答案: C

陣列元素可以包含任何值, 數字,字串,布林值,物件,陣列,nullundeifned,以及其他表達式,如日期,函式和計算,

元素將等于回傳的值, 1 + 2回傳31 * 2回傳'2,'1 / 2回傳0.5


81. 輸出什么?
function sayHi(name) {
  return `Hi there, ${name}`
}

console.log(sayHi())
  • A: Hi there,
  • B: Hi there, undefined
  • C: Hi there, null
  • D: ReferenceError
答案

答案: B

默認情況下,如果不給函式傳參,引數的值將為undefined, 上述情況,我們沒有給引數name傳值, name等于undefined,并被列印,

在 ES6 中,我們可以使用默認引數覆寫此默認的undefined值, 例如:

function sayHi(name =“Lydia”){...}

在這種情況下,如果我們沒有傳遞值或者如果我們傳遞undefinedname總是等于字串Lydia


82. 輸出什么?
var status = "??"

setTimeout(() => {
  const status = "??"

  const data = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/{
    status:"??",
    getStatus() {
      return this.status
    }
  }

  console.log(data.getStatus())
  console.log(data.getStatus.call(this))
}, 0)
  • A: "??" and "??"
  • B: "??" and "??"
  • C: "??" and "??"
  • D: "??" and "??"
答案

答案: B

this關鍵字的指向取決于使用它的位置, 在函式中,比如getStatusthis指向的是呼叫它的物件,上述例子中data物件呼叫了getStatus,因此this指向的就是data物件, 當我們列印this.status時,data物件的status屬性被列印,即"??"

使用call方法,可以更改this指向的物件,data.getStatus.call(this)是將this的指向由data物件更改為全域物件,在全域物件上,有一個名為status的變數,其值為”??“, 因此列印this.status時,會列印“??”


83. 輸出什么?
const person = {
  name: "Lydia",
  age: 21
}

let city = person.city
city = "Amsterdam"

console.log(person)
  • A: { name: "Lydia", age: 21 }
  • B: { name: "Lydia", age: 21, city: "Amsterdam" }
  • C: { name: "Lydia", age: 21, city: undefined }
  • D: "Amsterdam"
答案

答案: A

我們將變數city設定為等于person物件上名為city的屬性的值, 這個物件上沒有名為city的屬性,因此變數city的值為undefined

請注意,我們沒有參考person物件本身,只是將變數city設定為等于person物件上city屬性的當前值,

然后,我們將city設定為等于字串“Amsterdam”, 這不會更改 person 物件:沒有對該物件的參考,

因此列印person物件時,會回傳未修改的物件,


84. 輸出什么?
function checkAge(age) {
  if (age < 18) {
    const message = "Sorry, you're too young."
  } else {
    const message = "Yay! You're old enough!"
  }

  return message
}

console.log(checkAge(21))
  • A: "Sorry, you're too young."
  • B: "Yay! You're old enough!"
  • C: ReferenceError
  • D: undefined
答案

答案: C

constlet宣告的變數是具有塊級作用域的,塊是大括號({})之間的任何東西,即上述情況if / else陳述句的花括號, 由于塊級作用域,我們無法在宣告的塊之外參考變數,因此拋出ReferenceError


85. 什么樣的資訊將被列印?
fetch('https://www.website.com/api/user/1')
  .then(res => res.json())
  .then(res => console.log(res))
  • A: fetch方法的結果
  • B: 第二次呼叫fetch方法的結果
  • C: 前一個.then()中回呼方法回傳的結果
  • D: 總是undefined
答案

答案: C

第二個.thenres的值等于前一個.then中的回呼函式回傳的值, 你可以像這樣繼續鏈接.then,將值傳遞給下一個處理程式,


86. 哪個選項是將hasName設定為true的方法,前提是不能將true作為引數傳遞?
function getName(name) {
  const hasName = //
}
  • A: !!name
  • B: name
  • C: new Boolean(name)
  • D: name.length
答案

答案: A

使用邏輯非運算子!,將回傳一個布林值,使用!! name,我們可以確定name的值是真的還是假的, 如果name是真實的,那么!name回傳false!false回傳true

通過將hasName設定為name,可以將hasName設定為等于傳遞給getName函式的值,而不是布林值true

new Boolean(true)回傳一個物件包裝器,而不是布林值本身,

name.length回傳傳遞的引數的長度,而不是布林值true

87. 輸出什么?
console.log("I want pizza"[0])
  • A: """
  • B: "I"
  • C: SyntaxError
  • D: undefined
答案

答案: B

可以使用方括號表示法獲取字串中特定索引的字符,字串中的第一個字符具有索引 0,依此類推, 在這種情況下,我們想要得到索引為 0 的元素,字符'I'被記錄,

請注意,IE7 及更低版本不支持此方法, 在這種情況下,應該使用.charAt()


88. 輸出什么?
function sum(num1, num2 = num1) {
  console.log(num1 + num2)
}

sum(10)
  • A: NaN
  • B: 20
  • C: ReferenceError
  • D: undefined
答案

答案: B

您可以將默認引數的值設定為函式的另一個引數,只要另一個引數定義在其之前即可, 我們將值10傳遞給sum函式, 如果sum函式只接收 1 個引數,則意味著沒有傳遞num2的值,這種情況下,num1的值等于傳遞的值10num2的默認值是num1的值,即10num1 + num2回傳20

如果您嘗試將默認引數的值設定為后面定義的引數,則可能導致引數的值尚未初始化,從而引發錯誤,比如:

function test(m = n, n = 2) {
	console.log(m, n)
}
test() // Uncaught ReferenceError: Cannot access 'n' before initialization
test(3) // 3 2
test(3, 4) // 3 4


89. 輸出什么?
// module.js 
export default () => "Hello world"
export const name = "Lydia"

// index.js 
import * as data from "./module"

console.log(data)
  • A: { default: function default(), name: "Lydia" }
  • B: { default: function default() }
  • C: { default: "Hello world", name: "Lydia" }
  • D: Global object of module.js
答案

答案: A

使用import * as name語法,我們將module.js檔案中所有export匯入到index.js檔案中,并且創建了一個名為data的新物件, 在module.js檔案中,有兩個匯出:默認匯出和命名匯出, 默認匯出是一個回傳字串 “Hello World” 的函式,命名匯出是一個名為name的變數,其值為字串“Lydia”

data物件具有默認匯出的default屬性,其他屬性具有指定 exports 的名稱及其對應的值,


90. 輸出什么?
class Person {
  constructor(name) {
    this.name = name
  }
}

const member = new Person("John")
console.log(typeof member)
  • A: "class"
  • B: "function"
  • C: "object"
  • D: "string"
答案

答案: C

類是建構式的語法糖,如果用建構式的方式來重寫Person類則將是:

function Person() {
  this.name = name
}

通過new來呼叫建構式,將會生成建構式Person的實體,對實體執行typeof關鍵字將回傳"object",上述情況列印出"object"


91. 輸出什么?
let newList = [1, 2, 3].push(4)

console.log(newList.push(5))
  • A: [1, 2, 3, 4, 5]
  • B: [1, 2, 3, 5]
  • C: [1, 2, 3, 4]
  • D: Error
答案

答案: D

.push方法回傳陣列的長度,而不是陣列本身! 通過將newList設定為[1,2,3].push(4),實際上newList等于陣列的新長度:4

然后,嘗試在newList上使用.push方法, 由于newList是數值4,拋出 TypeError,


92. 輸出什么?
function giveLydiaPizza() {
  return "Here is pizza!"
}

const giveLydiaChocolate = () => "Here's chocolate... now go hit the gym already."

console.log(giveLydiaPizza.prototype)
console.log(giveLydiaChocolate.prototype)
  • A: { constructor: ...} { constructor: ...}
  • B: {} { constructor: ...}
  • C: { constructor: ...} {}
  • D: { constructor: ...} undefined
答案

答案: D

常規函式,例如giveLydiaPizza函式,有一個prototype屬性,它是一個帶有constructor屬性的物件(原型物件), 然而,箭頭函式,例如giveLydiaChocolate函式,沒有這個prototype屬性, 嘗試使用giveLydiaChocolate.prototype訪問prototype屬性時會回傳undefined


93. 輸出什么?
const person = {
  name: "Lydia",
  age: 21
}

for (const [x, y] of Object.entries(person)) {
  console.log(x, y)
}
  • A: name Lydia and age 21
  • B: ["name", "Lydia"] and ["age", 21]
  • C: ["name", "age"] and undefined
  • D: Error
答案

答案: A

Object.entries()方法回傳一個給定物件自身可列舉屬性的鍵值對陣列,上述情況回傳一個二維陣列,陣列每個元素是一個包含鍵和值的陣列:

[['name','Lydia'],['age',21]]

使用for-of回圈,我們可以迭代陣列中的每個元素,上述情況是子陣列, 我們可以使用const [x,y]for-of回圈中解構子陣列, x等于子陣列中的第一個元素,y等于子陣列中的第二個元素,

第一個子陣列是[“name”,“Lydia”],其中x等于name,而y等于Lydia
第二個子陣列是[“age”,21],其中x等于age,而y等于21


94. 輸出什么?
function getItems(fruitList, ...args, favoriteFruit) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")
  • A: ["banana", "apple", "pear", "orange"]
  • B: [["banana", "apple"], "pear", "orange"]
  • C: ["banana", "apple", ["pear"], "orange"]
  • D: SyntaxError
答案

答案: D

... args是剩余引數,剩余引數的值是一個包含所有剩余引數的陣列,并且只能作為最后一個引數,上述示例中,剩余引數是第二個引數,這是不可能的,并會拋出語法錯誤,

function getItems(fruitList, favoriteFruit, ...args) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")

上述例子是有效的,將會回傳陣列:[ 'banana', 'apple', 'orange', 'pear' ]


95. 輸出什么?
function nums(a, b) {
  if
  (a > b)
  console.log('a is bigger')
  else 
  console.log('b is bigger')
  return 
  a + b
}

console.log(nums(4, 2))
console.log(nums(1, 2))
  • A: a is bigger, 6 and b is bigger, 3
  • B: a is bigger, undefined and b is bigger, undefined
  • C: undefined and undefined
  • D: SyntaxError
答案

答案: B

在 JavaScript 中,我們不必顯式地撰寫分號 (;),但是 JavaScript 引擎仍然在陳述句之后自動添加分號,這稱為自動分號插入,例如,一個陳述句可以是變數,或者像throwreturnbreak這樣的關鍵字,

在這里,我們在新的一行上寫了一個return陳述句和另一個值a + b ,然而,由于它是一個新行,引擎并不知道它實際上是我們想要回傳的值,相反,它會在return后面自動添加分號,你可以這樣看:

  return;
  a + b

這意味著永遠不會到達a + b,因為函式在return關鍵字之后停止運行,如果沒有回傳值,就像這里,函式回傳undefined,注意,在if/else陳述句之后沒有自動插入!


96. 輸出什么?
class Person {
  constructor() {
    this.name = "Lydia"
  }
}

Person = class AnotherPerson {
  constructor() {
    this.name = "Sarah"
  }
}

const member = new Person()
console.log(member.name)
  • A: "Lydia"
  • B: "Sarah"
  • C: Error: cannot redeclare Person
  • D: SyntaxError
答案

答案: B

我們可以將類設定為等于其他類/函式建構式, 在這種情況下,我們將Person設定為AnotherPerson, 這個建構式的名字是Sarah,所以新的Person實體member上的 name 屬性是Sarah


97. 輸出什么?
const info = {
  [Symbol('a')]: 'b'
}

console.log(info)
console.log(Object.keys(info))
  • A: {Symbol('a'): 'b'} and ["{Symbol('a')"]
  • B: {} and []
  • C: { a: "b" } and ["a"]
  • D: {Symbol('a'): 'b'} and []
答案

答案: D

Symbol型別是不可列舉的,Object.keys方法回傳物件上的所有可列舉的鍵屬性,Symbol型別是不可見的,并回傳一個空陣列, 記錄整個物件時,所有屬性都是可見的,甚至是不可列舉的屬性,

這是Symbol的眾多特性之一:除了表示完全唯一的值(防止物件意外名稱沖突,例如當使用 2 個想要向同一物件添加屬性的庫時),您還可以隱藏這種方式物件的屬性(盡管不完全,你仍然可以使用Object.getOwnPropertySymbols()方法訪問 Symbol


98. 輸出什么?
const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }

const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }

console.log(getList(list))
console.log(getUser(user))
  • A: [1, [2, 3, 4]] and SyntaxError
  • B: [1, [2, 3, 4]] and { name: "Lydia", age: 21 }
  • C: [1, 2, 3, 4] and { name: "Lydia", age: 21 }
  • D: Error and { name: "Lydia", age: 21 }
答案

答案: A

getList函式接收一個陣列作為其引數, 在getList函式的括號之間,我們立即解構這個陣列, 您可以將其視為:

[x, ...y] = [1, 2, 3, 4]

使用剩余的引數... y,我們將所有剩余引數放在一個陣列中, 在這種情況下,其余的引數是234y的值是一個陣列,包含所有其余引數, 在這種情況下,x的值等于1,所以當我們列印[x,y]時,會列印[1,[2,3,4]]

getUser函式接收一個物件,對于箭頭函式,如果只回傳一個值,我們不必撰寫花括號,但是,如果您想從一個箭頭函式回傳一個物件,您必須將它寫在圓括號之間,否則兩個花括號之間的所有內容都將被解釋為一個塊陳述句!在這種情況下,花括號之間的代碼不是有效的 JavaScript 代碼,因此會拋出 SyntaxError,

以下函式將回傳一個物件:

const getUser = user => ({ name: user.name, age: user.age })


99. 輸出什么?
const name = "Lydia"

console.log(name())
  • A: SyntaxError
  • B: ReferenceError
  • C: TypeError
  • D: undefined
答案

答案: C

變數name保存字串的值,該字串不是函式,因此無法呼叫,

當值不是預期型別時,會拋出TypeErrors, JavaScript 期望name是一個函式,因為我們試圖呼叫它, 但它是一個字串,因此拋出TypeErrorname is not a function

當你撰寫了一些非有效的 JavaScript 時,會拋出語法錯誤,例如當你把return這個詞寫成retrun時,
當 JavaScript 無法找到您嘗試訪問的值的參考時,拋出ReferenceErrors


100. 輸出什么?
// ??? This is my 100th question! ???

const output = `${[] && 'Im'}possible!
You should${'' && `n't`} see a therapist after so much JavaScript lol`
  • A: possible! You should see a therapist after so much JavaScript lol
  • B: Impossible! You should see a therapist after so much JavaScript lol
  • C: possible! You shouldn't see a therapist after so much JavaScript lol
  • D: Impossible! You shouldn't see a therapist after so much JavaScript lol
答案

答案: B

[]是一個真值, 使用&&運算子,如果左側值是真值,則回傳右側值, 在這種情況下,左側值[]是一個真值,所以回傳Im

""是一個假值, 如果左側值是假的,則不回傳任何內容, n't不會被退回,


101.輸出什么?
const one = (false || {} || null)
const two = (null || false || "")
const three = ([] || 0 || true)

console.log(one, two, three)
  • A: false null []
  • B: null "" true
  • C: {} "" []
  • D: null null true
答案

答案: C

使用||運算子,我們可以回傳第一個真值, 如果所有值都是假值,則回傳最后一個值,

(false || {} || null):空物件{}是一個真值, 這是第一個(也是唯一的)真值,它將被回傳,one等于{}

(null || false ||“”):所有值都是假值, 這意味著回傳傳遞的值""two等于""

([] || 0 ||“”):空陣列[]是一個真值, 這是第一個回傳的真值, three等于[]


102. 依次輸出什么?
const myPromise = () => Promise.resolve('I have resolved!')

function firstFunction() {
  myPromise().then(res => console.log(res))
  console.log('second')
}

async function secondFunction() {
  console.log(await myPromise())
  console.log('second')
}

firstFunction()
secondFunction()
  • A: I have resolved!, second and I have resolved!, second
  • B: second, I have resolved! and second, I have resolved!
  • C: I have resolved!, second and second, I have resolved!
  • D: second, I have resolved! and I have resolved!, second
答案

答案: D

有了 promise,我們通常會說:當我想要呼叫某個方法,但是由于它可能需要一段時間,因此暫時將它放在一邊,只有當某個值被 resolved/rejected,并且執行堆疊為空時才使用這個值,

我們可以在async函式中通過.thenawait關鍵字獲得該值, 盡管我們可以通過.thenawait獲得 promise 的價值,但是它們的作業方式有所不同,

firstFunction中,當運行到myPromise方法時我們將其放在一邊,即 promise 進入微任務佇列,其他后面的代碼(console.log('second'))照常運行,因此second被列印出,firstFunction方法到此執行完畢,執行堆疊中宏任務佇列被清空,此時開始執行微任務佇列中的任務,I have resolved被列印出,

secondFunction方法中,我們通過await關鍵字,暫停了后面代碼的執行,直到異步函式的值被決議才開始后面代碼的執行,這意味著,它會等著直到 myPromise 以值I have resolved被解決之后,下一行second才開始執行,


103. 輸出什么?
const set = new Set()

set.add(1)
set.add("Lydia")
set.add({ name: "Lydia" })

for (let item of set) {
  console.log(item + 2)
}
  • A: 3, NaN, NaN
  • B: 3, 7, NaN
  • C: 3, Lydia2, [Object object]2
  • D: "12", Lydia2, [Object object]2
答案

答案: C

“+” 運算子不僅用于添加數值,還可以使用它來連接字串, 每當 JavaScript 引擎發現一個或多個值不是數字時,就會將數字強制為字串,

第一個是數字 1, 1 + 2 回傳數字 3,

但是,第二個是字串 “Lydia”, “Lydia” 是一個字串,2 是一個數字:2 被強制轉換為字串, “Lydia” 和 “2” 被連接起來,產生字串 “Lydia2”,

{name:“ Lydia”}是一個物件, 數字和物件都不是字串,因此將二者都字串化, 每當我們對常規物件進行字串化時,它就會變成[Object object], 與 “2” 串聯的 “ [Object object]” 成為 “[Object object]2”,


104. 結果是什么?
Promise.resolve(5)
  • A: 5
  • B: Promise {<pending>: 5}
  • C: Promise {<fulfilled>: 5}
  • D: Error
答案

答案: C

我們可以將我們想要的任何型別的值傳遞Promise.resolve,無論是否promise, 該方法本身回傳帶有已決議值的Promise (<fulfilled>), 如果您傳遞常規函式,它將是具有常規值的已解決promise, 如果你通過了 promise,它將是一個已經 resolved 的且帶有傳的值的 promise,

上述情況,我們傳了數字 5,因此回傳一個 resolved 狀態的 promise,resolve 值為5

105. 輸出什么?
function compareMembers(person1, person2 = person) {
  if (person1 !== person2) {
    console.log("Not the same!")
  } else {
    console.log("They are the same!")
  }
}

const person = { name: "Lydia" }

compareMembers(person)
  • A: Not the same!
  • B: They are the same!
  • C: ReferenceError
  • D: SyntaxError
答案

答案: B

物件通過參考傳遞, 當我們檢查物件的嚴格相等性(===)時,我們正在比較它們的參考,

我們將 “person2” 的默認值設定為 “person” 物件,并將 “person” 物件作為 “person1” 的值傳遞,

這意味著兩個值都參考記憶體中的同一位置,因此它們是相等的,

運行 “ else” 陳述句中的代碼塊,并記錄They are the same!


106. 輸出什么?
const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
}

const colors = ["pink", "red", "blue"]

console.log(colorConfig.colors[1])
  • A: true
  • B: false
  • C: undefined
  • D: TypeError
答案

答案: D

在 JavaScript 中,我們有兩種訪問物件屬性的方法:括號表示法或點表示法, 在此示例中,我們使用點表示法(colorConfig.colors)代替括號表示法(colorConfig [“ colors”]),

使用點表示法,JavaScript 會嘗試使用該確切名稱在物件上查找屬性, 在此示例中,JavaScript 嘗試在 colorconfig 物件上找到名為 colors 的屬性, 沒有名為 “colors” 的屬性,因此回傳 “undefined”,
然后,我們嘗試使用[1]訪問第一個元素的值, 我們無法對未定義的值執行此操作,因此會拋出Cannot read property '1' of undefined

JavaScript 解釋(或取消裝箱)陳述句, 當我們使用方括號表示法時,它會看到第一個左方括號[并一直進行下去,直到找到右方括號], 只有這樣,它才會評估該陳述句, 如果我們使用了 colorConfig [colors [1]],它將回傳 colorConfig 物件上 red 屬性的值,


107. 輸出什么?
console.log('??' === '??')
  • A: true
  • B: false
答案

答案: A

在內部,表情符號是 unicode, heat 表情符號的 unicode 是“ U + 2764 U + FE0F”, 對于相同的表情符號,它們總是相同的,因此我們將兩個相等的字串相互比較,這將回傳 true,


108. 哪些方法修改了原陣列?
const emojis = ['?', '??', '??']

emojis.map(x => x + '?')
emojis.filter(x => x !== '??')
emojis.find(x => x !== '??')
emojis.reduce((acc, cur) => acc + '?')
emojis.slice(1, 2, '?') 
emojis.splice(1, 2, '?')
  • A: All of them
  • B: map reduce slice splice
  • C: map slice splice
  • D: splice
答案

答案: D

使用splice方法,我們通過洗掉,替換或添加元素來修改原始陣列, 在這種情況下,我們從索引 1 中洗掉了 2 個元素(我們洗掉了'??''??'),同時添加了?emoji 表情,

mapfilterslice回傳一個新陣列,find回傳一個元素,而reduce回傳一個減小的值,


109. 輸出什么?
const food = ['??', '??', '??', '??']
const info = { favoriteFood: food[0] }

info.favoriteFood = '??'

console.log(food)
  • A: ['??', '??', '??', '??']
  • B: ['??', '??', '??', '??']
  • C: ['??', '??', '??', '??', '??']
  • D: ReferenceError
答案

答案: A

我們將info物件上的favoriteFood屬性的值設定為披薩表情符號 “??” 的字串,字串是原始資料型別,在 JavaScript 中,原始資料型別通過值起作用

在這種情況下,我們將info物件上的favoriteFood屬性的值設定為等于food陣列中的第一個元素的值,字串為披薩表情符號('??' ),字串是原始資料型別,并且通過值進行互動,我們更改info物件上favoriteFood屬性的值, food 陣列沒有改變,因為 favoriteFood 的值只是該陣列中第一個元素的值的復制,并且與該元素上的元素沒有相同的記憶體參考食物[0],當我們記錄食物時,它仍然是原始陣列['??','??','??','??']


110. 這個函式干了什么?
JSON.parse()
  • A: Parses JSON to a JavaScript value
  • B: Parses a JavaScript object to JSON
  • C: Parses any JavaScript value to JSON
  • D: Parses JSON to a JavaScript object only
答案

答案: A

使用JSON.parse()方法,我們可以將 JSON 字串決議為 JavaScript 值,

// 將數字字串化為有效的 JSON,然后將 JSON 字串決議為 JavaScript 值:
const jsonNumber = JSON.stringify(4) // '4'
JSON.parse(jsonNumber) // 4

// 將陣列值字串化為有效的 JSON,然后將 JSON 字串決議為 JavaScript 值:
const jsonArray = JSON.stringify([1, 2, 3]) // '[1, 2, 3]'
JSON.parse(jsonArray) // [1, 2, 3]

// 將物件字串化為有效的 JSON,然后將 JSON 字串決議為 JavaScript 值:
const jsonArray = JSON.stringify({ name: "Lydia" }) // '{"name":"Lydia"}'
JSON.parse(jsonArray) // { name: 'Lydia' }


111. 輸出什么?
let name = 'Lydia'

function getName() {
  console.log(name)
  let name = 'Sarah'
}

getName()
  • A: Lydia
  • B: Sarah
  • C: undefined
  • D: ReferenceError
答案

答案: D

每個函式都有其自己的執行背景關系, getName函式首先在其自身的背景關系(范圍)內查找,以查看其是否包含我們嘗試訪問的變數name, 上述情況,getName函式包含其自己的name變數:我們用let關鍵字和Sarah的值宣告變數name

帶有let關鍵字(和const)的變數被提升,但是與var不同,它不會被*** 初始化***, 在我們宣告(初始化)它們之前,無法訪問它們, 這稱為 “暫時性死區”, 當我們嘗試在宣告變數之前訪問變數時,JavaScript 會拋出ReferenceError: Cannot access 'name' before initialization

如果我們不在getName函式中宣告name變數,則 javascript 引擎會查看原型鏈,會找到其外部作用域有一個名為name的變數,其值為Lydia, 在這種情況下,它將列印Lydia

let name = 'Lydia'

function getName() {
  console.log(name)
}

getName() // Lydia


112. 輸出什么?
function* generatorOne() {
  yield ['a', 'b', 'c'];
}

function* generatorTwo() {
  yield* ['a', 'b', 'c'];
}

const one = generatorOne()
const two = generatorTwo()

console.log(one.next().value)
console.log(two.next().value)
  • A: a and a
  • B: a and undefined
  • C: ['a', 'b', 'c'] and a
  • D: a and ['a', 'b', 'c']
答案

答案: C

通過 yield 關鍵字,我們在 Generator 函式里執行yield運算式,通過 yield* 關鍵字,我們可以在一個Generator 函式里面執行(yield運算式)另一個 Generator 函式,或可遍歷的物件 (如陣列).

在函式 generatorOne 中,我們通過 yield 關鍵字 yield 了一個完整的陣列 ['a', 'b', 'c'],函式one通過next方法回傳的物件的value 屬性的值 (one.next().value) 等價于陣列 ['a', 'b', 'c'].

console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined

在函式 generatorTwo 中,我們使用 yield* 關鍵字,就相當于函式two第一個yield的值,等價于在迭代器中第一個 yield 的值,陣列['a', 'b', 'c']就是這個迭代器,第一個 yield 的值就是 a,所以我們第一次呼叫 two.next().value時,就回傳a

console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined


113. 輸出什么?
console.log(`${(x => x)('I love')} to program`)
  • A: I love to program
  • B: undefined to program
  • C: ${(x => x)('I love') to program
  • D: TypeError
答案

答案: A

帶有模板字面量的運算式首先被執行,相當于字串會包含運算式,這個立即執行函式 (x => x)('I love') 回傳的值,我們向箭頭函式 x => x 傳遞 'I love' 作為引數,x 等價于回傳的 'I love',這就是結果 I love to program


114. 將會發生什么?
let config = {
  alert: setInterval(() => {
    console.log('Alert!')
  }, 1000)
}

config = null
  • A: setInterval 的回呼不會被呼叫
  • B: setInterval 的回呼被呼叫一次
  • C: setInterval 的回呼仍然會被每秒鐘呼叫
  • D: 我們從沒呼叫過 config.alert(), config 為 null
答案

答案: C

一般情況下當我們將物件賦值為 null,那些物件會被進行 垃圾回收(garbage collected) 因為已經沒有對這些物件的參考了,然而,setInterval的引數是一個箭頭函式(所以背景關系系結到物件 config 了),回呼函式仍然保留著對 config的參考,只要存在參考,物件就不會被垃圾回收,因為沒有被垃圾回收,setInterval 的回呼每 1000ms (1s) 會被呼叫一次,


115. 哪一個方法會回傳 'Hello world!'
const myMap = new Map()
const myFunc = () => 'greeting'

myMap.set(myFunc, 'Hello world!')

//1
myMap.get('greeting')
//2
myMap.get(myFunc)
//3
myMap.get(() => 'greeting')
  • A: 1
  • B: 2
  • C: 2 and 3
  • D: All of them
答案

答案: B

當通過 set 方法添加一個鍵值對,一個傳遞給 set方法的引數將會是鍵名,第二個引數將會是值,在這個 case 里,鍵名為 函式 () => 'greeting',值為'Hello world'myMap 現在就是 { () => 'greeting' => 'Hello world!' }

1 是錯的,因為鍵名不是 'greeting' 而是 () => 'greeting'
3 是錯的,因為我們給get 方法傳遞了一個新的函式,物件受 參考 影響,函式也是物件,因此兩個函式嚴格上并不等價,盡管他們相同:他們有兩個不同的記憶體參考地址,


116. 輸出什么?
const person = {
  name: "Lydia",
  age: 21
}

const changeAge = (x = { ...person }) => x.age += 1
const changeAgeAndName = (x = { ...person }) => {
  x.age += 1
  x.name = "Sarah"
}

changeAge(person)
changeAgeAndName()

console.log(person)
  • A: {name: "Sarah", age: 22}
  • B: {name: "Sarah", age: 23}
  • C: {name: "Lydia", age: 22}
  • D: {name: "Lydia", age: 23}
答案

答案: C

函式 changeAge 和函式 changeAgeAndName 有著不同的引數,定義一個 生成的物件 { ...person },這個物件有著所有 person 物件 中 k/v 值的副本,

首項,我們呼叫 changeAge 函式并傳遞 person 物件作為它的引數,這個函式對 age 屬性進行加一操作,person 現在是 { name: "Lydia", age: 22 }

然后,我們呼叫函式 changeAgeAndName ,然而我們沒有傳遞引數,取而代之,x 的值等價 new 生成的物件:{ ...person },因為它是一個新生成的物件,它并不會對物件 person 造成任何副作用,person 仍然等價于 { name: "Lydia", age: 22 }


117. 下面那個選項將會回傳 6?
function sumValues(x, y, z) {
	return x + y + z;
}
  • A: sumValues([...1, 2, 3])
  • B: sumValues([...[1, 2, 3]])
  • C: sumValues(...[1, 2, 3])
  • D: sumValues([1, 2, 3])
答案

答案: C

通過展開運算子 ...,我們可以 暫開 單個可迭代的元素,函式 sumValues function 接收三個引數: x, yz...[1, 2, 3] 的執行結果為 1, 2, 3,將會傳遞給函式 sumValues


118. 輸出什么?
let num = 1;
const list = ["??", "??", "??", "??"];

console.log(list[(num += 1)]);
  • A: ??
  • B: ??
  • C: SyntaxError
  • D: ReferenceError
答案

答案: B

通過 += 運算子,我們對值 num 進行加 1 操作, num 有初始值 1,因此 1 + 1 的執行結果為 2,陣列 list 的第二項為 ??,console.log(list[2]) 輸出 ??.


119. 輸出什么?
const person = {
	firstName: "Lydia",
	lastName: "Hallie",
	pet: {
		name: "Mara",
		breed: "Dutch Tulip Hound"
	},
	getFullName() {
		return `${this.firstName} ${this.lastName}`;
	}
};

console.log(person.pet?.name);
console.log(person.pet?.family?.name);
console.log(person.getFullName?.());
console.log(member.getLastName?.());
  • A: undefined undefined undefined undefined
  • B: Mara undefined Lydia Hallie ReferenceError
  • C: Mara null Lydia Hallie null
  • D: null ReferenceError null ReferenceError
答案

答案: B

通過 ES10 或 TS3.7+可選鏈運算子 ?.,我們不再需要顯式檢測更深層的嵌套值是否有效,如果我們嘗試獲取 undefinednull 的值 (nullish),表達將會短路并回傳 undefined.

person.pet?.nameperson 有一個名為 pet 的屬性: person.pet 不是 nullish,它有個名為 name 的屬性,并回傳字串 Mara
person.pet?.family?.nameperson 有一個名為 pet 的屬性: person.pet 不是 nullish. pet 并沒有 一個名為 family 的屬性,person.pet.family 是 nullish,運算式回傳 undefined
person.getFullName?.()person 有一個名為 getFullName 的屬性: person.getFullName() 不是 nullish 并可以被呼叫,回傳字串 Lydia Hallie
member.getLastName?.(): 變數member 不存在,因此會拋出錯誤ReferenceError


120. 輸出什么?
const groceries = ["banana", "apple", "peanuts"];

if (groceries.indexOf("banana")) {
	console.log("We have to buy bananas!");
} else {
	console.log(`We don't have to buy bananas!`);
}
  • A: We have to buy bananas!
  • B: We don't have to buy bananas
  • C: undefined
  • D: 1
答案

答案: B

我們傳遞了一個狀態 groceries.indexOf("banana") 給 if 條件陳述句,groceries.indexOf("banana") 回傳 0, 一個 falsy 的值,因為 if 條件陳述句的狀態為 falsy,else 塊區內的代碼執行,并且 We don't have to buy bananas! 被輸出,


121. 輸出什么?
const config = {
	languages: [],
	set language(lang) {
		return this.languages.push(lang);
	}
};

console.log(config.language);
  • A: function language(lang) { this.languages.push(lang }
  • B: 0
  • C: []
  • D: undefined
答案

答案: D

方法 language 是一個 setter,Setters 并不保存一個實際值,它們的使命在于 修改 屬性,當呼叫方法 setter, 回傳 undefined


122. 輸出什么?
const name = "Lydia Hallie";

console.log(!typeof name === "object");
console.log(!typeof name === "string");
  • A: false true
  • B: true false
  • C: false false
  • D: true true
答案

答案: C

typeof name 回傳 "string",字串 "string" 是一個 truthy 的值,因此 !typeof name 回傳一個布林值 falsefalse === "object"false === "string" 都回傳 false

(如果我們想檢測一個值的型別,我們應該用 !== 而不是 !typeof


123. 輸出什么?
const add = x => y => z => {
	console.log(x, y, z);
	return x + y + z;
};

add(4)(5)(6);
  • A: 4 5 6
  • B: 6 5 4
  • C: 4 function function
  • D: undefined undefined 6
答案

答案: A

函式 add 是一個回傳 回傳箭頭函式的箭頭函式 的箭頭函式(still with me?),第一個函式接收一個值為 4 的引數 x,我們呼叫第二個函式,它接收一個值為 5 的引數 y,然后我們呼叫第三個函式,它接收一個值為 6 的引數 z,當我們嘗試在最后一個箭頭函式中獲取 x, yz 的值,JS 引擎根據作用域鏈去找 xy 的值,得到 4 5 6.


124. 輸出什么?
async function* range(start, end) {
	for (let i = start; i <= end; i++) {
		yield Promise.resolve(i);
	}
}

(async () => {
	const gen = range(1, 3);
	for await (const item of gen) {
		console.log(item);
	}
})();
  • A: Promise {1} Promise {2} Promise {3}
  • B: Promise {<pending>} Promise {<pending>} Promise {<pending>}
  • C: 1 2 3
  • D: undefined undefined undefined
答案

答案: C

我們給 函式 range 傳遞: Promise{1}, Promise{2}, Promise{3},Generator 函式 range 回傳一個全是 async object promise 陣列,我們將 async object 賦值給變數 gen,之后我們使用for await ... of 進行回圈遍歷,我們將回傳的 Promise 實體賦值給 item: 第一個回傳 Promise{1}, 第二個回傳 Promise{2},之后是 Promise{3},因為我們正 awaiting item 的值,resolved 狀態的 promsie,promise 陣列的 resolved 以此為: 123.


125. 輸出什么?
const myFunc = ({ x, y, z }) => {
	console.log(x, y, z);
};

myFunc(1, 2, 3);
  • A: 1 2 3
  • B: {1: 1} {2: 2} {3: 3}
  • C: { 1: undefined } undefined undefined
  • D: undefined undefined undefined
答案

答案: D

myFunc 期望接收一個包含 x, yz 屬性的物件作為它的引數,因為我們僅僅傳遞三個單獨的數字值 (1, 2, 3) 而不是一個含有 x, yz 屬性的物件 ({x: 1, y: 2, z: 3}), x, yz 有著各自的默認值 undefined.


126. 輸出什么?
function getFine(speed, amount) {
  const formattedSpeed = new Intl.NumberFormat(
    'en-US',
    { style: 'unit', unit: 'mile-per-hour' }
  ).format(speed)

  const formattedAmount = new Intl.NumberFormat(
    'en-US',
    { style: 'currency', currency: 'USD' }
  ).format(amount)

  return `The driver drove ${formattedSpeed} and has to pay ${formattedAmount}`
}

console.log(getFine(130, 300))
  • A: The driver drove 130 and has to pay 300
  • B: The driver drove 130 mph and has to pay $300.00
  • C: The driver drove undefined and has to pay undefined
  • D: The driver drove 130.00 and has to pay 300.00
答案

答案: B

通過方法 Intl.NumberFormat,我們可以格式化任意區域的數字值,我們對數字值 130 進行 mile-per-hour 作為 uniten-US 區域 格式化,結果為 130 mph,對數字值 300 進行 USD 作為 currentcyen-US 區域格式化,結果為 $300.00.


127. 輸出什么?
const spookyItems = ["??", "??", "??"];
({ item: spookyItems[3] } = { item: "??" });

console.log(spookyItems);
  • A: ["??", "??", "??"]
  • B: ["??", "??", "??", "??"]
  • C: ["??", "??", "??", { item: "??" }]
  • D: ["??", "??", "??", "[object Object]"]
答案

答案: B

通過解構物件們,我們可以從右手邊的物件中拆出值,并且將拆出的值分配給左手邊物件同名的屬性,在這種情況下,我們將值 "??" 分配給 spookyItems[3],相當于我們正在篡改陣列 spookyItems,我們給它添加了值 "??",當輸出 spookyItems 時,結果為 ["??", "??", "??", "??"]


128. 輸出什么?
const name = "Lydia Hallie";
const age = 21;

console.log(Number.isNaN(name));
console.log(Number.isNaN(age));

console.log(isNaN(name));
console.log(isNaN(age));
  • A: true false true false
  • B: true false false false
  • C: false false true false
  • D: false true false true
答案

答案: C

通過方法 Number.isNaN,你可以檢測你傳遞的值是否為 數字值 并且是否等價于 NaNname 不是一個數字值,因此 Number.isNaN(name) 回傳 falseage 是一個數字值,但它不等價于 NaN,因此 Number.isNaN(age) 回傳 false.

通過方法 isNaN, 你可以檢測你傳遞的值是否一個 number,name 不是一個 number,因此 isNaN(name) 回傳 true. age 是一個 number 因此 isNaN(age) 回傳 false.


129. 輸出什么?
const randomValue = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/21;

function getInfo() {
	console.log(typeof randomValue);
	const randomValue ="Lydia Hallie";
}

getInfo();
  • A: "number"
  • B: "string"
  • C: undefined
  • D: ReferenceError
答案

答案: D

通過 const 關鍵字宣告的變數在被初始化之前不可被參考:這被稱之為 暫時性死區,在函式 getInfo 中,變數 randomValue 宣告在getInfo 的作用域的此法環境中,在想要對 typeof randomValue 進行 log 之前,變數 randomValue 仍未被初始化: 錯誤ReferenceError 被拋出!JS 引擎并不會根據作用域鏈網上尋找該變數,因為我們已經在 getInfo 函式中宣告了 randomValue 變數,


130. 輸出什么?
const myPromise = Promise.resolve("Woah some cool data");

(async () => {
	try {
		console.log(await myPromise);
	} catch {
		throw new Error(`Oops didn't work`);
	} finally {
		console.log("Oh finally!");
	}
})();
  • A: Woah some cool data
  • B: Oh finally!
  • C: Woah some cool data Oh finally!
  • D: Oops didn't work Oh finally!
答案

答案: C

try 塊區,我們列印 myPromise 變數的 awaited 值: "Woah some cool data",因為try 塊區沒有錯誤拋出,catch 塊區的代碼并不執行,finally 塊區的代碼 總是 執行,"Oh finally!" 被輸出,


131. 輸出什么?
const emojis = ["??", ["?", "?", ["??", "??"]]];

console.log(emojis.flat(1));
  • A: ['??', ['?', '?', ['??', '??']]]
  • B: ['??', '?', '?', ['??', '??']]
  • C: ['??', ['?', '?', '??', '??']]
  • D: ['??', '?', '?', '??', '??']
答案

答案: B

通過方法 flat, 我們可以創建一個新的,已被扁平化的陣列,被扁平化的深度取決于我們傳遞的值,在這個 case 里,我們傳遞了值 1 (并不必要,這是默認值),相當于只有第一層的陣列才會被連接,即這個 case 里的 ['??'] and ['?', '?', ['??', '??']],連接這兩個陣列得到結果 ['??', '?', '?', ['??', '??']].


132. 輸出什么?
class Counter {
	constructor() {
		this.count = 0;
	}

	increment() {
		this.count++;
	}
}

const counterOne = new Counter();
counterOne.increment();
counterOne.increment();

const counterTwo = counterOne;
counterTwo.increment();

console.log(counterOne.count);
  • A: 0
  • B: 1
  • C: 2
  • D: 3
答案

答案: D

counterOne 是類 Counter 的一個實體,類 Counter 包含一個count 屬性在它的建構式里, 和一個 increment 方法,首先,我們通過 counterOne.increment() 呼叫方法 increment 兩次,現在,counterOne.count2.

然后,我們創建一個新的變數 counterTwo 并將 counterOne 的參考地址賦值給它,因為物件受參考地址的影響,我們剛剛創建了一個新的物件,其參考地址和 counterOne 的等價,因此它們指向同一塊記憶體地址,任何對其的副作用都會影響 counterTwo,現在 counterTwo.count2

我們呼叫 counterTwo.increment()count 的值設為 3,然后,我們列印 counterOne 里的 count,結果為 3


133. 輸出什么?
const myPromise = Promise.resolve(Promise.resolve("Promise!"));

function funcOne() {
	myPromise.then(res => res).then(res => console.log(res));
	setTimeout(() => console.log("Timeout!"), 0);
	console.log("Last line!");
}

async function funcTwo() {
	const res = await myPromise;
	console.log(await res);
	setTimeout(() => console.log("Timeout!"), 0);
	console.log("Last line!");
}

funcOne();
funcTwo();
  • A: Promise! Last line! Promise! Last line! Last line! Promise!
  • B: Last line! Timeout! Promise! Last line! Timeout! Promise!
  • C: Promise! Last line! Last line! Promise! Timeout! Timeout!
  • D: Last line! Promise! Promise! Last line! Timeout! Timeout!
答案

答案: D

首先,我們呼叫 funcOne,在函式 funcOne 的第一行,我們呼叫myPromise promise 異步操作,當 JS 引擎在忙于執行 promise,它繼續執行函式 funcOne,下一行 異步操作 setTimeout,其回呼函式被 Web API 呼叫, (詳情請參考我關于 event loop 的文章.)

promise 和 timeout 都是異步操作,函式繼續執行當 JS 引擎忙于執行 promise 和 處理 setTimeout 的回呼,相當于 Last line! 首先被輸出, 因為它不是異步操作,執行完 funcOne 的最后一行,promise 狀態轉變為 resolved,Promise! 被列印,然而,因為我們呼叫了 funcTwo(),呼叫堆疊不為空,setTimeout 的回呼仍不能入堆疊,

我們現在處于 funcTwo,先 awaiting myPromise,通過 await 關鍵字, 我們暫停了函式的執行直到 promise 狀態變為 resolved (或 rejected),然后,我們輸出 res 的 awaited 值(因為 promise 本身回傳一個 promise), 接著輸出 Promise!

下一行就是 異步操作 setTimeout,其回呼函式被 Web API 呼叫,

我們執行到函式 funcTwo 的最后一行,輸出 Last line!,現在,因為 funcTwo 出堆疊,呼叫堆疊為空,在事件佇列中等待的回呼函式(() => console.log("Timeout!") from funcOne, and () => console.log("Timeout!") from funcTwo)以此入堆疊,第一個回呼輸出 Timeout!,并出堆疊,然后,第二個回呼輸出 Timeout!,并出堆疊,得到結果 Last line! Promise! Promise! Last line! Timeout! Timeout!


134. 我們怎樣才能在 index.js 中呼叫 sum.js? 中的 sum
// sum.js
export default function sum(x) {
	return x + x;
}

// index.js
import * as sum from "./sum";
  • A: sum(4)
  • B: sum.sum(4)
  • C: sum.default(4)
  • D: 默認匯出不用 * 來匯入,只能具名匯出
答案

答案: C

使用符號 *,我們引入檔案中的所有值,包括默認和具名,如果我們有以下檔案:

// info.js
export const name = "Lydia";
export const age = 21;
export default "I love JavaScript";

// index.js
import * as info from "./info";
console.log(info);

將會輸出以下內容:

{
  default: "I love JavaScript",
  name: "Lydia",
  age: 21
}

sum 為例,相當于以下形式引入值 sum

{ default: function sum(x) { return x + x } }

我們可以通過呼叫 sum.default 來呼叫該函式


135. 輸出什么?
const handler = {
	set: () => console.log("Added a new property!"),
	get: () => console.log("Accessed a property!")
};

const person = new Proxy({}, handler);

person.name = "Lydia";
person.name;
  • A: Added a new property!
  • B: Accessed a property!
  • C: Added a new property! Accessed a property!
  • D: 沒有任何輸出
答案

答案: C

使用 Proxy 物件,我們可以給一個物件添加自定義行為,在這個 case,我們傳遞一個包含以下屬性的物件 handler : set and get,每當我們 設定 屬性值時 set 被呼叫,每當我們 獲取get 被呼叫,

第一個引數是一個空物件 {},作為 person 的值,對于這個物件,自定義行為被定義在物件 handler,如果我們向物件 person 添加屬性,set 將被呼叫,如果我們獲取 person 的屬性,get 將被呼叫,

首先,我們向 proxy 物件 (person.name = "Lydia") 添加一個屬性 nameset 被呼叫并輸出 "Added a new property!"

然后,我們獲取 proxy 物件的一個屬性,物件 handler 的屬性 get 被呼叫,輸出 "Accessed a property!"


136. 以下哪一項會對物件 person 有副作用?
const person = { name: "Lydia Hallie" };

Object.seal(person);
  • A: person.name = "Evan Bacon"
  • B: person.age = 21
  • C: delete person.name
  • D: Object.assign(person, { age: 21 })
答案

答案: A

使用 Object.seal 我們可以防止新屬性 被添加,或者存在屬性 被移除.

然而,你仍然可以對存在屬性進行更改,


137. 以下哪一項會對物件 person 有副作用?
const person = {
	name: "Lydia Hallie",
	address: {
		street: "100 Main St"
	}
};

Object.freeze(person);
  • A: person.name = "Evan Bacon"
  • B: delete person.address
  • C: person.address.street = "101 Main St"
  • D: person.pet = { name: "Mara" }
答案

答案: C

使用方法 Object.freeze 對一個物件進行 凍結,不能對屬性進行添加,修改,洗掉,

然而,它僅 對物件進行 凍結,意味著只有 物件中的 直接 屬性被凍結,如果屬性是另一個 object,像案例中的 addressaddress 中的屬性沒有被凍結,仍然可以被修改,


138. 輸出什么?
const add = x => x + x;

function myFunc(num = 2, value = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/add(num)) {
	console.log(num, value);
}

myFunc();
myFunc(3);
  • A: 2 4 and 3 6
  • B: 2 NaN and 3 NaN
  • C: 2 Error and 3 6
  • D: 2 4 and 3 Error
答案

答案: A

首先我們不傳遞任何引數呼叫 myFunc(),因為我們沒有傳遞引數,numvalue 獲取它們各自的默認值:num 為 2,而 value 為函式 add 的回傳值,對于函式 add,我們傳遞值為 2 的 num 作為引數,函式 add 回傳 4 作為 value 的值,

然后,我們呼叫 myFunc(3) 并傳遞值 3 引數 num 的值,我們沒有給 value 傳遞值,因為我們沒有給引數 value 傳遞值,它獲取默認值:函數 add 的回傳值,對于函式 add,我們傳遞值為 3 的 num給它,函式 add 回傳 6 作為 value 的值,


139. 輸出什么?
class Counter {
  #number = 10

  increment() {
    this.#number++
  }

  getNum() {
    return this.#number
  }
}

const counter = new Counter()
counter.increment()

console.log(counter.#number)
  • A: 10
  • B: 11
  • C: undefined
  • D: SyntaxError
答案

答案: D

在 ES2020 中,通過 # 我們可以給 class 添加私有變數,在 class 的外部我們無法獲取該值,當我們嘗試輸出 counter.#number,語法錯誤被拋出:我們無法在 class Counter 外部獲取它!


140. 選擇哪一個?
const teams = [
	{ name: "Team 1", members: ["Paul", "Lisa"] },
	{ name: "Team 2", members: ["Laura", "Tim"] }
];

function* getMembers(members) {
	for (let i = 0; i < members.length; i++) {
		yield members[i];
	}
}

function* getTeams(teams) {
	for (let i = 0; i < teams.length; i++) {
		// ? SOMETHING IS MISSING HERE ?
	}
}

const obj = getTeams(teams);
obj.next(); // { value: "Paul", done: false }
obj.next(); // { value: "Lisa", done: false }
  • A: yield getMembers(teams[i].members)
  • B: yield* getMembers(teams[i].members)
  • C: return getMembers(teams[i].members)
  • D: return yield getMembers(teams[i].members)
答案

答案: B

為了遍歷 teams 陣列中物件的屬性 members 中的每一項,我們需要將 teams[i].members 傳遞給 Generator 函式 getMembers,Generator 函式回傳一個 generator 物件,為了遍歷這個 generator 物件中的每一項,我們需要使用 yield*.

如果我們沒有寫 yieldreturn yield 或者 return,整個 Generator 函式不會第一時間 return 當我們呼叫 next 方法,


141. 輸出什么?
const person = {
	name: "Lydia Hallie",
	hobbies: ["coding"]
};

function addHobby(hobby, hobbies = person.hobbies) {
	hobbies.push(hobby);
	return hobbies;
}

addHobby("running", []);
addHobby("dancing");
addHobby("baking", person.hobbies);

console.log(person.hobbies);
  • A: ["coding"]
  • B: ["coding", "dancing"]
  • C: ["coding", "dancing", "baking"]
  • D: ["coding", "running", "dancing", "baking"]
答案

答案: C

函式 addHobby 接受兩個引數,hobby 和有著物件 person 中陣列 hobbies 默認值的 hobbies

首相,我們呼叫函式 addHobby,并給 hobby 傳遞 "running" 以及給 hobbies 傳遞一個空陣列,因為我們給 hobbies 傳遞了空陣列,"running" 被添加到這個空陣列,

然后,我們呼叫函式 addHobby,并給 hobby 傳遞 "dancing",我們不向 hobbies 傳遞值,因此它獲取其默認值 —— 物件 person 的 屬性 hobbies,我們向陣列 person.hobbies push dancing

最后,我們呼叫函式 addHobby,并向 hobby 傳遞 值 "bdaking",并且向 hobbies 傳遞 person.hobbies,我們向陣列 person.hobbies push dancing

pushing dancingbaking 之后,person.hobbies 的值為 ["coding", "dancing", "baking"]


142. 輸出什么?
class Bird {
	constructor() {
		console.log("I'm a bird. ??");
	}
}

class Flamingo extends Bird {
	constructor() {
		console.log("I'm pink. ??");
		super();
	}
}

const pet = new Flamingo();
  • A: I'm pink. ??
  • B: I'm pink. ?? I'm a bird. ??
  • C: I'm a bird. ?? I'm pink. ??
  • D: Nothing, we didn't call any method
答案

答案: B

我們創建了類 Flamingo 的實體 pet,當我們實體化這個實體,Flamingo 中的 constructor 被呼叫,首相,輸出 "I'm pink. ??",之后我們呼叫super()super() 呼叫父類的建構式,BirdBird 的建構式被呼叫,并輸出 "I'm a bird. ??"


143. 哪一個選項會導致報錯?
const emojis = ["??", "????", "??", "?"];

/* 1 */ emojis.push("??");
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, "??"];
/* 4 */ emojis.length = 0;
  • A: 1
  • B: 1 and 2
  • C: 3 and 4
  • D: 3
答案

答案: D

const 關鍵字意味著我們不能 重定義 變數中的值,它 僅可讀,而然,值本身不可修改,陣列 emojis 中的值可被修改,如 push 新的值,拼接,又或者將陣列的長度設定為 0,


144. 我們需要向物件 person 添加什么,以致執行 [...person] 時獲得形如 ["Lydia Hallie", 21] 的輸出?
const person = {
  name: "Lydia Hallie",
  age: 21
}

[...person] // ["Lydia Hallie", 21]
  • A: 不需要,物件默認就是可迭代的
  • B: *[Symbol.iterator]() { for (let x in this) yield* this[x] }
  • C: *[Symbol.iterator]() { yield* Object.values(this) }
  • D: *[Symbol.iterator]() { for (let x in this) yield this }
答案

答案: C

物件默認并不是可迭代的,如果迭代規則被定義,則一個物件是可迭代的(An iterable is an iterable if the iterator protocol is present),我們可以通過添加迭代器 symbol [Symbol.iterator] 來定義迭代規則,其回傳一個 generator 物件,比如說構建一個 generator 函式 *[Symbol.iterator]() {},如果我們想要回傳陣列 ["Lydia Hallie", 21]: yield* Object.values(this),這個 generator 函式一定要 yield 物件 personObject.values


145. 輸出什么?
let count = 0;
const nums = [0, 1, 2, 3];

nums.forEach(num => {
	if (num) count += 1
})

console.log(count)
  • A: 1
  • B: 2
  • C: 3
  • D: 4
答案

答案: C

forEach 回圈內部的 if 會判斷 num 的值是 truthy 或者是 falsy,因為 nums 陣列的第一個數字是 0,一個 falsy 值, if 陳述句代碼塊不會被執行,count 僅僅在 nums 陣列的其他 3 個數字 123 時加 1,因為 count 執行了 3 次加 1 運算,所以 count 的值為 3


146. 輸出是什么?
function getFruit(fruits) {
	console.log(fruits?.[1]?.[1])
}

getFruit([['??', '??'], ['??']])
getFruit()
getFruit([['??'], ['??', '??']])
  • A: null, undefined, ??
  • B: [], null, ??
  • C: [], [], ??
  • D: undefined, undefined, ??
答案

答案: D

? 允許我們去選擇性地訪問物件內部更深層的嵌套屬性, 我們嘗試列印 fruits 陣列索引值為 1 的子陣列內部的索引值為 1 的元素, 如果在 fruits 陣列索引值 為 1 的位置不存在元素,會直接回傳 undefined, 如果 fruits 陣列在索引值為 1 的位置存在元素,但是子陣列在索引值為 1 的位置不存在元素,也會回傳 undefined

首先,我們嘗試列印 [['??', '??'], ['??']] 的子陣列 ['??'] 的第 2 個元素,這個子陣列只包含一個元素,也就意味著在索引值為 1 的位置不存在元素,所以回傳的是 undefined

其次,我們在沒有傳入任何引數呼叫了 getFruits 函式,也就意味著形參 fruits 的默認值為undefined,因為我們選擇性地鏈接了 fruits 在索引值為 1 的元素,因為在索引值為 1 的位置不存在元素,因此回傳的是 undefined

最后,我們嘗試列印 ['??'], ['??', '??'] 的子陣列 ['??', '??'] 的第 2 個元素,子陣列索引值為 1的位置為 ?? ,因此它被列印出了,


147. 輸出什么?
class Calc {
	constructor() {
		this.count = 0 
	}

	increase() {
		this.count ++
	}
}

const calc = new Calc()
new Calc().increase()

console.log(calc.count)
  • A: 0
  • B: 1
  • C: undefined
  • D: ReferenceError
答案

答案: A

我們設定 calc 變數為 Calc 類的一個新實體, 然后,我們初始化一個 Calc 的新實體,而且呼叫了這個實體的 increase 方法,因為 count 屬性是在 Calc class 的 constructor 內部的,所以 count 屬性不會在 Calc 的原型鏈上共享出去,這就意味著 calc 實體的 count 值不會被更新,count 仍然是 0


148. 輸出什么?
const user = {
	email: "[email protected]",
	password: "12345"
}

const updateUser = ({ email, password }) => {
	if (email) {
		Object.assign(user, { email })
	}

	if (password) {
		user.password = password
	}

	return user
}

const updatedUser = updateUser({ email: "[email protected]" })

console.log(updatedUser === user)
  • A: false
  • B: true
  • C: TypeError
  • D: ReferenceError
答案

答案: B

updateUser 函式更新 user 的 emailpassword 屬性的值, 如果它們的值傳入函式, 函式回傳的就是 user 物件, updateUser 函式的回傳值是 user 物件,意味著 updatedUser 的值與 user 指向的是同一個 user 物件,updatedUser === usertrue.


149. 輸出什么?
const fruit = ['??', '??', '??']

fruit.slice(0, 1)
fruit.splice(0, 1)
fruit.unshift('??')

console.log(fruit)
  • A: ['??', '??', '??']
  • B: ['??', '??']
  • C: ['??', '??', '??']
  • D: ['??', '??', '??', '??']
答案

答案: C

首先,我們在 fruit 陣列上呼叫 slice 方法, slice 方法不會修改原始陣列,但是會回傳從陣列切片下來的值:香蕉 emoji,
其次,我們在 fruit 陣列上呼叫 splice 方法, splice 方法會修改原始陣列,也就意味著 fruit 陣列此時為 ['??', '??']
最后,我們在 fruit 陣列上呼叫 unshift 方法,通過添加一個值的方式改變了原始陣列,添加的是'??',它成為了陣列的第一個元素,現在 fruit 陣列的組成為 ['??', '??', '??']


150. 輸出什么?
const animals = {};
let dog = { emoji: '??' }
let cat = { emoji: '??' }

animals[dog] = { ...dog, name: "Mara" }
animals[cat] = { ...cat, name: "Sara" }

console.log(animals[dog])
  • A: { emoji: "??", name: "Mara" }
  • B: { emoji: "??", name: "Sara" }
  • C: undefined
  • D: ReferenceError
答案

答案: B

物件的鍵會被轉換為字串,

因為 dog 的值是一個物件, animals[dog] 實際上意味著我們創建了一個叫做 "object Object" 的屬性來代表新的物件, animals["object Object"] 現在等于 { emoji: "??", name: "Mara"}

cat 也是一個物件,animals[cat] 實際上意味著我們在用新的 cat 的屬性覆寫 animals[``"``object Object``"``] 的值,

列印 animals[dog],實際上是animals["object Object"],這是因為轉化dog物件為一個字串結果 "object Object" ,所以回傳 { emoji: "??", name: "Sara" }


151. 輸出什么?
const user = {
	email: "[email protected]",
	updateEmail: email => {
		this.email = email
	}
}

user.updateEmail("[email protected]")
console.log(user.email)
答案

答案: A

updateEmail 函式是一個箭頭函式,它沒有和 user 物件系結,這就意味著 this 關鍵字不會參考到 user 物件,但是會參考到全域物件, user 物件內部的 email 的值不會更新,當列印 user.email 的時候, 原始值 [email protected] 被回傳,


152. 輸出什么?
const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')

const runPromises = async () => {
	const res1 = await Promise.all([promise1, promise2])
	const res2  = await Promise.all([promise3, promise4])
	return [res1, res2]
}

runPromises()
	.then(res => console.log(res))
	.catch(err => console.log(err))
  • A: [['First', 'Second'], ['Fourth']]
  • B: [['First', 'Second'], ['Third', 'Fourth']]
  • C: [['First', 'Second']]
  • D: 'Third'
答案

答案: D

Promise.all 方法可以并行式運行 promise,如果其中一個 promise 失敗了,Promise.all 方法會帶上被 reject 的 promise 的值_rejects_,在這個例子中, promise3 帶著 "Third" 值 reject,我們在呼叫 runPromises 時在 runPromises 函式內部的 catch 方法去捕獲任意 error 從而捕獲到被 reject 的值,因為 promise3 帶著 "Third" 被 reject,所以只有 "Third" 列印,


153. 哪個作為method的值可以列印{ name: "Lydia", age: 22 }?
const keys = ["name", "age"]
const values = ["Lydia", 22]

const method = /* ?? */
Object[method](keys.map((_, i) => {
	return [keys[i], values[i]]
})) // { name: "Lydia", age: 22 }
  • A: entries
  • B: values
  • C: fromEntries
  • D: forEach
答案

答案: C

fromEntries 方法可以將二維陣列轉換為物件,在每個子陣列的第一個元素是 key,在每個子陣列的第二個元素是 value,在這個例子中,我們映射了 keys 陣列,它回傳了一個陣列,陣列的第一個元素為 keys 陣列當前索引的值,第二個元素為 values 陣列當前索引的值,

這樣就創建了一個包含正確 keys 和 values 的子陣列的陣列,因此結果為{ name: "Lydia", age: 22 }


154. 輸出什么?
const createMember = ({ email, address = {}}) => {
	const validEmail = /.+\@.+\..+/.test(email)
	if (!validEmail) throw new Error("Valid email pls")

	return {
		email,
		address: address ? address : null
	}
}

const member = createMember({ email: "[email protected]" })
console.log(member)
答案

答案: C

address 的默認值是一個空物件 {},當我們設定 member 變數為 createMember 函式回傳的物件,我們沒有為 address 引數傳值,意味著 address 的值為默認的空物件 {},一個空物件是一個 truthy 值,意味著 address ? address : null 條件會回傳 true,address 的值為空物件 {}


155. 輸出什么?
let randomValue = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/{ name:"Lydia" }
randomValue = https://www.cnblogs.com/mosaicMask/archive/2023/03/07/23

if (!typeof randomValue ==="string") {
	console.log("It's not a string!")
} else {
	console.log("Yay it's a string!")
}
  • A: It's not a string!
  • B: Yay it's a string!
  • C: TypeError
  • D: undefined
答案

答案: B

if 陳述句的條件判斷 !typeof randomValue 的值是否等于 "string"! 運算子將這個值轉化為一個布林值,如果值是 truthy 的話,回傳值會是 false,如果值是 falsy,回傳值會是 true,在這里, typeof randomValue 的回傳值是一個 truthy 值 "number",意味著 !typeof randomValue 的值是一個布林值 false

!typeof randomValue =https://www.cnblogs.com/mosaicMask/archive/2023/03/07/=="string" 總是回傳 false,因為我們實際上是在執行 false === "string",因為條件回傳的是 false,所以 else 陳述句中的代碼塊會被運行,因此列印 Yay it's a string!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/546113.html

標籤:其他

上一篇:前端設計模式——單例模式

下一篇:從0搭建Vue3組件庫(五): 如何使用Vite打包組件庫

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more