ES 新特性、異步、TypeScript


第1題

請說出下列代碼最終的執行結果,並解釋為什么?

var a = [];
for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); } } a[6]();

最終執行結果為:打印 10。

原因:for 循環時是使用 var 定義循環變量 i (存在變量提升),然后依次為 a 數組元素賦值為一個函數,函數內打印 i;循環結束后調用 a[6]() ,相當於在全局環境下打印 i,而此時 i 已經變為 10。

 

第2題

請說出下列代碼最終的執行結果,並解釋為什么?

var temp = 123; if (true) { console.log(tmp); let tmp; }

最終執行結果為:報出引用錯誤,在初始化之前不能訪問 'tmp'。

原因是因為,塊級作用域內使用了 let/const 關鍵字聲明變量,就存在暫時性死區,在聲明之前使用這些變量會報錯。
ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。

 

第3題

結合 ES6 新語法,用最簡單的方式找出數組中的最小值?

var arr = [12, 34, 32, 89, 4];

答案: Math.min(...arr)

 

第4題

請詳細說明 var,let,const 三種聲明變量的方式之間的具體差別?

1.使用var聲明變量

  • 存在變量提升的情況
  • 訪問在后續定義的變量會返回 undefined
  • var聲明的變量,可以在其他作用域訪問到

2.使用let聲明變量

  • 使用let命令,會創建一個塊級作用域
  • let聲明的變量只在塊級作用域內有效
  • 同個作用域里,使用let不能重復聲明變量

3.使用const聲明常量

  • 使用const聲明的常量不能被修改
  • 使用const聲明常量時就要賦值
  • 使用const聲明一個引用類型數據的常量,可以往這個常量上 增/刪/改 屬性,但是不能直接修改這個常量的值(內存地址不能修改)

 

第5題

請說出下列代碼最終的執行結果,並解釋為什么?

var a = 10; var obj = { a: 20, fn() { setTimeout(() => { console.log(this.a); }); } }; obj.fn();

最終執行結果為:打印出 20。

原因:setTimeout的回調是一個箭頭函數,箭頭函數不會改變this的指向。this始終指向沿着作用域往上找的第一個 function ,看這個 function 最終是怎樣調用的。題目里是這樣調用的 obj.fn() , 所以此時fn內的this指向obj。

 

第6題

簡述 Symbol 類型的用途?

Symbol 是 ES2015 提出的一種新的原始數據類型,主要用途有:

  • 為對象創建獨一無二的 key 值
  • 可以模擬實現對象的私有成員
  • 可以用作常量

 

第7題

說說什么是淺拷貝?什么是深拷貝?

引用類型的數據在賦值的過程中,其實是拷貝了內存地址,比如將b對象賦值給a變量,這兩個變量都指向了同一個內存地址,修改了a變量之后b對象也會跟着改變。而我們希望得到的是,修改a不會影響b,這兩個對象不會相互影響,針對這種場景就可以使用淺拷貝和深拷貝。

淺拷貝是指將對象的所有屬性值拷貝到新的對象,進行一層屬性的拷貝,但是如果屬性值也是對象的話,依舊是拷貝那個對象的地址,上面的問題還是會出現。這種情況就可以使用深拷貝來解決,即使屬性值是對象,深拷貝也可以做到無限層級拷貝,切斷兩個引用類型變量之間的關系,不會相互影響。

淺拷貝的方法:遍歷對象屬性賦值,Object.assign(),展開運算符...

深拷貝的方法:淺拷貝+遞歸,jsON.parse(jsON.stringify(obj))

JSON.parse(JSON.stringify())這個方法有一定的局限性:
序列化時遇到如下情況需要注意:

  • 時間對象 => 字符串的形式
  • RegExp,Error => {}
  • 會丟失 function,undefined
  • NaN,Infinity,-Infinity => null
  • 如果對象中存在循環引用的情況也無法實現深拷貝

終極深拷貝的方法可以參考 lodash 的深拷貝,不過日常開發如果沒遇到以上的情況,用 JSON.parse(JSON.stringify()) 足以...

 

第8題

談談你是如何理解 JS 異步編程的,EventLoop 是做什么的,什么是宏任務,什么是微任務?

js是單線程的,同一時間只能做一件事,兩段JS不能同時執行,主要原因是要避免DOM渲染的沖突。解決方案就是異步,而異步編寫的代碼,沒按照書寫方式執行,callback過多,導致可讀性很差,難以理解,所以就出現了 promise / async await。

EventLoop 指事件輪詢,是js實現異步的具體解決方案。同步代碼,在主線程(調用棧 Call stack)中直接執行,壓棧-彈棧。異步任務會依次放入消息隊列(Queue)中,EventLoop 會監聽調用棧和消息隊列,當調用棧中的代碼執行完之后,它會拿消息隊列中的第一個任務放到調用棧執行,以此類推。

異步任務可以分為宏任務和微任務,這兩個任務的執行順序不同。宏任務會依次放入消息隊列等待事件輪詢去執行,而微任務是放在本次調用棧的末尾去執行,也就是說,微任務比宏任務先執行。

  • 宏任務:目前大部分的異步調用都是作為宏任務執行
  • 微任務:Promise , MutationObserver , node 中 process.nextTick

 

第9題

將下面異步代碼使用 Promise 改進?

setTimeout(function () { var a = 'hello '; setTimeout(function () { var b = 'lagou '; setTimeout(function () { var c = 'I Love U'; console.log(a + b + c); }, 10); }, 10); }, 10);

答:

function task (msg) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(msg); }, 10); }); }; task('hello ') .then(msg => task(msg + 'lagou ')) .then(msg => task(msg + 'I Love U')) .then(msg => console.log(msg));

 

第10題

請簡述 TypeScript 與 JavaScript 之間的關系?

TypeScript 是 JavaScript 的一個超集(擴展集),就是在 JS 的基礎上多出一些擴展特性,這些擴展特性包括:強大的類型系統、對 ES6+ 的良好支持。TS 最終會被編譯為 JS 運行。

品牌vi設計公司http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com

第11題

請談談你所認為的 TypeScript 優缺點?

優點:

  1. 使用 TS 新特性開發項目,項目代碼的健壯性增強,代碼錯誤更早暴露。
  2. 編輯器支持情況良好,比如:VSCode,有很多智能提示,編碼更准確,提升開發效率。
  3. 使用 TS 的強類型特性來開發項目,可以使得項目代碼重構更牢靠。
  4. 使用 TS 的強類型特性來編寫代碼,可以減少很多不必要的類型判斷。
  5. TS 最終會被編譯為 JS 運行,可以將 ES6+ 編譯為ES5/ES3,兼容性好。
  6. TS 是漸進式的,完全可以使用 JS 編寫代碼,可以將新特性慢慢應用到項目中。

缺點:

  1. 引入了很多概念和新語法,有一定學習成本,對於一些小項目會增加開發成本
  2. 開發過程中遇到問題,可能相關 TS 的網上資料相比 JS 會少一些,需要花一些精力查找資料去解決問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM