前端經典面試題 30道

題 1 :什麼是防抖和節流?有什麼區別?如何實現?

防抖:觸發高頻事件後n秒內函數只會執行一次,如果n秒內高頻事件再次被觸發,則重新計算時間

思路:每次觸發事件時都取消之前的延時調用方法

節流:高頻事件觸發,但在 n 秒內只會執行一次,所以節流會稀釋函數的執行頻率

思路:每次觸發事件時都判斷當前是否有等待執行的延時函數

 

題 2 :get請求傳參長度的誤區、get和post請求在緩存方面的區別

誤區:我們經常說get請求參數的大小存在限制,而post請求的參數大小是無限制的。

實際上 HTTP 協議從未規定 GET/POST 的請求長度限制是多少。對 get 請求參數的限制是來源與瀏覽器或 web 服務器,瀏覽器或 web 服務器限制了 url 的長度。爲了明確這個概念,我們必須再次強調下面幾點:

  • HTTP 協議未規定 GET 和 POST 的長度限制

  • GET 的最大長度顯示是因爲瀏覽器和 web 服務器限制了 URI 的長度

  • 不同的瀏覽器和 WEB 服務器,限制的最大長度不一樣

  • 要支持 IE,則最大長度爲 2083byte,若只支持 Chrome,則最大長度 8182byte

補充補充一個 get 和 post 在緩存方面的區別:

  • get 請求類似於查找的過程,用戶獲取數據,可以不用每次都與數據庫連接,所以可以使用緩存。

  • post 不同,post 做的一般是修改和刪除的工作,所以必須與數據庫交互,所以不能使用緩存。因此 get 請求適合於請求緩存。

 

題 3:模塊化發展歷程

可從IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、<script type="module"> 這幾個角度考慮。

模塊化主要是用來抽離公共代碼,隔離作用域,避免變量衝突等。

IIFE:使用自執行函數來編寫模塊化,特點:在一個單獨的函數作用域中執行代碼,避免變量衝突

AMD:使用 requireJS 來編寫模塊化,特點:提前聲明好

CMD:使用 seaJS 來編寫模塊化,特點:支持動態引入依文件

CommonJS:nodejs 中自帶的模塊化。

UMD:兼容 AMD,CommonJS 模塊化語法。

webpack(require.ensure):webpack 2.x 版本中的代碼分割。

ES Modules:ES6 引入的模塊化,支持 import 來引入另一個 js 。

 

題 4:npm 模塊安裝機制,爲什麼輸入 npm install 就可以自動安裝對應的模塊?

 1. npm 模塊安裝機制

  • 發出npm install命令

  • 查詢node_modules目錄之中是否已經存在指定模塊

    • 若存在,不再重新安裝

    • 若不存在

      • npm 向 registry 查詢模塊壓縮包的網址

      • 下載壓縮包,存放在根目錄下的.npm目錄裏

      • 解壓壓縮包到當前項目的node_modules目錄

2. npm 實現原理

輸入 npm install 命令並敲下回車後,會經歷如下幾個階段(以 npm 5.5.1 爲例):

  • 執行工程自身 preinstall

當前 npm 工程如果定義了 preinstall 鉤子此時會被執行。

  • 確定首

首先需要做的是確定工程中的首層依賴,也就是 dependencies 和 devDependencies 屬性中直接指定的模塊(假設此時沒有添加 npm install 參數)。

