2020-03

Q1:什么是防抖和節(jié)流?有什么區(qū)別?如何實現(xiàn)?

防抖:觸發(fā)高頻事件后n秒內(nèi)函數(shù)只會執(zhí)行一次,如果n秒內(nèi)高頻事件再次被觸發(fā),則重新計算時間。實現(xiàn)原理就是利用定時器,函數(shù)第一次執(zhí)行時設(shè)定一個定時器,之后調(diào)用時發(fā)現(xiàn)已經(jīng)設(shè)定過定時器就清空之前的定時器祝钢,并重新設(shè)定一個新的定時器疤估,如果存在沒有被清空的定時器慷荔,當(dāng)定時器計時結(jié)束后觸發(fā)函數(shù)執(zhí)行磷雇。

function debounce(fn) {
      let timeout = null; // 創(chuàng)建一個標(biāo)記用來存放定時器的返回值
      return function () {
        clearTimeout(timeout); // 每當(dāng)用戶輸入的時候把前一個 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又創(chuàng)建一個新的 setTimeout, 這樣就能保證輸入字符后的 interval 間隔內(nèi)如果還有字符輸入的話躏救,就不會執(zhí)行 fn 函數(shù)
          fn.apply(this, arguments);
        }, 500);
      };
    }
    function sayHi() {
      console.log('防抖成功');
    }

    var inp = document.getElementById('inp');
    inp.addEventListener('input', debounce(sayHi)); // 防抖

節(jié)流:函數(shù)節(jié)流指的是某個函數(shù)在一定時間間隔內(nèi)(例如 3 秒)只執(zhí)行一次尿庐,在這 3 秒內(nèi) 無視后來產(chǎn)生的函數(shù)調(diào)用請求,也不會延長時間間隔皮假。3 秒間隔結(jié)束后第一次遇到新的函數(shù)調(diào)用會觸發(fā)執(zhí)行惹资,然后在這新的 3 秒內(nèi)依舊無視后來產(chǎn)生的函數(shù)調(diào)用請求猴誊,以此類推。

function throttle(fn) {
      let canRun = true; // 通過閉包保存一個標(biāo)記
      return function () {
        if (!canRun) return; // 在函數(shù)開頭判斷標(biāo)記是否為true,不為true則return
        canRun = false; // 立即設(shè)置為false
        setTimeout(() => { // 將外部傳入的函數(shù)的執(zhí)行放在setTimeout中
          fn.apply(this, arguments);
          // 最后在setTimeout執(zhí)行完畢后再把標(biāo)記設(shè)置為true(關(guān)鍵)表示可以執(zhí)行下一次循環(huán)了卫漫。當(dāng)定時器沒有執(zhí)行的時候標(biāo)記永遠(yuǎn)是false辫塌,在開頭被return掉
          canRun = true;
        }, 500);
      };
    }
    function sayHi(e) {
      console.log(e.target.innerWidth, e.target.innerHeight);
    }
    window.addEventListener('resize', throttle(sayHi));

節(jié)流的例子:eshop滾動的時候監(jiān)聽頁面是否滾動到所處的高度值持隧。

Q2:介紹下 Set只酥、Map、WeakSet 和 WeakMap 的區(qū)別

Set 和 Map 主要的應(yīng)用場景在于 數(shù)據(jù)重組 和 數(shù)據(jù)儲存呀狼。Set 是一種叫做集合的數(shù)據(jù)結(jié)構(gòu)裂允,Map 是一種叫做字典的數(shù)據(jù)結(jié)構(gòu).Set是一種構(gòu)造函數(shù)。

image.png

比較相等的方法是'Same-value-zero equality'哥艇。
WeakSet 對象允許你將弱引用對象儲存在一個集合中绝编。
WeakSet 只能儲存對象引用,不能存放值,而 Set 對象都可以
WeakSet 對象中儲存的對象值都是被弱引用的十饥,即垃圾回收機(jī)制不考慮 WeakSet 對該對象的應(yīng)用怎棱,如果沒有其他的變量或?qū)傩砸眠@個對象值,則這個對象將會被垃圾回收掉(不考慮該對象還存在于 WeakSet 中)绷跑,所以拳恋,WeakSet 對象里有多少個成員元素,取決于垃圾回收機(jī)制有沒有運行砸捏,運行前后成員個數(shù)可能不一致谬运,遍歷結(jié)束之后,有的成員可能取不到了(被垃圾回收了)垦藏,WeakSet 對象是無法被遍歷的(ES6 規(guī)定 WeakSet 不可遍歷)梆暖,也沒有辦法拿到它包含的所有元素。(看起來沒啥用)
Map
共同點:集合掂骏、字典 可以儲存不重復(fù)的值
不同點:集合 是以 [value, value]的形式儲存元素轰驳,字典 是以 [key, value] 的形式儲存。

