整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JavaScript 偵測手機瀏覽器的五種方法

          JavaScript 偵測手機瀏覽器的五種方法

          時候,前端網(wǎng)頁需要知道,用戶使用的是手機瀏覽器還是桌面瀏覽器。

          本文根據(jù) StackOverflow,整理了 JavaScript 偵測手機瀏覽器的五種方法。

          一、navigator.userAgent

          最簡單的方法就是分析瀏覽器的 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,window.innerWidth

          另一種方法是通過屏幕寬度,判斷是否為手機。

          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

          第三種方法是偵測屏幕方向,手機屏幕可以隨時改變方向(橫屏或豎屏),桌面設備做不到。

          window.orientation屬性用于獲取屏幕的當前方向,只有移動設備才有這個屬性,桌面設備會返回undefined。

          if (typeof window.orientation !== 'undefined') { // 當前設備是移動設備 }

          注意,iPhone 的 Safari 瀏覽器不支持該屬性。

          四、touch 事件

          第四種方法是,手機瀏覽器上的 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; } }

          五、window.matchMedia()

          最后一種方法是結合 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í)行,以后的代碼會是這三者的不同組合。

          分支語句

          1 語句

          如果說表達式(例如:num1+num2)是短語。

          語句就是完整的句子。(例如:sum=num1+num2;)

          表達式計算出來的是一個值,語句來執(zhí)行使某事情發(fā)生。

          例如:給一個學生的年齡,輸出這個學生是否成年了。

          如果 年齡大于等于18歲 輸出學生成年了。

          這里的成年了是否會輸出是有 年齡是否滿足決定的。

          JS在默認的就是從上到下一條條的執(zhí)行代碼語句。

          為使某事發(fā)生可能會改變語句的默認執(zhí)行順序。

          2 if語句

          格式:if(條件){

          條件為真實執(zhí)行的語句

          }

          JS解釋器會根據(jù)條件的結果決定是執(zhí)行還是跳過語句。

          讀法:如果 條件為真,執(zhí)行里面的代碼。為假掉過里面的代碼。

          //實踐:給一個學生的年齡,輸出這個學生是否成年了。
          //var age1=parseInt(prompt("請輸入一個學生的年齡:"));
           var age1=23;
           if(age1>=18){
              console.log("這個學生成年了。");
           }
           if(age1<18){
              console.log("這個學生沒有成年。");
           }

          分析一下,這里的判斷是一個事情的兩個方面?

          3 if-else語句

          格式:

          if(條件){條件為真,執(zhí)行的語句}

          else{條件為假(不為真),執(zhí)行的語句。}

          讀法:如果 條件為真 執(zhí)行為真的語句,否則執(zhí)行為假的語句

          //實踐:給一個學生的年齡,輸出這個學生是否成年了。
          // var age2=parseInt(prompt("請輸入一個學生的年齡:"));
          var age2=16;
          if(age2>=18){
          console.log("這個學生成年了。");
          }
          else{
          console.log("這個學生沒有成年。");
          }

          如果判斷學生的成績等級,會有很多的判斷。

          4 if-else if語句

          格式:

          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");}

          5 switch語句

          它是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;}
          

          6 三元運算符

          可以當成一種簡單的if-else語句。

          名字表示的三元運算符需要三個操作數(shù)。

          語法是:

          條件 ? 結果1 : 結果2;

          這里你把條件寫在問號上(?)的前面后面跟著用冒號(:)分隔的結果1和結果2。

          滿足條件時結果1否則結果2。





          這兩天的GitHub Trending repositories被一個名叫 javascript-questions的項目霸榜了,項目中記錄了一些JavaScript題目。



          我大概從頭到尾看了一遍,都是一些基礎的題目,我大概花了半個小時(有些題很簡單,可以一掃而過)把這些題做完了,雖然題目很簡單,但是每道題都對應一個知識點,如果這個知識點你沒有接觸過,那肯定會做錯,如果你接觸過這些知識點,那么這些題對你來說就很容易。

          建議大家也花半個小時來做一做,以便查漏補缺。

          為方便大家能夠更快的做題,而不把時間浪費在翻譯上,我又花了幾個小時把它們翻譯成了中文,當然已經(jīng)獲得了作者授權。


          文中有些點作者解釋的不太完整,為了更好的理解,我在文中添加了一些個人解釋。

          倉庫地址:https://github.com/lydiahallie/javascript-questions

          JavaScript 進階問題列表

          我在我的Instagram上發(fā)布了每日JavaScript選擇題,我也會在這里發(fā)布!

          從基礎到高級:測試您對JavaScript的了解程度,刷新您的知識,或為您的編碼面試做好準備! 我每周用新問題更新這個項目。

          答案位于問題下方的折疊部分,只需單擊它們即可展開。 祝你好運??


          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關鍵字聲明了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ū)”,在變量未初始化或賦值前不允許訪問。

          變量的賦值可以分為三個階段:

          • 創(chuàng)建變量,在內(nèi)存中開辟空間
          • 初始化變量,將變量初始化為undefined
          • 真正賦值

          關于let、var和function:

          • let 的「創(chuàng)建」過程被提升了,但是初始化沒有提升。
          • var 的「創(chuàng)建」和「初始化」都被提升了。
          • function 的「創(chuàng)建」「初始化」和「賦值」都被提升了。



          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í)行機制,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)的塊級作用域。



          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關鍵字指向是它所在上下文(定義時的位置)的環(huán)境,與普通函數(shù)不同! 這意味著當我們調(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類型轉換為數(shù)字類型。 true被轉換為1,false被轉換為0。

          字符串'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: All of them are valid

          答案


          答案: 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。




          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()是一個內(nèi)置的函數(shù)構造函數(shù)。 雖然它看起來像一個數(shù)字,但它并不是一個真正的數(shù)字:它有一堆額外的功能,是一個對象。

          當我們使用==運算符時,它只檢查它是否具有相同的值。 他們都有3的值,所以它返回true。

          譯者注:==會引發(fā)隱式類型轉換,右側的對象類型會自動拆箱為Number類型。

          然而,當我們使用===操作符時,類型和值都需要相等,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)建它們的構造函數(shù)中存在,并且不能傳遞給任何子級。 由于freddie是一個子級對象,函數(shù)不會傳遞,所以在freddie實例上不存在freddie方法:拋出TypeError。



          9. 下面代碼的輸出是什么?

          let greeting;
          greetign={}; // Typo!
          console.log(greetign);
          復制代碼
          • A: {}
          • B: ReferenceError: greetign is not defined
          • C: undefined

          答案


          答案: A

          控制臺會輸出空對象,因為我們剛剛在全局對象上創(chuàng)建了一個空對象! 當我們錯誤地將greeting輸入為greetign時,JS解釋器實際上在瀏覽器中將其視為global.greetign={}(或window.greetign={})。

          為了避免這種情況,我們可以使用“use strict”。 這可以確保在將變量賦值之前必須聲明變量。



          10. 當我們這樣做時會發(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中是可能的,因為函數(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ī)對象那樣向構造函數(shù)添加屬性。 如果要一次向所有對象添加功能,則必須使用原型。 所以在這種情況下應該這樣寫:

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

          這樣會使member.getFullName()是可用的,為什么樣做是對的? 假設我們將此方法添加到構造函數(shù)本身。 也許不是每個Person實例都需要這種方法。這會浪費大量內(nèi)存空間,因為它們?nèi)匀痪哂性搶傩裕@占用了每個實例的內(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關鍵字。 使用new時,它指的是我們創(chuàng)建的新空對象。 但是,如果你不添加new它指的是全局對象!

          我們指定了this.firstName等于'Sarah和this.lastName等于Smith。 我們實際做的是定義global.firstName='Sarah'和global.lastName='Smith。 sarah本身的返回值是undefined。



          12. 事件傳播的三個階段是什么??

          • A: 目標 > 捕獲 > 冒泡
          • B: 冒泡 > 目標 > 捕獲
          • C: 目標 > 冒泡 > 捕獲
          • D: 捕獲 > 目標 > 冒泡

          答案


          答案: D

          在捕獲階段,事件通過父元素向下傳遞到目標元素。 然后它到達目標元素,冒泡開始。



          13. 所有對象都有原型.

          • A: 對
          • B: 錯誤

          答案


          答案: B

          基礎對象外,所有對象都有原型。 基礎對象可以訪問某些方法和屬性,例如.toString。 這就是您可以使用內(nèi)置JavaScript方法的原因! 所有這些方法都可以在原型上找到。 雖然JavaScript無法直接在您的對象上找到它,但它會沿著原型鏈向下尋找并在那里找到它,這使您可以訪問它。

          譯者注:基礎對象指原型鏈終點的對象。基礎對象的原型是null。



          14. 下面代碼的輸出是什么?

          function sum(a, b) {
            return a + b;
          }
          
          sum(1, "2");
          復制代碼
          • A: NaN
          • B: TypeError
          • C: "12"
          • D: 3

          答案


          答案: C

          JavaScript是一種動態(tài)類型語言:我們沒有指定某些變量的類型。 在您不知情的情況下,值可以自動轉換為另一種類型,稱為隱式類型轉換。 強制從一種類型轉換為另一種類型。

          在此示例中,JavaScript將數(shù)字1轉換為字符串,以使函數(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

          后綴一元運算符++:

          1. 返回值(返回0)
          2. 增加值(數(shù)字現(xiàn)在是1)

          前綴一元運算符++:

          1. 增加值(數(shù)字現(xiàn)在是2)
          2. 返回值(返回2)

          所以返回0 2 2。



          16. 下面代碼的輸出是什么?

          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

          如果使用標記的模板字符串,則第一個參數(shù)的值始終是字符串值的數(shù)組。 其余參數(shù)獲取傳遞到模板字符串中的表達式的值!



          17. 下面代碼的輸出是什么?

          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

          在比較相等性,原始類型通過它們的值進行比較,而對象通過它們的引用進行比較。JavaScript檢查對象是否具有對內(nèi)存中相同位置的引用。

          我們作為參數(shù)傳遞的對象和我們用于檢查相等性的對象在內(nèi)存中位于不同位置,所以它們的引用是不同的。

          這就是為什么{ age: 18 }==={ age: 18 }和 { age: 18 }=={ age: 18 } 返回 false的原因。



          18. 下面代碼的輸出是什么?

          function getAge(...args) {
            console.log(typeof args);
          }
          
          getAge(21);
          復制代碼
          • A: "number"
          • B: "array"
          • C: "object"
          • D: "NaN"

          答案


          答案: C

          擴展運算符(... args)返回一個帶參數(shù)的數(shù)組。 數(shù)組是一個對象,因此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',它會引發(fā)一個ReferenceError。 如果我們不使用“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:永遠,數(shù)據(jù)不會丟失。
          • B:用戶關閉選項卡時。
          • C:當用戶關閉整個瀏覽器時,不僅是選項卡。
          • D:用戶關閉計算機時。

          答案


          答案: B

          關閉選項卡后,將刪除存儲在sessionStorage中的數(shù)據(jù)。

          如果使用localStorage,數(shù)據(jù)將永遠存在,除非例如調(diào)用localStorage.clear()。



          23. 下面代碼的輸出是什么?

          var num=8;
          var num=10;
          
          console.log(num);
          復制代碼
          • A: 8
          • B: 10
          • C: SyntaxError
          • D: ReferenceError

          答案


          答案: B

          使用var關鍵字,您可以用相同的名稱聲明多個變量。然后變量將保存最新的值。

          您不能使用let或const來實現(xiàn)這一點,因為它們是塊作用域的。



          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

          所有對象鍵(不包括Symbols)都會被存儲為字符串,即使你沒有給定字符串類型的鍵。 這就是為什么obj.hasOwnProperty('1')也返回true。

          上面的說法不適用于Set。 在我們的Set中沒有“1”:set.has('1')返回false。 它有數(shù)字類型1,set.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全局執(zhí)行上下文為你創(chuàng)建了兩個東西:全局對象和this關鍵字.

          • A: 對
          • B: 錯誤
          • C: 視情況而定

          答案


          答案: A

          基本執(zhí)行上下文是全局執(zhí)行上下文:它是代碼中隨處可訪問的內(nèi)容。



          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是一個內(nèi)置的構造函數(shù),我們可以為它添加屬性。 我剛給它的原型添加了一個方法。 原始類型的字符串自動轉換為字符串對象,由字符串原型函數(shù)生成。 因此,所有字符串(字符串對象)都可以訪問該方法!

          譯者注:

          當使用基本類型的字符串調(diào)用giveLydiaPizza時,實際上發(fā)生了下面的過程:

          • 創(chuàng)建一個String的包裝類型實例
          • 在實例上調(diào)用substring方法
          • 銷毀實例



          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

          對象鍵自動轉換為字符串。我們試圖將一個對象設置為對象a的鍵,其值為123。

          但是,當對象自動轉換為字符串化時,它變成了[Object object]。 所以我們在這里說的是a["Object object"]=123。 然后,我們可以嘗試再次做同樣的事情。 c對象同樣會發(fā)生隱式類型轉換。那么,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函數(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被打印,它從棧中彈出。



          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: div外部
          • B: div內(nèi)部
          • C: button
          • D: 所有嵌套元素的數(shù)組.

          答案


          答案: C

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



          32. 單擊下面的html片段打印的內(nèi)容是什么?

          <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,我們會看到兩個日志:p和div。在事件傳播期間,有三個階段:捕獲,目標和冒泡。 默認情況下,事件處理程序在冒泡階段執(zhí)行(除非您將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方法會立即執(zhí)行!

          .bind方法會返回函數(shù)的拷貝值,但帶有綁定的上下文! 它不會立即執(zhí)行。



          34. 下面代碼的輸出是什么?

          function sayHi() {
            return (()=> 0)();
          }
          
          typeof sayHi();
          復制代碼
          • A: "object"
          • B: "number"
          • C: "function"
          • D: "undefined"

          答案


          答案: B

          sayHi函數(shù)返回立即調(diào)用的函數(shù)(IIFE)的返回值。 該函數(shù)返回0,類型為數(shù)字。

          僅供參考:只有7種內(nèi)置類型:null,undefined,boolean,number,string,object和symbol。 function不是一個類型,因為函數(shù)是對象,它的類型是object。



          35. 下面這些值哪些是假值?

          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: 所有都是假值

          答案


          答案: A

          JavaScript中只有6個假值:

          • undefined
          • null
          • NaN
          • 0
          • '' (empty string)
          • false

          函數(shù)構造函數(shù),如new Number和new Boolean都是真值。



          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

          當你為數(shù)組中的元素設置一個超過數(shù)組長度的值時,JavaScript會創(chuàng)建一個名為“空插槽”的東西。 這些位置的值實際上是undefined,但你會看到類似的東西:

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

          這取決于你運行它的位置(每個瀏覽器有可能不同)。



          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塊接收參數(shù)x。當我們傳遞參數(shù)時,這與變量的x不同。這個變量x是屬于catch作用域的。

          之后,我們將這個塊級作用域的變量設置為1,并設置變量y的值。 現(xiàn)在,我們打印塊級作用域的變量x,它等于1。

          在catch塊之外,x仍然是undefined,而y是2。 當我們想在catch塊之外的console.log(x)時,它返回undefined,而y返回2。



          39. JavaScript中的所有內(nèi)容都是...

          • A:原始或對象
          • B:函數(shù)或對象
          • C:技巧問題!只有對象
          • D:數(shù)字或對象

          答案


          答案: 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]是我們的初始值。 這是我們開始執(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]。



          41. 下面代碼的輸出是什么?

          !!null;
          !!"";
          !!1;
          復制代碼
          • A: false true false
          • B: false false true
          • C: false true true
          • D: true true false

          答案


          答案: B

          null是假值。 !null返回true。 !true返回false。

          ""是假值。 !""返回true。 !true返回false。

          1是真值。 !1返回false。 !false返回true。



          42. setInterval方法的返回值什么?

          setInterval(()=> console.log("Hi"), 1000);
          復制代碼
          • A:一個唯一的id
          • B:指定的毫秒數(shù)
          • C:傳遞的函數(shù)
          • D:undefined

          答案


          答案: A

          它返回一個唯一的id。 此id可用于使用clearInterval()函數(shù)清除該定時器。



          43. 下面代碼的返回值是什么?

          [..."Lydia"];
          復制代碼
          • A: ["L", "y", "d", "i", "a"]
          • B: ["Lydia"]
          • C: [[], "Lydia"]
          • D: [["L", "y", "d", "i", "a"]]

          答案


          答案: A

          字符串是可迭代的。 擴展運算符將迭代的每個字符映射到一個元素。


          小結

          文中如有錯誤,歡迎在評論區(qū)指正,如果這篇文章幫助到了你,歡迎點贊和關注。

          想閱讀更多優(yōu)質(zhì)文章、可關注我的github博客,你的star?、點贊和關注是我持續(xù)創(chuàng)作的動力!


          github : https://github.com/ConardLi/ConardLi.github.io

          原鏈接:https://juejin.im/post/5d0644976fb9a07ed064b0ca


          主站蜘蛛池模板: 国产成人av一区二区三区在线观看| 国产精品一级香蕉一区| 国产在线无码视频一区二区三区| 中文字幕一区二区三| 亚洲AV无码一区二区乱孑伦AS| 亚洲日本va午夜中文字幕一区| 无码人妻精品一区二区三区久久| 成人中文字幕一区二区三区| 日韩一区二区在线免费观看| 国模精品一区二区三区| 国产日韩一区二区三区| 国产一区二区在线视频播放| 国产免费一区二区视频| 亚洲日韩一区二区一无码| 538国产精品一区二区在线| 无码人妻精品一区二区三区夜夜嗨| 亚洲AV无码一区二区三区久久精品 | 精品一区二区三区无码视频| 人妻少妇精品一区二区三区| 国产手机精品一区二区| V一区无码内射国产| 中文字幕无线码一区二区| 久久久久人妻一区精品果冻| 国产精品一级香蕉一区| 久久一区二区三区99| 亚洲一本一道一区二区三区| 韩国福利一区二区三区高清视频| 精品国产乱子伦一区二区三区| 丰满人妻一区二区三区视频| 乱精品一区字幕二区| 一区二区三区日本电影| 中文字幕无线码一区2020青青| 国产精品福利区一区二区三区四区| 亚洲国产系列一区二区三区| 中文字幕一区二区三区乱码| 日韩久久精品一区二区三区| 国产91大片精品一区在线观看| 果冻传媒一区二区天美传媒| 成人免费一区二区无码视频| 亚洲爆乳精品无码一区二区三区 | 蜜桃视频一区二区三区在线观看|