工程本身是整棵依賴樹的根節點,每個首層依賴模塊都是根節點下面的一棵子樹,npm 會開啓多進程從每個首層依賴模塊開始逐步尋找更深層級的節點。

  • 獲取模塊

    獲取模塊是一個遞歸的過程,分爲以下幾步:

 

    • 獲取模塊信息。在下載一個模塊之前,首先要確定其版本,這是因爲 package.json 中往往是 semantic version(semver,語義化版本)。此時如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有該模塊信息直接拿即可,如果沒有則從倉庫獲取。如 packaeg.json 中某個包的版本是 ^1.1.0,npm 就會去倉庫中獲取符合 1.x.x 形式的最新版本。

    • 獲取模塊實體。上一步會獲取到模塊的壓縮包地址(resolved 字段),npm 會用此地址檢查本地緩存,緩存中有就直接拿,如果沒有則從倉庫下載。

    • 查找該模塊依賴,如果有依賴則回到第1步,如果沒有則停止。

  • 扁平化(dedupe

上一步獲取到的是一棵完整的依賴樹,其中可能包含大量重複模塊。比如 A 模塊依賴於 loadsh,B 模塊同樣依賴於 lodash。在 npm3 以前會嚴格按照依賴樹的結構進行安裝,因此會造成模塊冗餘。

從 npm3 開始默認加入了一個 dedupe的過程。它會遍歷所有節點,逐個將模塊放在根節點下面,也就是 node-modules 的第一層。當發現有重複模塊時,則將其丟棄。

這裏需要對重複模塊進行一個定義,它指的是模塊名相同且 semver兼容。每個 semver 都對應一段版本允許範圍,如果兩個模塊的版本允許範圍存在交集,那麼就可以得到一個兼容版本,而不必版本號完全一致,這可以使更多冗餘模塊在 dedupe 過程中被去掉。

比如 node-modules 下 foo 模塊依賴 lodash@^1.0.0,bar 模塊依賴 lodash@^1.1.0,則 ^1.1.0 爲兼容版本。

而當 foo 依賴 lodash@^2.0.0,bar 依賴 lodash@^1.1.0,則依據 semver 的規則,二者不存在兼容版本。會將一個版本放在 node_modules 中,另一個仍保留在依賴樹裏。

  • 安裝模

這一步將會更新工程中的 node_modules,並執行模塊中的生命週期函數(按照 preinstall、install、postinstall 的順序)。

  • 執行工程自身生命周

當前 npm 工程如果定義了鉤子此時會被執行(按照 install、postinstall、prepublish、prepare 的順序)。

最後一步是生成或更新版本描述文件,npm install 過程完成。

 

題 5:ES5 的繼承和 ES6 的繼承有什麼區別?

ES5的繼承時通過prototype或構造函數機制來實現。ES5的繼承實質上是先創建子類的實例對象,然後再將父類的方法添加到this上(Parent.apply(this))。

ES6的繼承機制完全不同,實質上是先創建父類的實例對象this(所以必須先調用父類的super()方法),然後再用子類的構造函數修改this

具體的:ES6通過class關鍵字定義類,裏面有構造方法,類之間通過extends關鍵字實現繼承。子類必須在constructor方法中調用super方法,否則新建實例報錯。因爲子類沒有自己的this對象,而是繼承了父類的this對象,然後對其進行加工。如果不調用super方法,子類得不到this對象。

ps:super關鍵字指代父類的實例,即父類的this對象。在子類構造函數中,調用super後,纔可使用this關鍵字,否則報錯。

 

題 6:setTimeout、Promise、Async/Await 的區別

移步此處查看答案

https://gongchenghuigch.github.io/2019/09/14/awat/

 

題 7:定時器的執行順序或機制?

因爲js是單線程的,瀏覽器遇到setTimeout或者setInterval會先執行完當前的代碼塊,在此之前會把定時器推入瀏覽器的待執行事件隊列裏面,等到瀏覽器執行完當前代碼之後會看一下事件隊列裏面有沒有任務,有的話才執行定時器的代碼。所以即使把定時器的時間設置爲0還是會先執行當前的一些代碼。

輸出結果:

 

題 8:

['1','2','3'].map(parseInt) 輸出什麼,爲什麼?

 

輸出:[1, NaN, NaN]

  • 首先讓我們回顧一下,map 函數的第一個參數 callback:

var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])

這個 callback 一共可以接收三個參數,其中第一個參數代表當前被處理的元素,而第二個參數代表該元素的索引。

而 parseInt 則是用來解析字符串的,使字符串成爲指定基數的整數。

parseInt(string, radix)

接收兩個參數,第一個表示被處理的值(字符串),第二個表示爲解析時的基數。

  • 瞭解這兩個函數後,我們可以模擬一下運行情況

  1. parseInt('1', 0) //radix爲0時,且string參數不以“0x”和“0”開頭時,按照 10 爲基數處理。這個時候返回 1

  2. parseInt('2', 1) //基數爲1(1進制)表示的數中,最大值小於2,所以無法解析,返回NaN

  3. parseInt('3', 2) //基數爲 2(2進制)表示的數中,最大值小於 3,所以無法解析,返回 NaN

  • map 函數返回的是一個數組,所以最後結果爲[1, NaN, NaN]

     

題 9:Doctype 作用? 嚴格模式與混雜模式如何區分?它們有何意義?

Doctype聲明於文檔最前面,告訴瀏覽器以何種方式來渲染頁面,這裏有兩種模式,嚴格模式和混雜模式。

  • 嚴格模式的排版和 JS 運作模式是 以該瀏覽器支持的最高標準運行。

  • 混雜模式,向後兼容,模擬老式瀏覽器,防止瀏覽器無法兼容頁面。

題 10:fetch 發送 2 次請求的原因

fetch 發送 post 請求的時候,總是發送 2 次,第一次狀態碼是 204,第二次才成功?

原因很簡單,因爲你用fetch的post請求的時候,導致fetch 第一次發送了一個Options請求,詢問服務器是否支持修改的請求頭,如果服務器支持,則在第二次中發送真正的請求。

 

題 11 :TCP 三次握手和四次揮手

三次握手之所以是三次是保證 client 和 server 均讓對方知道自己的接收和發送能力沒問題而保證的最小次數。

第一次 client => server 只能 server 判斷出 client 具備發送能力
第二次 server => client client 就可以判斷出 server 具備發送和接受能力。此時 client 還需讓 server 知道自己接收能力沒問題於是就有了第三次
第三次 client => server 雙方均保證了自己的接收和發送能力沒有問題

其中,爲了保證後續的握手是爲了應答上一個握手,每次握手都會帶一個標識 seq,後續的 ACK 都會對這個 seq 進行加一來進行確認。

 

題 12 :img iframe script 來發送跨域請求有什麼優缺點?

  • iframe

優點:跨域完畢之後 DOM 操作和互相之間的 JavaScript 調用都是沒有問題的

缺點:1.若結果要以 URL 參數傳遞,這就意味着在結果數據量很大的時候需要分割傳遞,巨煩。2.還有一個是 iframe 本身帶來的,母頁面和 iframe 本身的交互本身就有安全性限制。

  • script

優點:可以直接返回 json 格式的數據,方便處理

缺點:只接受 GET 請求方式

  • 圖片ping

優點:可以訪問任何 url,一般用來進行點擊追蹤,做頁面分析常用的方法

缺點:不能訪問響應文本,只能監聽是否響應

題 13:Cookie、sessionStorage、localStorage 的區別

共同點:都是保存在瀏覽器端,並且是同源的

  • Cookie:cookie數據始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和服務器間來回傳遞。而sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存。cookie數據還有路徑(path)的概念,可以限制cookie只屬於某個路徑下,存儲的大小很小隻有4K左右。(key:可以在瀏覽器和服務器端來回傳遞,存儲容量小,只有大約4K左右)

  • sessionStorage:僅在當前瀏覽器窗口關閉前有效,自然也就不可能持久保持,localStorage:始終有效,窗口或瀏覽器關閉也一直保存,因此用作持久數據;cookie只在設置的cookie過期時間之前一直有效,即使窗口或瀏覽器關閉。(key:本身就是一個回話過程,關閉瀏覽器後消失,session爲一個回話,當頁面不同即使是同一頁面打開兩次,也被視爲同一次回話)

  • localStorage:localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。(key:同源窗口都會共享,並且不會失效,不管窗口或者瀏覽器關閉與否都會始終生效)

題 14:Cookie 如何防範 XSS 攻擊

XSS(跨站腳本攻擊)是指攻擊者在返回的HTML中嵌入javascript腳本,爲了減輕這些攻擊,需要在HTTP頭部配上,set-cookie:

  • httponly-這個屬性可以防止XSS,它會禁止javascript腳本來訪問cookie。

  • secure - 這個屬性告訴瀏覽器僅在請求爲https的時候發送cookie。

結果應該是這樣的:Set-Cookie=...