const map = new Map();

map.set(['a'], 555);
map.get(['a']) // undefined

Map 的鍵實際上是跟內(nèi)存地址綁定的弟灼,只要內(nèi)存地址不一樣级解,就視為兩個鍵。
WeakMap 對象是一組鍵值對的集合田绑,其中的鍵是弱引用對象勤哗,而值可以是任意。
注意掩驱,WeakMap 弱引用的只是鍵名芒划,而不是鍵值。鍵值依然是正常引用欧穴。
Set
成員唯一民逼、無序且不重復(fù)
[value, value],鍵值與鍵名是一致的(或者說只有鍵值涮帘,沒有鍵名)
可以遍歷拼苍,方法有:add、delete焚辅、has
WeakSet
成員都是對象
成員都是弱引用映屋,可以被垃圾回收機(jī)制回收,可以用來保存DOM節(jié)點同蜻,不容易造成內(nèi)存泄漏
不能遍歷,方法有add早处、delete湾蔓、has
Map
本質(zhì)上是鍵值對的集合,類似集合
可以遍歷砌梆,方法很多可以跟各種數(shù)據(jù)格式轉(zhuǎn)換
WeakMap
只接受對象作為鍵名(null除外)默责,不接受其他類型的值作為鍵名
鍵名是弱引用贬循,鍵值可以是任意的,鍵名所指向的對象可以被垃圾回收桃序,此時鍵名是無效的
不能遍歷杖虾,方法有g(shù)et、set媒熊、has奇适、delete

Q3: Async/Await 如何通過同步的方式實現(xiàn)異步

async/await 是參照 Generator 封裝的一套異步處理方案,可以理解為 Generator 的語法糖芦鳍。而 Generator 又依賴于迭代器Iterator嚷往,而 Iterator 的思想呢又來源于單向鏈表。

鏈表是一種線性表柠衅,但是并不會按線性的順序儲存數(shù)據(jù)皮仁,而是在每一個節(jié)點里存到下一個節(jié)點的指針。
單向鏈表的思想: 鏈表中最簡單的一種菲宴,它包含兩個域贷祈,一個信息域和一個指針域。這個鏈接指向列表中的下一個節(jié)點喝峦,而最后一個節(jié)點則指向一個空值付燥。
迭代器協(xié)議:產(chǎn)生一個有限或無限序列的值,并且當(dāng)所有的值都已經(jīng)被迭代后愈犹,就會有一個默認(rèn)的返回值键科。一個對象要變成可迭代的,必須實現(xiàn) @@iterator 方法漩怎,即對象(或它原型鏈上的某個對象)必須有一個名字是 Symbol.iterator 的屬性

const returnData = arr => {
let nextIndex = 0;
return {
next: nextIndex < arr.length 
  ? {value: arr[nextIndex++], done: false}
   : {value:undefined, done: true}
}
}
const arr = ['星月','神話']
const it = returnData(arr);
it.next() --> 星月
it.next() ---> 神話

調(diào)用一個生成器函數(shù)并不會馬上執(zhí)行它里面的語句勋颖,而是返回一個這個生成器的迭代器對象,當(dāng)這個迭代器的 next() 方法被首次(后續(xù))調(diào)用時勋锤,其內(nèi)的語句會執(zhí)行到第一個(后續(xù))出現(xiàn) yield 的位置為止(讓執(zhí)行處于暫停狀)饭玲,yield 后緊跟迭代器要返回的值∪矗或者如果用的是 yield*(多了個星號)茄厘,則表示將執(zhí)行權(quán)移交給另一個生成器函數(shù)(當(dāng)前生成器暫停執(zhí)行),調(diào)用 next() (再啟動)方法時谈宛,如果傳入了參數(shù)次哈,那么這個參數(shù)會作為上一條執(zhí)行的 yield 語句的返回值

const promisify = require('util').promisify;
const path = require('path');
const fs = require('fs');
const readFile = promisify(fs.readFile);

function run(gen) {
  const g = gen();
  function next(data) {
    const res = g.next(data);
    // 深度遞歸,只要 `Generator` 函數(shù)還沒執(zhí)行到最后一步吆录,`next` 函數(shù)就調(diào)用自身
    if (res.done) return res.value;
    res.value.then(function(data) {
      next(data);
    });
  }
  next();
}
run(function*() {
  const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
  console.log(res1);
  // {
  //   "a": 1
  // }
  const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
  console.log(res2);
  // {
  //   "b": 2
  // }
});
// Generator
run(function*() {
  const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
  console.log(res1);
  const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
  console.log(res2);
});
// async/await
const readFile = async ()=>{
  const res1 = await readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
  console.log(res1);
  const res2 = await readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
  console.log(res2);
  return 'done'窑滞;
}
const res = readFile();

