時候,前端網(wǎng)頁需要知道,用戶使用的是手機瀏覽器還是桌面瀏覽器。
本文根據(jù) StackOverflow,整理了 JavaScript 偵測手機瀏覽器的五種方法。
最簡單的方法就是分析瀏覽器的 user agent 字符串,它包含了設備信息。
JS 通過navigator.userAgent屬性拿到這個字符串,只要里面包含mobi、android、iphone等關鍵字,就可以認定是移動設備。
if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) { // 當前設備是移動設備 } // 另一種寫法 if ( navigator.userAgent.match(/Mobi/i) || navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/iPhone/i) ) { // 當前設備是移動設備 }
這種方法的優(yōu)點是簡單方便,缺點是不可靠,因為用戶可以修改這個字符串,讓手機瀏覽器偽裝成桌面瀏覽器。
Chromium 系的瀏覽器,還有一個navigator.userAgentData屬性,也是類似的作用。不同之處是它將 user agent 字符串解析為一個對象,該對象的mobile屬性,返回一個布爾值,表示用戶是否使用移動設備。
const isMobile = navigator.userAgentData.mobile;
注意,蘋果的 Safari 瀏覽器和 Firefox 瀏覽器都不支持這個屬性,具體情況可以查看 Caniuse 網(wǎng)站。
此外,還有一個已經(jīng)廢除的navigator.platform屬性,所有瀏覽器都支持,所以也可以用。它返回一個字符串,表示用戶的操作系統(tǒng)。
if (/Android|iPhone|iPad|iPod/i.test(navigator.platform)) { // 當前設備是移動設備 }
另一種方法是通過屏幕寬度,判斷是否為手機。
window.screen對象返回用戶設備的屏幕信息,該對象的width屬性是屏幕寬度(單位為像素)。
if (window.screen.width < 500) { // 當前設備是移動設備 }
上面示例中,如果屏幕寬度window.screen.width小于500像素,就認為是手機。
這個方法的缺點在于,如果手機橫屏使用,就識別不了。
另一個屬性window.innerWidth返回瀏覽器窗口里面的網(wǎng)頁可見部分的寬度,比較適合指定網(wǎng)頁在不同寬度下的樣式。
const getBrowserWidth = function() { if (window.innerWidth < 768) { return "xs"; } else if (window.innerWidth < 991) { return "sm"; } else if (window.innerWidth < 1199) { return "md"; } else { return "lg"; } };
第三種方法是偵測屏幕方向,手機屏幕可以隨時改變方向(橫屏或豎屏),桌面設備做不到。
window.orientation屬性用于獲取屏幕的當前方向,只有移動設備才有這個屬性,桌面設備會返回undefined。
if (typeof window.orientation !== 'undefined') { // 當前設備是移動設備 }
注意,iPhone 的 Safari 瀏覽器不支持該屬性。
第四種方法是,手機瀏覽器上的 DOM 元素可以通過ontouchstart屬性,為touch事件指定監(jiān)聽函數(shù)。桌面設備沒有這個屬性。
function isMobile() { return ('ontouchstart' in document.documentElement); } // 另一種寫法 function isMobile() { try { document.createEvent("TouchEvent"); return true; } catch(e) { return false; } }
最后一種方法是結合 CSS 來判斷。
CSS 通過 media query(媒介查詢)為網(wǎng)頁指定響應式樣式。如果某個針對手機的 media query 語句生效了,就可以認為當前設備是移動設備。
window.matchMedia()方法接受一個 CSS 的 media query 語句作為參數(shù),判斷這個語句是否生效。
let isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
上面示例中,window.matchMedia()的參數(shù)是一個 CSS 查詢語句,表示只對屏幕寬度不超過 700 像素的設備生效。它返回一個對象,該對象的matches屬性是一個布爾值。如果是true,就表示查詢生效,當前設備是手機。
除了通過屏幕寬度判斷,還可以通過指針的精確性判斷。
let isMobile = window.matchMedia("(pointer:coarse)").matches;
上面示例中,CSS 語句pointer:coarse表示當前設備的指針是不精確的。由于手機不支持鼠標,只支持觸摸,所以符合這個條件。
有些設備支持多種指針,比如同時支持鼠標和觸摸。pointer:coarse只用來判斷主指針,此外還有一個any-pointer命令判斷所有指針。
let isMobile = window.matchMedia("(any-pointer:coarse)").matches;
上面示例中,any-pointer:coarse表示所有指針里面,只要有一個指針是不精確的,就符合查詢條件。
除了上面這些方法,也可以使用別人寫好的工具包。這里推薦 react-device-detect,它支持多種粒度的設備偵測。
import {isMobile} from 'react-device-detect'; if (isMobile) { // 當前設備是移動設備 }
(完)
體上程序代碼的執(zhí)行是從上到下順序執(zhí)行,在某些具體階段可以會產(chǎn)生分支和循環(huán)重復的情形,形成了各種不同的程序語句,構成了不同的程序結構。主要有順序結構,分支結構和循環(huán)結構。以前的代碼主要是按程序的順序執(zhí)行,以后的代碼會是這三者的不同組合。
如果說表達式(例如:num1+num2)是短語。
語句就是完整的句子。(例如:sum=num1+num2;)
表達式計算出來的是一個值,語句來執(zhí)行使某事情發(fā)生。
例如:給一個學生的年齡,輸出這個學生是否成年了。
如果 年齡大于等于18歲 輸出學生成年了。
這里的成年了是否會輸出是有 年齡是否滿足決定的。
JS在默認的就是從上到下一條條的執(zhí)行代碼語句。
為使某事發(fā)生可能會改變語句的默認執(zhí)行順序。
格式:if(條件){
條件為真實執(zhí)行的語句
}
JS解釋器會根據(jù)條件的結果決定是執(zhí)行還是跳過語句。
讀法:如果 條件為真,執(zhí)行里面的代碼。為假掉過里面的代碼。
//實踐:給一個學生的年齡,輸出這個學生是否成年了。
//var age1=parseInt(prompt("請輸入一個學生的年齡:"));
var age1=23;
if(age1>=18){
console.log("這個學生成年了。");
}
if(age1<18){
console.log("這個學生沒有成年。");
}
分析一下,這里的判斷是一個事情的兩個方面?
格式:
if(條件){條件為真,執(zhí)行的語句}
else{條件為假(不為真),執(zhí)行的語句。}
讀法:如果 條件為真 執(zhí)行為真的語句,否則執(zhí)行為假的語句
//實踐:給一個學生的年齡,輸出這個學生是否成年了。
// var age2=parseInt(prompt("請輸入一個學生的年齡:"));
var age2=16;
if(age2>=18){
console.log("這個學生成年了。");
}
else{
console.log("這個學生沒有成年。");
}
如果判斷學生的成績等級,會有很多的判斷。
格式:
if(條件1){為真,執(zhí)行的語句}
else if(條件2){為真,執(zhí)行的語句}
......
else if(條件n){為真,執(zhí)行的語句}
else{ 條件n為假,執(zhí)行的語句 }
//實踐:根據(jù)學生的成績,判定學生的等級
//var score1=parseFloat(prompt("請輸入一個學生的成績:"));
var score1=95;
if(score1>=90){console.log("A");}
else if(score1>=80){console.log("B");}
else if(score1>=70){console.log("C");}
else if(score1>=60){console.log("D");}
else{console.log("E");}
它是if語句的另外一種形式,解決根據(jù)表達式的不同而執(zhí)行不同語句的問題。
格式:
switch(表達式){
case 值1:語句塊;break;
case 值2:語句塊;break;
......
case 值n:語句塊;break;
default:語句塊n+1;break;
}
執(zhí)行:
計算一次 switch 表達式
每個表達式的值與每個 case 的值進行對比
如果存在匹配,則執(zhí)行關聯(lián)代碼
default:關鍵詞規(guī)定不存在 case 匹配時所運行的代碼。
break:如果 JavaScript 遇到 break 關鍵詞,它會跳出 switch 代碼塊。
//實踐:重寫根據(jù)學生的成績,判定學生的等級
//var score2=parseInt(prompt("請輸入一個學生的成績:"));
var score2=90;
score2=parseInt(score2/10);//parseInt()取得整數(shù)部分。
switch(score2){
case 10:console.log("A");break;
case 9:console.log("A");break;
case 8:console.log("B");break;
case 7:console.log("C");break;
case 6:console.log("D");break;
default:console.log("E");break;}
可以當成一種簡單的if-else語句。
名字表示的三元運算符需要三個操作數(shù)。
語法是:
條件 ? 結果1 : 結果2;
這里你把條件寫在問號上(?)的前面后面跟著用冒號(:)分隔的結果1和結果2。
滿足條件時結果1否則結果2。
這兩天的GitHub Trending repositories被一個名叫 javascript-questions的項目霸榜了,項目中記錄了一些JavaScript題目。
我大概從頭到尾看了一遍,都是一些基礎的題目,我大概花了半個小時(有些題很簡單,可以一掃而過)把這些題做完了,雖然題目很簡單,但是每道題都對應一個知識點,如果這個知識點你沒有接觸過,那肯定會做錯,如果你接觸過這些知識點,那么這些題對你來說就很容易。
建議大家也花半個小時來做一做,以便查漏補缺。
為方便大家能夠更快的做題,而不把時間浪費在翻譯上,我又花了幾個小時把它們翻譯成了中文,當然已經(jīng)獲得了作者授權。
文中有些點作者解釋的不太完整,為了更好的理解,我在文中添加了一些個人解釋。
倉庫地址:https://github.com/lydiahallie/javascript-questions
我在我的Instagram上發(fā)布了每日JavaScript選擇題,我也會在這里發(fā)布!
從基礎到高級:測試您對JavaScript的了解程度,刷新您的知識,或為您的編碼面試做好準備! 我每周用新問題更新這個項目。
答案位于問題下方的折疊部分,只需單擊它們即可展開。 祝你好運??
function sayHi() {
console.log(name);
console.log(age);
var name="Lydia";
let age=21;
}
sayHi();
復制代碼
答案
答案: D
在函數(shù)中,我們首先使用var關鍵字聲明了name變量。 這意味著變量在創(chuàng)建階段會被提升(JavaScript會在創(chuàng)建變量創(chuàng)建階段為其分配內(nèi)存空間),默認值為undefined,直到我們實際執(zhí)行到使用該變量的行。 我們還沒有為name變量賦值,所以它仍然保持undefined的值。
使用let關鍵字(和const)聲明的變量也會存在變量提升,但與var不同,初始化沒有被提升。 在我們聲明(初始化)它們之前,它們是不可訪問的。 這被稱為“暫時死區(qū)”。 當我們在聲明變量之前嘗試訪問變量時,JavaScript會拋出一個ReferenceError。
譯者注:
關于let的是否存在變量提升,我們可以用下面的例子來驗證:
let name='ConardLi'
{
console.log(name) // Uncaught ReferenceError: name is not defined
let name='code秘密花園'
}
復制代碼
let變量如果不存在變量提升,console.log(name)就會輸出ConardLi,結果卻拋出了ReferenceError,那么這很好的說明了,let也存在變量提升,但是它存在一個“暫時死區(qū)”,在變量未初始化或賦值前不允許訪問。
變量的賦值可以分為三個階段:
關于let、var和function:
for (var i=0; i < 3; i++) {
setTimeout(()=> console.log(i), 1);
}
for (let i=0; i < 3; i++) {
setTimeout(()=> console.log(i), 1);
}
復制代碼
答案
答案: C
由于JavaScript中的事件執(zhí)行機制,setTimeout函數(shù)真正被執(zhí)行時,循環(huán)已經(jīng)走完。 由于第一個循環(huán)中的變量i是使用var關鍵字聲明的,因此該值是全局的。 在循環(huán)期間,我們每次使用一元運算符++都會將i的值增加1。 因此在第一個例子中,當調(diào)用setTimeout函數(shù)時,i已經(jīng)被賦值為3。
在第二個循環(huán)中,使用let關鍵字聲明變量i:使用let(和const)關鍵字聲明的變量是具有塊作用域的(塊是{}之間的任何東西)。 在每次迭代期間,i將被創(chuàng)建為一個新值,并且每個值都會存在于循環(huán)內(nèi)的塊級作用域。
const shape={
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: ()=> 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
復制代碼
答案
答案: B
請注意,diameter是普通函數(shù),而perimeter是箭頭函數(shù)。
對于箭頭函數(shù),this關鍵字指向是它所在上下文(定義時的位置)的環(huán)境,與普通函數(shù)不同! 這意味著當我們調(diào)用perimeter時,它不是指向shape對象,而是指其定義時的環(huán)境(window)。沒有值radius屬性,返回undefined。
+true;
!"Lydia";
復制代碼
答案
答案: A
一元加號會嘗試將boolean類型轉換為數(shù)字類型。 true被轉換為1,false被轉換為0。
字符串'Lydia'是一個真值。 我們實際上要問的是“這個真值是假的嗎?”。 這會返回false。
const bird={
size: "small"
};
const mouse={
name: "Mickey",
small: true
};
復制代碼
答案
答案: A
在JavaScript中,所有對象鍵都是字符串(除了Symbol)。盡管有時我們可能不會給定字符串類型,但它們總是被轉換為字符串。
JavaScript解釋語句。當我們使用方括號表示法時,它會看到第一個左括號[,然后繼續(xù),直到找到右括號]。只有在那個時候,它才會對這個語句求值。
mouse [bird.size]:首先它會對bird.size求值,得到small。 mouse [“small”]返回true。
但是,使用點表示法,這不會發(fā)生。 mouse沒有名為bird的鍵,這意味著mouse.bird是undefined。 然后,我們使用點符號來詢問size:mouse.bird.size。 由于mouse.bird是undefined,我們實際上是在詢問undefined.size。 這是無效的,并將拋出Cannot read property "size" of undefined。
let c={ greeting: "Hey!" };
let d;
d=c;
c.greeting="Hello";
console.log(d.greeting);
復制代碼
答案
答案: A
在JavaScript中,當設置它們彼此相等時,所有對象都通過引用進行交互。
首先,變量c為對象保存一個值。 之后,我們將d指定為c與對象相同的引用。
更改一個對象時,可以更改所有對象。
let a=3;
let b=new Number(3);
let c=3;
console.log(a==b);
console.log(a===b);
console.log(b===c);
復制代碼
答案
答案: C
new Number()是一個內(nèi)置的函數(shù)構造函數(shù)。 雖然它看起來像一個數(shù)字,但它并不是一個真正的數(shù)字:它有一堆額外的功能,是一個對象。
當我們使用==運算符時,它只檢查它是否具有相同的值。 他們都有3的值,所以它返回true。
譯者注:==會引發(fā)隱式類型轉換,右側的對象類型會自動拆箱為Number類型。
然而,當我們使用===操作符時,類型和值都需要相等,new Number()不是一個數(shù)字,是一個對象類型。兩者都返回 false。
class Chameleon {
static colorChange(newColor) {
this.newColor=newColor;
}
constructor({ newColor="green" }={}) {
this.newColor=newColor;
}
}
const freddie=new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
復制代碼
答案
答案: D
colorChange方法是靜態(tài)的。 靜態(tài)方法僅在創(chuàng)建它們的構造函數(shù)中存在,并且不能傳遞給任何子級。 由于freddie是一個子級對象,函數(shù)不會傳遞,所以在freddie實例上不存在freddie方法:拋出TypeError。
let greeting;
greetign={}; // Typo!
console.log(greetign);
復制代碼
答案
答案: A
控制臺會輸出空對象,因為我們剛剛在全局對象上創(chuàng)建了一個空對象! 當我們錯誤地將greeting輸入為greetign時,JS解釋器實際上在瀏覽器中將其視為global.greetign={}(或window.greetign={})。
為了避免這種情況,我們可以使用“use strict”。 這可以確保在將變量賦值之前必須聲明變量。
function bark() {
console.log("Woof!");
}
bark.animal="dog";
復制代碼
答案
答案: A
這在JavaScript中是可能的,因為函數(shù)也是對象!(原始類型之外的所有東西都是對象)
函數(shù)是一種特殊類型的對象。您自己編寫的代碼并不是實際的函數(shù)。 該函數(shù)是具有屬性的對象,此屬性是可調(diào)用的。
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
您不能像使用常規(guī)對象那樣向構造函數(shù)添加屬性。 如果要一次向所有對象添加功能,則必須使用原型。 所以在這種情況下應該這樣寫:
Person.prototype.getFullName=function () {
return `${this.firstName} ${this.lastName}`;
}
復制代碼
這樣會使member.getFullName()是可用的,為什么樣做是對的? 假設我們將此方法添加到構造函數(shù)本身。 也許不是每個Person實例都需要這種方法。這會浪費大量內(nèi)存空間,因為它們?nèi)匀痪哂性搶傩裕@占用了每個實例的內(nèi)存空間。 相反,如果我們只將它添加到原型中,我們只需將它放在內(nèi)存中的一個位置,但它們都可以訪問它!
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
對于sarah,我們沒有使用new關鍵字。 使用new時,它指的是我們創(chuàng)建的新空對象。 但是,如果你不添加new它指的是全局對象!
我們指定了this.firstName等于'Sarah和this.lastName等于Smith。 我們實際做的是定義global.firstName='Sarah'和global.lastName='Smith。 sarah本身的返回值是undefined。
答案
答案: D
在捕獲階段,事件通過父元素向下傳遞到目標元素。 然后它到達目標元素,冒泡開始。
答案
答案: B
除基礎對象外,所有對象都有原型。 基礎對象可以訪問某些方法和屬性,例如.toString。 這就是您可以使用內(nèi)置JavaScript方法的原因! 所有這些方法都可以在原型上找到。 雖然JavaScript無法直接在您的對象上找到它,但它會沿著原型鏈向下尋找并在那里找到它,這使您可以訪問它。
譯者注:基礎對象指原型鏈終點的對象。基礎對象的原型是null。
function sum(a, b) {
return a + b;
}
sum(1, "2");
復制代碼
答案
答案: C
JavaScript是一種動態(tài)類型語言:我們沒有指定某些變量的類型。 在您不知情的情況下,值可以自動轉換為另一種類型,稱為隱式類型轉換。 強制從一種類型轉換為另一種類型。
在此示例中,JavaScript將數(shù)字1轉換為字符串,以使函數(shù)有意義并返回值。 在讓數(shù)字類型(1)和字符串類型('2')相加時,該數(shù)字被視為字符串。 我們可以連接像“Hello”+“World”這樣的字符串,所以這里發(fā)生的是“1”+“2”返回“12”。
let number=0;
console.log(number++);
console.log(++number);
console.log(number);
復制代碼
答案
答案: C
后綴一元運算符++:
前綴一元運算符++:
所以返回0 2 2。
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person="Lydia";
const age=21;
getPersonInfo`${person} is ${age} years old`;
復制代碼
答案
答案: B
如果使用標記的模板字符串,則第一個參數(shù)的值始終是字符串值的數(shù)組。 其余參數(shù)獲取傳遞到模板字符串中的表達式的值!
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 });
復制代碼
答案
答案: C
在比較相等性,原始類型通過它們的值進行比較,而對象通過它們的引用進行比較。JavaScript檢查對象是否具有對內(nèi)存中相同位置的引用。
我們作為參數(shù)傳遞的對象和我們用于檢查相等性的對象在內(nèi)存中位于不同位置,所以它們的引用是不同的。
這就是為什么{ age: 18 }==={ age: 18 }和 { age: 18 }=={ age: 18 } 返回 false的原因。
function getAge(...args) {
console.log(typeof args);
}
getAge(21);
復制代碼
答案
答案: C
擴展運算符(... args)返回一個帶參數(shù)的數(shù)組。 數(shù)組是一個對象,因此typeof args返回object。
function getAge() {
"use strict";
age=21;
console.log(age);
}
getAge();
復制代碼
答案
答案: C
使用“use strict”,可以確保不會意外地聲明全局變量。 我們從未聲明變量age,因為我們使用``use strict',它會引發(fā)一個ReferenceError。 如果我們不使用“use strict”,它就會起作用,因為屬性age`會被添加到全局對象中。
const sum=eval("10*10+5");
復制代碼
答案
答案: A
eval會為字符串傳遞的代碼求值。 如果它是一個表達式,就像在這種情況下一樣,它會計算表達式。 表達式為10 * 10 + 5計算得到105。
sessionStorage.setItem("cool_secret", 123);
復制代碼
答案
答案: B
關閉選項卡后,將刪除存儲在sessionStorage中的數(shù)據(jù)。
如果使用localStorage,數(shù)據(jù)將永遠存在,除非例如調(diào)用localStorage.clear()。
var num=8;
var num=10;
console.log(num);
復制代碼
答案
答案: B
使用var關鍵字,您可以用相同的名稱聲明多個變量。然后變量將保存最新的值。
您不能使用let或const來實現(xiàn)這一點,因為它們是塊作用域的。
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);
復制代碼
答案
答案: C
所有對象鍵(不包括Symbols)都會被存儲為字符串,即使你沒有給定字符串類型的鍵。 這就是為什么obj.hasOwnProperty('1')也返回true。
上面的說法不適用于Set。 在我們的Set中沒有“1”:set.has('1')返回false。 它有數(shù)字類型1,set.has(1)返回true。
const obj={ a: "one", b: "two", a: "three" };
console.log(obj);
復制代碼
答案
答案: C
如果對象有兩個具有相同名稱的鍵,則將替前面的鍵。它仍將處于第一個位置,但具有最后指定的值。
答案
答案: A
基本執(zhí)行上下文是全局執(zhí)行上下文:它是代碼中隨處可訪問的內(nèi)容。
for (let i=1; i < 5; i++) {
if (i===3) continue;
console.log(i);
}
復制代碼
答案
答案: C
如果某個條件返回true,則continue語句跳過迭代。
String.prototype.giveLydiaPizza=()=> {
return "Just give Lydia pizza already!";
};
const name="Lydia";
name.giveLydiaPizza();
復制代碼
答案
答案: A
String是一個內(nèi)置的構造函數(shù),我們可以為它添加屬性。 我剛給它的原型添加了一個方法。 原始類型的字符串自動轉換為字符串對象,由字符串原型函數(shù)生成。 因此,所有字符串(字符串對象)都可以訪問該方法!
譯者注:
當使用基本類型的字符串調(diào)用giveLydiaPizza時,實際上發(fā)生了下面的過程:
const a={};
const b={ key: "b" };
const c={ key: "c" };
a[b]=123;
a[c]=456;
console.log(a[b]);
復制代碼
答案
答案: B
對象鍵自動轉換為字符串。我們試圖將一個對象設置為對象a的鍵,其值為123。
但是,當對象自動轉換為字符串化時,它變成了[Object object]。 所以我們在這里說的是a["Object object"]=123。 然后,我們可以嘗試再次做同樣的事情。 c對象同樣會發(fā)生隱式類型轉換。那么,a["Object object"]=456。
然后,我們打印a[b],它實際上是a["Object object"]。 我們將其設置為456,因此返回456。
const foo=()=> console.log("First");
const bar=()=> setTimeout(()=> console.log("Second"));
const baz=()=> console.log("Third");
bar();
foo();
baz();
復制代碼
答案
答案: B
我們有一個setTimeout函數(shù)并首先調(diào)用它。 然而卻最后打印了它。
這是因為在瀏覽器中,我們不只有運行時引擎,我們還有一個叫做WebAPI的東西。WebAPI為我們提供了setTimeout函數(shù),例如DOM。
將callback推送到WebAPI后,setTimeout函數(shù)本身(但不是回調(diào)!)從堆棧中彈出。
現(xiàn)在,調(diào)用foo,并打印First。
foo從堆棧彈出,baz被調(diào)用,并打印Third。
WebAPI不能只是在準備就緒時將內(nèi)容添加到堆棧中。 相反,它將回調(diào)函數(shù)推送到一個稱為任務隊列的東西。
這是事件循環(huán)開始工作的地方。 事件循環(huán)查看堆棧和任務隊列。 如果堆棧為空,則會占用隊列中的第一個內(nèi)容并將其推送到堆棧中。
bar被調(diào)用,Second被打印,它從棧中彈出。
<div onclick="console.log('first div')">
<div onclick="console.log('second div')">
<button onclick="console.log('button')">
Click!
</button>
</div>
</div>
復制代碼
答案
答案: C
導致事件的最深嵌套元素是事件的目標。 你可以通過event.stopPropagation停止冒泡
<div onclick="console.log('div')">
<p onclick="console.log('p')">
Click here!
</p>
</div>
復制代碼
答案
答案: A
如果我們單擊p,我們會看到兩個日志:p和div。在事件傳播期間,有三個階段:捕獲,目標和冒泡。 默認情況下,事件處理程序在冒泡階段執(zhí)行(除非您將useCapture設置為true)。 它從最深的嵌套元素向外延伸。
const person={ name: "Lydia" };
function sayHi(age) {
console.log(`${this.name} is ${age}`);
}
sayHi.call(person, 21);
sayHi.bind(person, 21);
復制代碼
答案
答案: D
使用兩者,我們可以傳遞我們想要this關鍵字引用的對象。 但是,.call方法會立即執(zhí)行!
.bind方法會返回函數(shù)的拷貝值,但帶有綁定的上下文! 它不會立即執(zhí)行。
function sayHi() {
return (()=> 0)();
}
typeof sayHi();
復制代碼
答案
答案: B
sayHi函數(shù)返回立即調(diào)用的函數(shù)(IIFE)的返回值。 該函數(shù)返回0,類型為數(shù)字。
僅供參考:只有7種內(nèi)置類型:null,undefined,boolean,number,string,object和symbol。 function不是一個類型,因為函數(shù)是對象,它的類型是object。
0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
復制代碼
答案
答案: A
JavaScript中只有6個假值:
函數(shù)構造函數(shù),如new Number和new Boolean都是真值。
console.log(typeof typeof 1);
復制代碼
答案
答案: B
typeof 1 返回 "number". typeof "number" 返回 "string"
const numbers=[1, 2, 3];
numbers[10]=11;
console.log(numbers);
復制代碼
答案
答案: C
當你為數(shù)組中的元素設置一個超過數(shù)組長度的值時,JavaScript會創(chuàng)建一個名為“空插槽”的東西。 這些位置的值實際上是undefined,但你會看到類似的東西:
[1, 2, 3, 7 x empty, 11]
這取決于你運行它的位置(每個瀏覽器有可能不同)。
(()=> {
let x, y;
try {
throw new Error();
} catch (x) {
(x=1), (y=2);
console.log(x);
}
console.log(x);
console.log(y);
})();
復制代碼
答案
答案: A
catch塊接收參數(shù)x。當我們傳遞參數(shù)時,這與變量的x不同。這個變量x是屬于catch作用域的。
之后,我們將這個塊級作用域的變量設置為1,并設置變量y的值。 現(xiàn)在,我們打印塊級作用域的變量x,它等于1。
在catch塊之外,x仍然是undefined,而y是2。 當我們想在catch塊之外的console.log(x)時,它返回undefined,而y返回2。
答案
答案: A
JavaScript只有原始類型和對象。
原始類型是boolean,null,undefined,bigint,number,string和symbol。
[[0, 1], [2, 3]].reduce(
(acc, cur)=> {
return acc.concat(cur);
},
[1, 2]
);
復制代碼
答案
答案: C
[1,2]是我們的初始值。 這是我們開始執(zhí)行reduce函數(shù)的初始值,以及第一個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]。
!!null;
!!"";
!!1;
復制代碼
答案
答案: B
null是假值。 !null返回true。 !true返回false。
""是假值。 !""返回true。 !true返回false。
1是真值。 !1返回false。 !false返回true。
setInterval(()=> console.log("Hi"), 1000);
復制代碼
答案
答案: A
它返回一個唯一的id。 此id可用于使用clearInterval()函數(shù)清除該定時器。
[..."Lydia"];
復制代碼
答案
答案: A
字符串是可迭代的。 擴展運算符將迭代的每個字符映射到一個元素。
文中如有錯誤,歡迎在評論區(qū)指正,如果這篇文章幫助到了你,歡迎點贊和關注。
想閱讀更多優(yōu)質(zhì)文章、可關注我的github博客,你的star?、點贊和關注是我持續(xù)創(chuàng)作的動力!
github : https://github.com/ConardLi/ConardLi.github.io
原鏈接:https://juejin.im/post/5d0644976fb9a07ed064b0ca
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。