題 15:瀏覽器和 Node 事件循環的區別?

其中一個主要的區別在於瀏覽器的 event loop 和 nodejs 的 event loop 在處理異步事件的順序是不同的,nodejs 中有 micro event;其中Promise屬於micro event 該異步事件的處理順序就和瀏覽器不同.nodejs V11.0以上 這兩者之間的順序就相同了。

題 16:簡述 HTTPS 中間人攻擊

HTTPS 協議由 HTTP + SSL 協議構成,具體的鏈接過程可參考SSL或TLS握手的概述https://github.com/lvwxx/blog/issues/3

中間人攻擊過程如下:

  1. 服務器向客戶端發送公鑰。

  2. 攻擊者截獲公鑰,保留在自己手上。

  3. 然後攻擊者自己生成一個【僞造的】公鑰,發給客戶端。

  4. 客戶端收到僞造的公鑰後,生成加密hash值發給服務器。

  5. 攻擊者獲得加密hash值,用自己的私鑰解密獲得真祕鑰。

  6. 同時生成假的加密hash值,發給服務器。

  7. 服務器用私鑰解密獲得假祕鑰。

  8. 服務器用加祕鑰加密傳輸信息

防範方法:服務端在發送瀏覽器的公鑰中加入 CA 證書,瀏覽器可以驗證 CA 證書的有效性。

題 17:說幾條 Web 前端優化策略

(1) 減少 HTTP 請求數

(2) 從設計實現層面簡化頁面

(3) 合理設置 HTTP 緩存

(4) 資源合併與壓縮

(5) CSS Sprites

(6) Inline Images

(7) Lazy Load Images

題 18:你瞭解的瀏覽器的重繪和迴流導致的性能問題

重繪(Repaint)和迴流(Reflow)

重繪和迴流是渲染步驟中的一小節,但是這兩個步驟對於性能影響很大。

  • 重繪是當節點需要更改外觀而不會影響佈局的,比如改變 color就叫稱爲重繪

  • 迴流是佈局或者幾何屬性需要改變就稱爲迴流。

迴流必定會發生重繪,重繪不一定會引發迴流。迴流所需的成本比重繪高的多,改變深層次的節點很可能導致父節點的一系列迴流。

所以以下幾個動作可能會導致性能問題:

  • 改變 window 大小

  • 改變字體

  • 添加或刪除樣式

  • 文字改變

  • 定位或者浮動

  • 盒模型

很多人不知道的是,重繪和迴流其實和 Event loop 有關。

  1. 當 Event loop 執行完 Microtasks 後,會判斷 document 是否需要更新。因爲瀏覽器是 60Hz 的刷新率,每 16ms 纔會更新一次。

  2. 然後判斷是否有 resize或者 scroll,有的話會去觸發事件,所以 resize和 scroll事件也是至少 16ms 纔會觸發一次,並且自帶節流功能。

  3. 判斷是否觸發了 media query

  4. 更新動畫並且發送事件

  5. 判斷是否有全屏操作事件

  6. 執行 requestAnimationFrame回調

  7. 執行 IntersectionObserver回調,該方法用於判斷元素是否可見,可以用於懶加載上,但是兼容性不好

  8. 更新界面

  9. 以上就是一幀中可能會做的事情。如果在一幀中有空閒時間,就會去執行 requestIdleCallback回調。

減少重繪和迴流

  • 使用 translate 替代 top

    
     

    <div class="test"></div>
    <style>
    .test {
    position: absolute;
    top: 10px;
    width: 100px;
    height: 100px;
    background: red;
    }
    </style>
    <script>
    setTimeout(() => {
    // 引起迴流
    document.querySelector('.test').style.top = '100px'
    }, 1000)
    </script>

  • 使用 visibility替換 display: none,因爲前者只會引起重繪,後者會引發迴流(改變了佈局)

    把 DOM 離線後修改,比如:先把 DOM 給 display:none(有一次 Reflow),然後你修改100次,然後再把它顯示出來

    不要把 DOM 結點的屬性值放在一個循環裏當成循環裏的變量

    
     

    for(let i = 0; i < 1000; i++) {
    // 獲取 offsetTop 會導致迴流,因爲需要去獲取正確的值
    console.log(document.querySelector('.test').style.offsetTop)
    }

  • 不要使用 table 佈局,可能很小的一個小改動會造成整個 table 的重新佈局

  • 動畫實現的速度的選擇,動畫速度越快,迴流次數越多,也可以選擇使用 requestAnimationFrame

  • CSS 選擇符從右往左匹配查找,避免 DOM 深度過深

  • 將頻繁運行的動畫變爲圖層,圖層能夠阻止該節點回流影響別的元素。比如對於 video標籤,瀏覽器會自動將該節點變爲圖層。