當(dāng) await 后面跟的是 Promise 對象時,才會異步執(zhí)行,其它類型的數(shù)據(jù)會同步執(zhí)行哀卫。并且返回的仍然是一個promise對象

Q4:Promise 構(gòu)造函數(shù)是同步執(zhí)行還是異步執(zhí)行巨坊,那么 then 方法呢?

const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})

promise.then(() => {
  console.log(3)
})

console.log(4)

執(zhí)行結(jié)果是:1此改,2趾撵,4,3 promise順序放在微隊列里面共啃,settimeOut任務(wù)是宏任務(wù)

Q5: 簡單講解一下http2的多路復(fù)用

在 HTTP/1 中占调,每次請求都會建立一次HTTP連接,也就是我們常說的3次握手4次揮手勋磕,這個過程在一次請求過程中占用了相當(dāng)長的時間妈候,即使開啟了 Keep-Alive ,解決了多次連接的問題挂滓,但是依然有兩個效率上的問題:

第一個:串行的文件傳輸苦银。當(dāng)請求a文件時,b文件只能等待赶站,等待a連接到服務(wù)器幔虏、服務(wù)器處理文件、服務(wù)器返回文件贝椿,這三個步驟想括。我們假設(shè)這三步用時都是1秒,那么a文件用時為3秒烙博,b文件傳輸完成用時為6秒瑟蜈,依此類推。(注:此項計算有一個前提條件渣窜,就是瀏覽器和服務(wù)器是單通道傳輸)
第二個:連接數(shù)過多铺根。我們假設(shè)Apache設(shè)置了最大并發(fā)數(shù)為300,因為瀏覽器限制乔宿,瀏覽器發(fā)起的最大請求數(shù)為6位迂,也就是服務(wù)器能承載的最高并發(fā)為50,當(dāng)?shù)?1個人訪問時详瑞,就需要等待前面某個請求處理完成掂林。
HTTP/2的多路復(fù)用就是為了解決上述的兩個性能問題。 在 HTTP/2 中坝橡,有兩個非常重要的概念泻帮,分別是幀(frame)和流(stream)。 幀代表著最小的數(shù)據(jù)單位驳庭,每個幀會標(biāo)識出該幀屬于哪個流刑顺,流也就是多個幀組成的數(shù)據(jù)流氯窍。 多路復(fù)用饲常,就是在一個 TCP 連接中可以存在多條流蹲堂。換句話說,也就是可以發(fā)送多個請求贝淤,對端可以通過幀中的標(biāo)識知道屬于哪個請求柒竞。通過這個技術(shù),可以避免 HTTP 舊版本中的隊頭阻塞問題播聪,極大的提高傳輸性能朽基。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市离陶,隨后出現(xiàn)的幾起案子稼虎,更是在濱河造成了極大的恐慌,老刑警劉巖招刨,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霎俩,死亡現(xiàn)場離奇詭異,居然都是意外死亡沉眶,警方通過查閱死者的電腦和手機(jī)打却,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谎倔,“玉大人柳击,你說我怎么就攤上這事∑埃” “怎么了捌肴?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長藕咏。 經(jīng)常有香客問我状知,道長,這世上最難降的妖魔是什么侈离? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任试幽,我火速辦了婚禮,結(jié)果婚禮上卦碾,老公的妹妹穿的比我還像新娘铺坞。我一直安慰自己,他們只是感情好洲胖,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布济榨。 她就那樣靜靜地躺著,像睡著了一般绿映。 火紅的嫁衣襯著肌膚如雪擒滑。 梳的紋絲不亂的頭發(fā)上腐晾,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音丐一,去河邊找鬼藻糖。 笑死,一個胖子當(dāng)著我的面吹牛库车,可吹牛的內(nèi)容都是我干的巨柒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柠衍,長吁一口氣:“原來是場噩夢啊……” “哼洋满!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起珍坊,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤牺勾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后阵漏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驻民,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年袱饭,在試婚紗的時候發(fā)現(xiàn)自己被綠了川无。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡虑乖,死狀恐怖懦趋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疹味,我是刑警寧澤仅叫,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站糙捺,受9級特大地震影響诫咱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洪灯,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一坎缭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧签钩,春花似錦掏呼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昧旨,卻和暖如春拾给,著一層夾襖步出監(jiān)牢的瞬間祥得,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工蒋得, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留级及,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓窄锅,卻偏偏與公主長得像创千,于是被迫代替她去往敵國和親缰雇。 傳聞我的和親對象是個殘疾皇子入偷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容