這兩天的GitHub Trending repositories被一個名叫?javascript-questions的項(xiàng)目霸榜了,項(xiàng)目中記錄了一些JavaScript題目。
我大概從頭到尾看了一遍,都是一些基礎(chǔ)的題目,我大概花了半個小時(有些題很簡單,可以一掃而過)把這些題做完了,雖然題目很簡單,但是每道題都對應(yīng)一個知識點(diǎn),如果這個知識點(diǎn)你沒有接觸過,那肯定會做錯,如果你接觸過這些知識點(diǎn),那么這些題對你來說就很容易。
建議大家也花半個小時來做一做,以便查漏補(bǔ)缺。
為方便大家能夠更快的做題,而不把時間浪費(fèi)在翻譯上,我又花了幾個小時把它們翻譯成了中文,當(dāng)然已經(jīng)獲得了作者授權(quán)。
JavaScript 進(jìn)階問題列表
1. 下面代碼的輸出是什么?
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
答案: D
在函數(shù)中,我們首先使用var關(guān)鍵字聲明了name變量。 這意味著變量在創(chuàng)建階段會被提升(JavaScript會在創(chuàng)建變量創(chuàng)建階段為其分配內(nèi)存空間),默認(rèn)值為undefined,直到我們實(shí)際執(zhí)行到使用該變量的行。 我們還沒有為name變量賦值,所以它仍然保持undefined的值。
使用let關(guān)鍵字(和const)聲明的變量也會存在變量提升,但與var不同,初始化沒有被提升。 在我們聲明(初始化)它們之前,它們是不可訪問的。 這被稱為“暫時死區(qū)”。 當(dāng)我們在聲明變量之前嘗試訪問變量時,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 2?and?0 1 2
B:?0 1 2?and?3 3 3
C:?3 3 3?and?0 1 2
答案: C
由于JavaScript中的事件執(zhí)行機(jī)制,setTimeout函數(shù)真正被執(zhí)行時,循環(huán)已經(jīng)走完。 由于第一個循環(huán)中的變量i是使用var關(guān)鍵字聲明的,因此該值是全局的。 在循環(huán)期間,我們每次使用一元運(yùn)算符++都會將i的值增加1。 因此在第一個例子中,當(dāng)調(diào)用setTimeout函數(shù)時,i已經(jīng)被賦值為3。
在第二個循環(huán)中,使用let關(guān)鍵字聲明變量i:使用let(和const)關(guān)鍵字聲明的變量是具有塊作用域的(塊是{}之間的任何東西)。 在每次迭代期間,i將被創(chuàng)建為一個新值,并且每個值都會存在于循環(huán)內(nè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是普通函數(shù),而perimeter是箭頭函數(shù)。
對于箭頭函數(shù),this關(guān)鍵字指向是它所在上下文(定義時的位置)的環(huán)境,與普通函數(shù)不同! 這意味著當(dāng)我們調(diào)用perimeter時,它不是指向shape對象,而是指其定義時的環(huán)境(window)。沒有值radius屬性,返回undefined。
4. 下面代碼的輸出是什么?
+true;
!"Lydia";
A:?1?and?false
B:?false?and?NaN
C:?false?and?false
答案: A
一元加號會嘗試將boolean類型轉(zhuǎn)換為數(shù)字類型。?true被轉(zhuǎn)換為1,false被轉(zhuǎn)換為0。
字符串'Lydia'是一個真值。 我們實(shí)際上要問的是“這個真值是假的嗎?”。 這會返回false。
5. 哪個選項(xiàng)是不正確的?
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中,所有對象鍵都是字符串(除了Symbol)。盡管有時我們可能不會給定字符串類型,但它們總是被轉(zhuǎn)換為字符串。
JavaScript解釋語句。當(dāng)我們使用方括號表示法時,它會看到第一個左括號[,然后繼續(xù),直到找到右括號]。只有在那個時候,它才會對這個語句求值。
mouse [bird.size]:首先它會對bird.size求值,得到small。?mouse [“small”]返回true。
但是,使用點(diǎn)表示法,這不會發(fā)生。?mouse沒有名為bird的鍵,這意味著mouse.bird是undefined。 然后,我們使用點(diǎn)符號來詢問size:mouse.bird.size。 由于mouse.bird是undefined,我們實(shí)際上是在詢問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中,當(dāng)設(shè)置它們彼此相等時,所有對象都通過引用進(jìn)行交互。
首先,變量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是一個內(nèi)置的函數(shù)構(gòu)造函數(shù)。 雖然它看起來像一個數(shù)字,但它并不是一個真正的數(shù)字:它有一堆額外的功能,是一個對象。
當(dāng)我們使用==運(yùn)算符時,它只檢查它是否具有相同的值。 他們都有3的值,所以它返回true。
然而,當(dāng)我們使用===操作符時,類型和值都需要相等,new Number不是一個數(shù)字,是一個對象類型。兩者都返回?false。
8. 下面代碼的輸出是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = 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)方法僅在創(chuàng)建它們的構(gòu)造函數(shù)中存在,并且不能傳遞給任何子級。 由于freddie是一個子級對象,函數(shù)不會傳遞,所以在freddie實(shí)例上不存在freddie方法:拋出TypeError。
9. 下面代碼的輸出是什么?
let greeting;
greetign = {}; // Typo!
console.log(greetign);
A:?{}
B:?ReferenceError: greetign is not defined
C:?undefined
答案: A
控制臺會輸出空對象,因?yàn)槲覀儎倓傇谌謱ο笊蟿?chuàng)建了一個空對象! 當(dāng)我們錯誤地將greeting輸入為greetign時,JS解釋器實(shí)際上在瀏覽器中將其視為global.greetign = {}(或window.greetign = {})。
為了避免這種情況,我們可以使用“use strict”。 這可以確保在將變量賦值之前必須聲明變量。
10. 當(dāng)我們這樣做時會發(fā)生什么?
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中是可能的,因?yàn)楹瘮?shù)也是對象!(原始類型之外的所有東西都是對象)
函數(shù)是一種特殊類型的對象。您自己編寫的代碼并不是實(shí)際的函數(shù)。 該函數(shù)是具有屬性的對象,此屬性是可調(diào)用的。
11. 下面代碼的輸出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = => 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)該這樣寫:
Person.prototype.getFullName = function {
return `${this.firstName} ${this.lastName}`;
}
這樣會使member.getFullName是可用的,為什么樣做是對的? 假設(shè)我們將此方法添加到構(gòu)造函數(shù)本身。 也許不是每個Person實(shí)例都需要這種方法。這會浪費(fèi)大量內(nèi)存空間,因?yàn)樗鼈內(nèi)匀痪哂性搶傩?,這占用了每個實(shí)例的內(nèi)存空間。 相反,如果我們只將它添加到原型中,我們只需將它放在內(nèi)存中的一個位置,但它們都可以訪問它!
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關(guān)鍵字。 使用new時,它指的是我們創(chuàng)建的新空對象。 但是,如果你不添加new它指的是全局對象!
我們指定了this.firstName等于'Sarah和this.lastName等于Smith。 我們實(shí)際做的是定義global.firstName ='Sarah'和global.lastName ='Smith。?sarah本身的返回值是undefined。
12. 事件傳播的三個階段是什么?
A: 目標(biāo) > 捕獲 > 冒泡
B: 冒泡 > 目標(biāo) > 捕獲
C: 目標(biāo) > 冒泡 > 捕獲
D: 捕獲 > 目標(biāo) > 冒泡
答案: D
在捕獲階段,事件通過父元素向下傳遞到目標(biāo)元素。 然后它到達(dá)目標(biāo)元素,冒泡開始。
13. 所有對象都有原型.
A: 對
B: 錯誤
答案: B
除基礎(chǔ)對象外,所有對象都有原型。 基礎(chǔ)對象可以訪問某些方法和屬性,例如.toString。 這就是您可以使用內(nèi)置JavaScript方法的原因! 所有這些方法都可以在原型上找到。 雖然JavaScript無法直接在您的對象上找到它,但它會沿著原型鏈向下尋找并在那里找到它,這使您可以訪問它。
14. 下面代碼的輸出是什么?
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)換。?強(qiáng)制從一種類型轉(zhuǎn)換為另一種類型。
在此示例中,JavaScript將數(shù)字1轉(zhuǎn)換為字符串,以使函數(shù)有意義并返回值。 在讓數(shù)字類型(1)和字符串類型('2')相加時,該數(shù)字被視為字符串。 我們可以連接像“Hello”+“World”這樣的字符串,所以這里發(fā)生的是“1”+“2”返回“12”。
15. 下面代碼的輸出是什么?
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
后綴一元運(yùn)算符++:
返回值(返回0)
增加值(數(shù)字現(xiàn)在是1)
前綴一元運(yùn)算符++:
增加值(數(shù)字現(xiàn)在是2)
返回值(返回2)
所以返回0 2 2。
小結(jié)
文中如有錯誤,歡迎在評論區(qū)指正,如果這篇文章幫助到了你,歡迎點(diǎn)贊和關(guān)注。
想閱讀更多優(yōu)質(zhì)文章、可關(guān)注我,你的點(diǎn)贊和關(guān)注是我持續(xù)創(chuàng)作的動力!
歡迎大家和我一起討論學(xué)習(xí),我們一起交流成長。
“我自己是一名從事了5年前端的老程序員,辭職目前在做講師,今年年初我花了一個月整理了一份最適合2019年學(xué)習(xí)的web前端干貨,從最基礎(chǔ)的HTML+CSS+JS到移動端HTML5到各種框架都有整理,送給每一位前端小伙伴,這里是小白聚集地,歡迎初學(xué)和進(jìn)階中的小伙伴。"
加微信:webtutou123 (領(lǐng)?。?/p>