題 19:寫 React / Vue 項目時爲什麼要在列表組件中寫 key,其作用是什麼?

 

vue 和 react 都是採用 diff 算法來對比新舊虛擬節點,從而更新節點。在 vue 的 diff函數中(建議先了解一下 diff 算法過程)。

在交叉對比中,當新節點跟舊節點頭尾交叉對比沒有結果時,會根據新節點的 key 去對比舊節點數組中的 key,從而找到相應舊節點(這裏對應的是一個 key => index 的 map 映射)。如果沒找到就認爲是一個新增節點。而如果沒有 key,那麼就會採用遍歷查找的方式去找到對應的舊節點。一種一個 map 映射,另一種是遍歷查找。相比而言,map 映射的速度更快。

題 20:React 中 setState 什麼時候是同步的,什麼時候是異步的?

在React中,如果是由React引發的事件處理(比如通過onClick引發的事件處理),調用setState不會同步更新this.state,除此之外的setState調用會同步執行this.state。所謂“除此之外”,指的是繞過React通過addEventListener直接添加的事件處理函數,還有通過setTimeout/setInterval產生的異步調用。

原因:在 React 的 setState 函數實現中,會根據一個變量isBatchingUpdates 判斷是直接更新 this.state 還是放到隊列中回頭再說,而 isBatchingUpdates 默認是 false,也就表示 setState 會同步更新 this.state,但是,有一個函數 batchedUpdates,這個函數會把 isBatchingUpdates 修改爲 true,而當 React 在調用事件處理函數之前就會調用這個 batchedUpdates,造成的後果,就是由 React 控制的事件處理過程 setState 不會同步更新  this.state

題 21:爲什麼虛擬 dom 會提高性能?

虛擬 dom 相當於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法避免了沒有必要的 dom 操作,從而提高性能。

具體實現步驟如下:

1. 用 JavaScript 對象結構表示 DOM 樹的結構;然後用這個樹構建一個真正的 DOM 樹,插到文檔當中。

2. 當狀態變更的時候,重新構造一棵新的對象樹。然後用新的樹和舊的樹進行比較,記錄兩棵樹差異。

把 2 所記錄的差異應用到步驟 1 所構建的真正的DOM樹上,視圖就更新了。

題 22:清除浮動的方式有哪些?比較好的是哪一種?

常用的一般爲三種:

.clearfixclear:both,overflow:hidden

比較好是 .clearfix,僞元素萬金油版本,後兩者有侷限性。

clear:both:若是用在同一個容器內相鄰元素上,那是賊好的,有時候在容器外就有些問題了, 比如相鄰容器的包裹層元素塌陷

overflow:hidden:這種若是用在同個容器內,可以形成 BFC避免浮動造成的元素塌陷

題 23:分析比較 opacity: 0、visibility: hidden、display: none 優劣和適用場景

結構:

display:none: 會讓元素完全從渲染樹中消失,渲染的時候不佔據任何空間, 不能點擊,

visibility: hidden:不會讓元素從渲染樹消失,渲染元素繼續佔據空間,只是內容不可見,不能點擊
opacity: 0: 不會讓元素從渲染樹消失,渲染元素繼續佔據空間,只是內容不可見,可以點擊

繼承:

display: none和opacity: 0:是非繼承屬性,子孫節點消失由於元素從渲染樹消失造成,通過修改子孫節點屬性無法顯示。
visibility: hidden:是繼承屬性,子孫節點消失由於繼承了hidden,通過設置visibility: visible;可以讓子孫節點顯式。

