[fed-task-01-01]ES 新特性、異步、TypeScript

簡答題

第1題

請說出下列代碼最終的執行結果,並解釋爲何?javascript

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

最終執行結果爲:打印 10。java

緣由:for 循環時是使用 var 定義循環變量 i (存在變量提高),而後依次爲 a 數組元素賦值爲一個函數,函數內打印 i;循環結束後調用 a[6]() ,至關於在全局環境下打印 i,而此時 i 已經變爲 10。node

第2題

請說出下列代碼最終的執行結果,並解釋爲何?編程

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

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

緣由是由於,塊級做用域內使用了 let/const 關鍵字聲明變量,就存在暫時性死區,在聲明以前使用這些變量會報錯。
ES6 明確規定,若是區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。promise

第3題

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

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

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

第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 運行。

第11題

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

優勢:

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

缺點:

  1. 引入了不少概念和新語法,有必定學習成本,對於一些小項目會增長開發成本
  2. 開發過程當中遇到問題,可能相關 TS 的網上資料相比 JS 會少一些,須要花一些精力查找資料去解決問題
相關文章
相關標籤/搜索