###### 1.輸出是什么刨啸?
```javascript
function sayHi() {
??console.log(name)
??console.log(age)
??var name = 'Lydia'
??let age = 21
}
sayHi()
```
- A: `Lydia`和 `undefined`
- B: `Lydia`和 `ReferenceError`
- C: `ReferenceError`和 `21`
- D: `undefined`和 `ReferenceError`
答案</b></summary>
<p>
####答案: D
在函數(shù)內(nèi)部,我們首先通過`var`關(guān)鍵字聲明了 `name` 變量膝迎。這意味著變量被提升了(內(nèi)存空間在創(chuàng)建階段就被設(shè)置好了)誉结,直到程序運行到定義變量位置之前默認(rèn)值都是 `undefined`董虱。因為當(dāng)我們打印 `name` 變量時還沒有執(zhí)行到定義變量的位置店煞,因此變量的值保持為 `undefined`苞慢。
通過`let`和 `const` 關(guān)鍵字聲明的變量也會提升诵原,但是和 `var` 不同,它們不會被<i>初始化</i>挽放。在我們聲明(初始化)之前是不能訪問它們的绍赛。這個行為被稱之為暫時性死區(qū)。當(dāng)我們試圖在聲明之前訪問它們時骂维,JavaScript 將會拋出一個 `ReferenceError` 錯誤惹资。
###### 2.輸出是什么?
```javascript
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 2`和 `0 1 2`
- B: `0 1 2`和 `3 3 3`
- C: `3 3 3`和 `0 1 2`
####答案: C
由于JavaScript的事件循環(huán)航闺,`setTimeout` 回調(diào)會在*遍歷結(jié)束后*才執(zhí)行褪测。因為在第一個遍歷中遍歷 `i` 是通過 `var` 關(guān)鍵字聲明的,所以這個值是全局作用域下的潦刃。在遍歷過程中侮措,我們通過一元操作符 `++` 來每次遞增 `i` 的值。當(dāng) `setTimeout` 回調(diào)執(zhí)行的時候乖杠,`i` 的值等于 3分扎。
在第二個遍歷中,遍歷`i`是通過 `let` 關(guān)鍵字聲明的:通過 `let` 和 `const` 關(guān)鍵字聲明的變量是擁有塊級作用域(指的是任何在 {} 中的內(nèi)容)胧洒。在每次的遍歷過程中畏吓,`i` 都有一個新值,并且每個值都在循環(huán)內(nèi)的作用域中卫漫。
###### 3.輸出是什么菲饼?
```javascript
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`的值是一個常規(guī)函數(shù),但是 `perimeter` 的值是一個箭頭函數(shù)列赎。
對于箭頭函數(shù)宏悦,`this`關(guān)鍵字指向的是它當(dāng)前周圍作用域(簡單來說是包含箭頭函數(shù)的常規(guī)函數(shù),如果沒有常規(guī)函數(shù)的話就是全局對象),這個行為和常規(guī)函數(shù)不同饼煞。這意味著當(dāng)我們調(diào)用 `perimeter` 時源葫,`this` 不是指向 `shape` 對象,而是它的周圍作用域(在例子中是 `window`)砖瞧。
在`window`中沒有 `radius` 這個屬性息堂,因此返回 `undefined`。
###### 4.輸出是什么芭届?
```javascript
;+true
!'Lydia'
```
- A: `1` and `false`
- B: `false` and `NaN`
- C: `false` and `false`
####答案: A
一元操作符加號嘗試將bool轉(zhuǎn)為 number储矩。`true` 轉(zhuǎn)換為 number 的話為 `1`,`false` 為 `0`褂乍。
字符串`'Lydia'`是一個真值持隧,真值取反那么就返回 `false`。
###### 5.哪一個是無效的逃片?
```javascript
const bird = {
??size: 'small'
}
const mouse = {
??name: 'Mickey',
??small: true
}
```
- A: `mouse.bird.size`
- B: `mouse[bird.size]`
- C: `mouse[bird["size"]]`
- D: All of them are valid
####答案: A
在JavaScript中屡拨,所有對象的 keys 都是字符串(除非對象是 Symbol)。盡管我們可能不會定義它們?yōu)樽址焓担鼈冊诘讓涌倳晦D(zhuǎn)換為字符串呀狼。
當(dāng)我們使用括號語法時([]),JavaScript 會解釋(或者 unboxes)語句损离。它首先看到第一個開始括號 `[` 并繼續(xù)前進直到找到結(jié)束括號 `]`哥艇。只有這樣,它才會計算語句的值僻澎。
`mouse[bird.size]`:首先計算 `bird.size`貌踏,這會得到 `small`。`mouse["small"]` 返回 `true`窟勃。
然后使用點語法的話祖乳,上面這一切都不會發(fā)生。`mouse`沒有 `bird` 這個 key秉氧,這也就意味著 `mouse.bird` 是 `undefined`眷昆。然后當(dāng)我們使用點語法 `mouse.bird.size` 時,因為 `mouse.bird` 是 `undefined`汁咏,這也就變成了 `undefined.size`亚斋。這個行為是無效的,并且會拋出一個錯誤類似 `Cannot read property "size" of undefined`攘滩。
###### 6.輸出是什么帅刊?
```javascript
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中,當(dāng)設(shè)置兩個對象彼此相等時,它們會通過*引用*進行交互。
首先室埋,變量`c`的值是一個對象。接下來冒黑,我們給 `d` 分配了一個和 `c` 對象相同的引用。
<img src="https://i.imgur.com/ko5k0fs.png" width="200">
因此當(dāng)我們改變其中一個對象時勤哗,其實是改變了所有的對象抡爹。
###### 7.輸出是什么?
```javascript
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()`是一個內(nèi)建的函數(shù)構(gòu)造器芒划。雖然它看著像是一個 number冬竟,但它實際上并不是一個真實的 number:它有一堆額外的功能并且它是一個對象。
當(dāng)我們使用`==`操作符時民逼,它只會檢查兩者是否擁有相同的*值*泵殴。因為它們的值都是 `3`,因此返回 `true`拼苍。
然后笑诅,當(dāng)我們使用`===`操作符時,兩者的值以及*類型*都應(yīng)該是相同的疮鲫。`new Number()` 是一個對象而不是 number吆你,因此返回 `false`。
###### 8.輸出是什么俊犯?
```javascript
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`是一個靜態(tài)方法妇多。靜態(tài)方法被設(shè)計為只能被創(chuàng)建它們的構(gòu)造器使用(也就是 `Chameleon`),并且不能傳遞給實例燕侠。因為 `freddie` 是一個實例者祖,靜態(tài)方法不能被實例使用,因此拋出了 `TypeError` 錯誤贬循。
###### 9.輸出是什么咸包?
```javascript
let greeting
greetign = {} // Typo!
console.log(greetign)
```
- A: `{}`
- B: `ReferenceError: greetign is not defined`
- C: `undefined`
####答案: A
代碼打印出了一個對象,這是因為我們在全局對象上創(chuàng)建了一個空對象杖虾!當(dāng)我們將`greeting`寫錯成 `greetign` 時烂瘫,JS 解釋器實際在上瀏覽器中將它視為 `global.greetign = {}` (或者 `window.greetign = {}`)。
為了避免這個為題奇适,我們可以使用`"use strict"坟比。這能確保當(dāng)你聲明變量時必須賦值。
###### 10.當(dāng)我們這么做時嚷往,會發(fā)生什么葛账?
```javascript
function bark() {
??console.log('Woof!')
}
bark.animal = 'dog'
```
- A: Nothing, this is totally fine!
- B: `SyntaxError`. You cannot add properties to a function this way.
- C: `undefined`
- D: `ReferenceError`
####答案: A
這在JavaScript中是可以的,因為函數(shù)是對象Fと省(除了基本類型之外其他都是對象)
函數(shù)是一個特殊的對象籍琳。你寫的這個代碼其實不是一個實際的函數(shù)菲宴。函數(shù)是一個擁有屬性的對象,并且屬性也可被調(diào)用趋急。
###### 11.輸出是什么喝峦?
```javascript
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
你不能像常規(guī)對象那樣,給構(gòu)造函數(shù)添加屬性呜达。如果你想一次性給所有實例添加特性谣蠢,你應(yīng)該使用原型。因此本例中查近,使用如下方式:
```js
Person.prototype.getFullName = function () {
??return `${this.firstName} ${this.lastName}`;
}
```
這才會使`member.getFullName()`起作用眉踱。為什么這么做有益的?假設(shè)我們將這個方法添加到構(gòu)造函數(shù)本身里霜威。也許不是每個 `Person` 實例都需要這個方法谈喳。這將浪費大量內(nèi)存空間,因為它們?nèi)匀痪哂性搶傩越募溃@將占用每個實例的內(nèi)存空間叁执。相反,如果我們只將它添加到原型中矮冬,那么它只存在于內(nèi)存中的一個位置谈宛,但是所有實例都可以訪問它!
###### 12.輸出是什么胎署?
```javascript
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` 關(guān)鍵字。當(dāng)使用 `new` 時琼牧,`this` 引用我們創(chuàng)建的空對象恢筝。當(dāng)未使用 `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)階段中暂题,事件從祖先元素向下傳播到目標(biāo)元素。當(dāng)事件達到**目標(biāo)**(target)元素后究珊,**冒泡**(bubbling)才開始薪者。
<img src="https://i.imgur.com/N18oRgd.png" width="200">
###### 14.所有對象都有原型。
- A: true
- B: false
####答案: B
除了**基本對象**(base object)剿涮,所有對象都有原型言津」ト耍基本對象可以訪問一些方法和屬性,比如 `.tostring`悬槽。這就是為什么你可以使用內(nèi)置的 JavaScript 方法贝椿!所有這些方法在原型上都是可用的。雖然 JavaScript 不能直接在對象上找到這些方法陷谱,但 JavaScript 會沿著原型鏈找到它們,以便于你使用瑟蜈。
###### 15.輸出是什么烟逊?
```javascript
function sum(a, b) {
??return a + b
}
sum(1, '2')
```
- A: `NaN`
- B: `TypeError`
- C: `"12"`
- D: `3`
####答案: C
JavaScript是一種**動態(tài)類型語言**:我們不指定某些變量的類型。值可以在你不知道的情況下自動轉(zhuǎn)換成另一種類型铺根,這種類型稱為**隱式類型轉(zhuǎn)換**(implicit type coercion)宪躯。**Coercion** 是指將一種類型轉(zhuǎn)換為另一種類型。
在本例中位迂,JavaScript將數(shù)字 `1` 轉(zhuǎn)換為字符串访雪,以便函數(shù)有意義并返回一個值。在數(shù)字類型(`1`)和字符串類型(`'2'`)相加時掂林,該數(shù)字被視為字符串臣缀。我們可以連接字符串,比如 `"Hello" + "World"`泻帮,這里發(fā)生的是 `"1" + "2"`精置,它返回 `"12"`。
###### 16.輸出是什么锣杂?
```javascript
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 現(xiàn)在是 `1`)
一元**前自增**運算符 `++`:
1.值自增(number 現(xiàn)在是 `2`)
2.返回值(返回 `2`)
結(jié)果是`0 2 2`.
###### 17.輸出是什么脂倦?
```javascript
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
如果使用標(biāo)記模板字面量,第一個參數(shù)的值總是包含字符串的數(shù)組元莫。其余的參數(shù)獲取的是傳遞的表達式的值赖阻!
###### 18.輸出是什么?
```javascript
function checkAge(data) {
??if (data === { age: 18 }) {
????console.log('You are an adult!')
??} else if (data == { 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 檢查對象是否具有對內(nèi)存中相同位置的引用朽基。
題目中我們正在比較的兩個對象不是同一個引用:作為參數(shù)傳遞的對象引用的內(nèi)存位置布隔,與用于判斷相等的對象所引用的內(nèi)存位置并不同。
這也是`{ age: 18 } === { age: 18 }`和 `{ age: 18 } == { age: 18 }` 都返回 `false` 的原因稼虎。
###### 19.輸出是什么衅檀?
```javascript
function getAge(...args) {
??console.log(typeof args)
}
getAge(21)
```
- A: `"number"`
- B: `"array"`
- C: `"object"`
- D: `"NaN"`
####答案: C
擴展運算符(`...args`)會返回實參組成的數(shù)組。而數(shù)組是對象霎俩,因此 `typeof args` 返回 `"object"`哀军。
###### 20.輸出是什么沉眶?
```javascript
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.輸出是什么藕咏?
```javascript
const sum = eval('10*10+5')
```
- A: `105`
- B: `"105"`
- C: `TypeError`
- D: `"10*10+5"`
####答案: A
代碼以字符串形式傳遞進來,`eval`對其求值秽五。如果它是一個表達式孽查,就像本例中那樣,它對表達式求值坦喘。表達式是 `10 * 10 + 5`盲再。這將返回數(shù)字 `105`。
###### 22. cool_secret可訪問多長時間瓣铣?
```javascript
sessionStorage.setItem('cool_secret', 123)
```
- A: Forever, the data doesn't get lost.
- B: When the user closes the tab.
- C: When the user closes the entire browser, not only the tab.
- D: When the user shuts off their computer.
####答案: B
關(guān)閉**tab標(biāo)簽頁** 后答朋,`sessionStorage` 存儲的數(shù)據(jù)才會刪除。
如果使用`localStorage`棠笑,那么數(shù)據(jù)將永遠在那里绿映,除非調(diào)用了 `localStorage.clear()`。
###### 23.輸出是什么腐晾?
```javascript
var num = 8
var num = 10
console.log(num)
```
- A: `8`
- B: `10`
- C: `SyntaxError`
- D: `ReferenceError`
####答案: B
使用`var`關(guān)鍵字叉弦,你可以用相同的名稱聲明多個變量。然后變量將保存最新的值藻糖。
你不能使用`let`或 `const` 來實現(xiàn)這一點淹冰,因為它們是塊作用域的。
###### 24.輸出是什么巨柒?
```javascript
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`牺勾。它有數(shù)字類型為 `1`正罢,`set.has(1)` 返回 `true`。
###### 25.輸出是什么驻民?
```javascript
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
如果你有兩個名稱相同的鍵翻具,則鍵會被替換掉履怯。它仍然位于第一個鍵出現(xiàn)的位置,但是值是最后出現(xiàn)那個鍵的值裆泳。