性能:

displaynone : 修改元素會造成文檔迴流,讀屏器不會讀取display: none元素內容,性能消耗較大
visibility:hidden: 修改元素只會造成本元素的重繪,性能消耗較少讀屏器讀取visibility: hidden元素內容
opacity: 0 :修改元素會造成重繪,性能消耗較少

聯繫:它們都能讓元素不可見

題 24:css sprite 是什麼,有什麼優缺點

概念:將多個小圖片拼接到一個圖片中。通過 background-position 和元素尺寸調節需要顯示的背景圖案。

優點:

  1. 減少 HTTP 請求數,極大地提高頁面加載速度

  2. 增加圖片信息重複度,提高壓縮比,減少圖片大小

  3. 更換風格方便,只需在一張或幾張圖片上修改顏色或樣式即可實現

缺點:

  1. 圖片合併麻煩

  2. 維護麻煩,修改一個圖片可能需要重新佈局整個圖片,樣式

題 25:link 與 @import 的區別

  1. link是 HTML 方式, @import是 CSS 方式

  2. link最大限度支持並行下載,@import過多嵌套導致串行下載,出現FOUC

  3. link可以通過rel="alternate stylesheet"指定候選樣式

  4. 瀏覽器對link支持早於@import,可以使用@import對老瀏覽器隱藏樣式

  5. @import必須在樣式規則之前,可以在 css 文件中引用其他文件

  6. 總體來說:link 優於@import

 

題 26:容器包含若干浮動元素時如何清理浮動

  1. 容器元素閉合標籤前添加額外元素並設置clear: both

  2. 父元素觸發塊級格式化上下文(見塊級可視化上下文部分)

  3. 設置容器元素僞元素進行清理推薦的清理浮動方法

 

題 27:display,float,position 的關係

  1. 如果display爲 none,那麼 position 和 float 都不起作用,這種情況下元素不產生框。

  2. 否則,如果 position 值爲 absolute 或者 fixed,框就是絕對定位的,float 的計算值爲 none,display 根據下面的表格進行調整。

  3. 否則,如果 float 不是 none,框是浮動的,display 根據下表進行調整。

  4. 否則,如果元素是根元素,display 根據下表進行調整。

  5. 其他情況下 display 的值爲指定值 總結起來:絕對定位、浮動、根元素都需要調整display。

題 28:JS 的四種設計模式

工廠模式:簡單的工廠模式可以理解爲解決多個相似的問題;

單例模式:只能被實例化(構造函數給實例添加屬性與方法)一次;

沙箱模式:將一些函數放到自執行函數裏面,但要用閉包暴露接口,用變量接收暴露的接口,再調用裏面的值,否則無法使用裏面的值;

發佈者訂閱模式:就例如如我們關注了某一個公衆號,然後他對應的有新的消息就會給你推送,代碼實現邏輯是用數組存儲訂閱者, 發佈者回調函數裏面通知的方式是遍歷訂閱者數組,並將發佈者內容傳入訂閱者數組。

 29:下面代碼的輸出是什麼?


 

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

 true true false true

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

上面的說法不適用於Set。在我們的Set中沒有“1”set.has('1')返回false。它有數字類型1set.has(1)返回true

 30:下面代碼的輸出是什麼?


 

// example 1
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]);

---------------------
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);

---------------------
// example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
a[c]='c';
console.log(a[b]);

這題考察的是對象的鍵名的轉換。

  • 對象的鍵名只能是字符串和 Symbol 類型。

  • 其他類型的鍵名會被轉換成字符串類型。

  • 對象轉字符串默認會調用 toString 方法。


 

// example 1
var a={}, b='123', c=123;
a[b]='b';
// c 的鍵名會被轉換成字符串'123',這裏會把 b 覆蓋掉。
a[c]='c';
// 輸出 c
console.log(a[b]);


// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
// b 是 Symbol 類型,不需要轉換。
a[b]='b';
// c 是 Symbol 類型,不需要轉換。任何一個 Symbol 類型的值都是不相等的,所以不會覆蓋掉 b。
a[c]='c';
// 輸出 b
console.log(a[b]);


// example 3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章