1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【原創(chuàng)】前端面試知識體系(一)

        共 27600字,需瀏覽 56分鐘

         ·

        2023-01-09 14:17

        我的博客來源:https://1024bibi.com/2018/01/01/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E7%9F%A5%E8%AF%86%E4%BD%93%E7%B3%BB%EF%BC%88%E4%B8%80%EF%BC%89/

        防抖和節(jié)流有什么區(qū)別,分別用于什么場景
        • 節(jié)流:限制執(zhí)行頻率,有節(jié)奏的執(zhí)行;
        • 防抖:限制執(zhí)行次數(shù),多次密集的觸發(fā)只執(zhí)行一次;

        防抖 debounce

              
              function?debounce(fn,?delay?=?200)?{
        ?let?timer?=?0
        ?
        ?return?function?()?{
        ??if?(timer)?clearTimeout(timer);
        ??
        ??timer?=?setTimeout(()?=>?{
        ???fn.apply(this,?arguments);?//?透傳?this?和參數(shù)
        ???timer?=?0
        ??},?delay)
        ?}
        }
              
              const?input?=?document.getElementById('input')
        input.addEventListener('keyup',?debounce(()?=>?{
        ?console.log('發(fā)起搜索',?input.value)
        }),?300)

        節(jié)流 throttle

        例如:drag或scroll期間觸發(fā)某個回調(diào),要設(shè)置一個時間間隔

        px % em rem vw/vh 有什么區(qū)別

        px 和 %

        • px基本單位,絕對單位(固定的),其他的都是相對單位
        • % 相對于父元素的寬度比例
        • 元素內(nèi)的垂直居中
              
              <style>
        ?#container?{
        ??width:?200px;
        ??height:?200px;
        ??position:?relative;
        ??background-color:?#ccc;
        ?}
        ?#box?{
        ??width:?100px;
        ??height:?100px;
        ??position:?absolute;
        ??left:?50%;
        ??top:?50%;
        ??margin-top:?-50px;
        ??margin-left:?-50px;
        ??background-color:?blue;
        ?}
        </style>
        <div?id="container">
        ?<div?id="box"></
        div>
        </div>

        em 和 rem

        • em 相對于當前元素的 font-size
        • rem 相對于根節(jié)點的 font-size
              
              <div?style="font-size:?20px;">
        ?<p?style="text-indent:?2em;?font-size:?40px;">首行縮進</p>?//?font-size:?40px;?text-indent:?80px;
        ?<p?style="text-indent:?2em;">哪吒,?算法貓叔</p>?//?font-size:?20px;?text-indent:?40px;
        </div>
              
              <style>
        ?@media?only?screen?and?(max-width:?374px)?{
        ??//?iphone5?或者更小的尺寸,以?iphone5?的寬度(320px)比例設(shè)置?font-size
        ??html?{
        ???font-size:?86px;
        ??}
        ?}
        ?@media?only?screen?and?(min-width:?375px)?and?(max-width:?413px)?{
        ??//?iphone6/7/8?和?iphone?x
        ??html?{
        ???font-size:?100px;
        ??}
        ?}
        ?@media?only?screen?and?(min-width:?414px)?{
        ??//?iphone6p?或者更大的尺寸,以?iphone6p?的寬度(414px)比例設(shè)置?font-size
        ??html?{
        ???font-size:?110px;
        ??}
        ?}
        ?p?{
        ??font-size:?.16rem;
        ?}
        </style>

        vw / vh

        • vw 屏幕寬度的 1%
        • vh 屏幕高度的 1%
        • vmin 兩者的最小值,vmax 兩者的最大值
              
              <div?id="div1">?div1?</div>
        <div?id="div2">?div2?</
        div>
        <div?id="div3">?div3?</div>
        <style>
        ?div?{
        ??border:?1px?solid?#ccc;
        ??margin-top:?20px;
        ?}
        ?#div1?{
        ??width:?10vw;
        ??height:?10vh;
        ?}
        ?#div2?{
        ??width:?10vmax;
        ??height:?10vmax;
        ?}
        ?#div3?{
        ??width:?10vmin;
        ??height:?10vmin;
        ?}
        </style>

        什么時候不能使用箭頭函數(shù)

        箭頭函數(shù)有什么缺點?

        • 沒有 arguments
        • 無法通過 apply call bind 改變 this
        • 某些箭頭函數(shù)代碼難以閱讀

        什么時候不能使用箭頭函數(shù)?

        • 不適用-對象方法
              
              const?obj?=?{
        ?name:?'哪吒,B站,算法貓叔',
        ?getName:?()?=>?{
        ??return?this.name
        ?}
        }
        console.log(obj.getName())
        • 不適用-原型方法
              
              const?obj?=?{
        ?name:?'哪吒,B站,算法貓叔'
        }
        obj.__proto__.getName?=?()?=>?{
        ?return?this.name
        }
        console.log(?obj.getName()?)
        • 不適用-構(gòu)造函數(shù)
              
              const?Foo?=?(name,?age)?=>?{
        ?this.name?=?name
        ?this.age?=?age
        }
        const?f?=?new?Foo('張三',?20)
        //?報錯?Foo?is?not?a?constructor
        • 不適用-動態(tài)上下文中的回調(diào)函數(shù)
              
              const?btn1?=?document.getElementById('btn1')
        btn1.addEventListener('click',?()?=>?{
        ?//?console.log(this?===?window)
        ?this.innerHTMl?=?'clicked'
        })
        • 不適用-Vue生命周期和method : vue組件本質(zhì)上一個 JS 對象
        • React 組件(非Hooks)本質(zhì)上是一個 es6 class,class里面適用箭頭函數(shù)沒問題
              
              {
        ?data()?{?return?{?name:??'哪吒,B站:算法貓叔'?}?},
        ?methods:?{
        ??getName:?()?=>?{
        ???//?報錯?Cannot?read?properties?of?undefined?(reading?'name')
        ??return?this.name
        ??},
        ??//?getName()?{
        ??//??return?this.name?//?正常
        ??//?}
        ?},
        ?mounted:?()?=>?{
        ??//?報錯
        ?},
        ?//?mounted()?{
        ?//??正常
        ?//?}
        }
        JS中for-in和for-of有什么區(qū)別

        for of 去遍歷可以generator

              
              const?arr?=?[10,?20,?30]
        for?(let?val?of?arr)?{
        ?console.log(val);?//?值
        }

        const?str?=?'abc'
        for?(let?c?of?str)?{
        ?console.log(c);
        }

        function?fn()?{
        ?for?(let?arg?of?arguments)?{
        ??console.log(arg)
        ?}
        }
        fn(100,?200,?'aaa')

        const?pList??=?document.getElementsByTagName('p')
        //?querySelectorAll('p')
        for?(let?p?of?pList)?{
        ?console.log(p)
        }
        • 遍歷對象: for ... in 可以,for ... of 不可以
        • 遍歷Map Set:for...of 可以,for...in 不可以
        • 遍歷generator:for...of 可以,for ... in 不可以
              
              對象,數(shù)組,字符串可枚舉的,就可以使用for?...?in?循環(huán)
        const?obj1?=?{?x:?100?}
        Object.getOwnPropertyDescriptors(obj1)
        x:
        configurable:?true
        enumerable:?true
        value:?100
        writeable:?true
        • 可枚舉 vs 可迭代

        for ... in 用于可枚舉數(shù)據(jù),如對象,數(shù)組,字符串,得到key

        for ... of 用于可迭代數(shù)據(jù),如數(shù)組,字符串,Map,Set,得到value

        for-await-of有什么作用

        for await...of 用于遍歷多個Promise

              
              function?createPromise(val)?{
        ?return?new?Promise((resolve)?=>?{
        ??setTimeout(()?=>?{
        ???resolve(val)
        ??},?1000)
        ?})
        }

        (async?function?()?{
        ?const?p1?=?createPromise(100)
        ?const?p2?=?createPromise(200)
        ?const?p3?=?createPromise(300)
        ?//?const?res1?=?await?p1
        ?//?console.log(res1)
        ?//?const?res2?=?await?p2
        ?//?console.log(res2)
        ?//?const?res3?=?await?p3
        ?//?console.log(res3)
        ?const?list?=?[p1,?p2,?p3]
        ?//?Promise.all(list).then(res?=>?console.log(res))

        ?for?await?(let?res?of?list)?{
        ??console.log(res)
        ?}
        })()
        offsetHeight - scrollHeight - clientHeight區(qū)別

        盒子模型: width, height, padding, border, margin, box-sizing

        offsetHeight offsetWidth : border + padding + content

        clientHeight clientWidth: padding + content

        scrollHeight scrollWidth: padding + 實際內(nèi)容尺寸

        HTMLCollection和NodeList有什么區(qū)
        • DOM是一顆樹,所有節(jié)點都是Node
        • Node是Element的基類
        • Element是其他HTML元素的基類,如HTMLDivElement
              
              const?p1?=?document.getElementById('p1')
        class?Node?{}

        //?document
        class?Document?extends?Node?{}
        class?DocumentFragment?extends?Node?{}

        //?文本和注釋
        class?CharacterData?extends?Node?{}
        class?Comment?extends?CharacterData?{}
        class?Text?extends?CharacterData?{}

        //?elem
        class?Element?extends?Node?{}
        class?HTMLElement?extends?Element?{}
        class?HTMLDivElement?extends?HTMLElement?{}
        class?HTMLInputElement?extends?HTMLElement?{}
        • HTMLCollection 是 Element 的集合
        • NodeList 是 Node 集合
              
              <p?id="p1">
        ?<b>node</b>?vs?<em>element</em>
        </
        p>

        <script>
        ?const?p1?=?document.getElementById('p1')
        ?console.log(p1.children)
        ?
        ?console.log(p1.childNodes)
        ?//?[b,text,em,comment]
        </script>

        劃重點:

        • 獲取 Node 和 Element 的返回結(jié)果可能不一樣
        • 如 elem.childNodes 和 elem.children 不一樣
        • 前者包含Text和Comment節(jié)點,后者不會

        類數(shù)組 變成 數(shù)組

              
              const?arr1?=?Array.from(list)
        const?arr2?=?Array.prototype.slice.call(list)
        const?arr3?=?[...list]
        Vue中computed和watch有什么區(qū)別
        • computed 用于計算產(chǎn)生新的數(shù)據(jù)
        • watch 用于監(jiān)聽現(xiàn)有數(shù)據(jù)
              
              watch:?{
        ?name(newValue,?oldValue)?{
        ??console.log('watch?name',?newValue,?oldValue)
        ?}
        },
        computed:?{
        ?userInfo()?{
        ??return?this.name?+?this.city
        ?}
        }

        computed有緩存 watch沒有緩存

        Vue組件通訊有幾種方式
              
              props和$emit

        $parent

        自定義事件

        $refs

        $attr

        provide/inject

        vuex

        ---

        $attrs?$listeners

        vue3?移除?$listeners

        上一級沒有接收到的

        props:?['x'],?//?$attrs

        emits:?['getX'],?//?$listeners

        Object.keys(this.$attrs)

        <l3?v-bind="$attrs"></l3>

        dom結(jié)點:?inheritAttrs:?false

        ---

        this.$parent
        this.$refs

        provide:?{
        ?info:?'aaa'
        }

        provide()?{
        ?return?{
        ??info:?computed(()?=>?this.name)
        ?}
        }

        ---

        父子組件

        上下級組件(跨多級)通訊

        全局組件
        Vuex中action和mutation有什么區(qū)別

        mutation: 原子操作,必須同步代碼

        action: 可包含多個mutation;可包含異步代碼

        JS嚴格模式有什么特點
              
              'use?strict'?//?全局開啟

        function?fn()?{
        ?'use?strict'?//?某個函數(shù)開啟
        }
        • 全局變量必須先聲明
        • 禁止使用 with
        • 創(chuàng)建eval作用域
        • 禁止this指向window
        • 函數(shù)參數(shù)不能重名
        JS內(nèi)存垃圾回收用什么算法

        垃圾回收 GC

              
              什么是垃圾回收?

        function?fn1()?{
        ?const?a?=?'aa'
        ?console.log(a)
        ?
        ?const?obj?=?{?x:?100?}
        ?console.log(obj)
        }
        fn1()
              
              function?fn2()?{
        ?const?obj?=?{?x:?100?}
        ?window.obj?=?obj
        }
        fn2()


        function?getDataFns()?{
        ?const?data?=?{}?//?閉包
        ?return?{
        ??get(key)?{
        ???return?data[key]
        ??},
        ??set(key,?value)?{
        ???data[key]?=?value
        ??}
        ?}
        }
        const?{?get,?set?}?=?getDataFns()
        set('x',?100)
        get('x')
              
              引用計數(shù)(之前)

        //?對象被?a?引用
        let?a?=?{?x:?100?}
        let?a1?=?a
        a?=?10
        a1?=?null

        //?循環(huán)引用
        function?fn3()?{
        ?const?obj1?=?{}
        ?const?obj2?=?{}
        ?obj1.a?=?obj2
        ?obj2.a?=?obj1
        }
        fn3()

        //?ie6-7?內(nèi)存泄漏的?bug
        var?div1?=?document.getElementById('div1')
        div1.a?=?div1
        div1.someBigData?=?{}

        標記清除(現(xiàn)代)
        //?JS?根?window
        JS閉包是內(nèi)存泄漏嗎

        閉包的數(shù)據(jù)是不可以被垃圾回收的

        如何檢測JS內(nèi)存泄漏

        檢測內(nèi)存變化

              
              const?arr?=?[]
        for?(let?i?=?0;?i?<?10?*?10000;?i++)?{
        ?arr.push(i)
        }

        function?bind()?{
        ?//?模擬一個比較大的數(shù)據(jù)
        ?const?obj?=?{
        ??str:?JSON.stringify(arr)?//?簡單的拷貝
        ?}
        ?window.addEventListener('resize',?()?=>?{
        ??console.log(obj)
        ?})
        }

        let?n?=?0
        function?start()?{
        ?setTimeout(()?=>?{
        ??bind()
        ??n++
        ??
        ??//?執(zhí)行?50?次
        ??if?(n?<?50)?{
        ???start()
        ??}?else?{
        ???alert('done')
        ??}
        ?},?200)
        }

        document.getElementById('btn1').addEventListener('click',?()?=>?{
        ?start()
        })
        JS內(nèi)存泄漏的場景有哪些
        1. 被全局變量,函數(shù)引用,組件銷毀時未清除
        2. 被全局事件,定時器引用,組件銷毀時未清除
        3. 被自定義事件引用,組件銷毀時未清除
        JS內(nèi)存泄漏的場景有哪些-擴展-WeakMap和Weak
              
              //?標記清除算法
        const?data?=?{}
        function?fn1()?{
        ?const?obj?=?{?x:?100?}
        ?data.obj?=?obj
        }
        fn1()
              
              const?map?=?new?Map()
        function?fn1()?{
        ?const?obj?=?{?x:?100?}
        ?map.set('a',?obj)
        }
        fn1()
              
              //?WeakMap?WeakSet?弱引用
        <script>
        ?const?wMap?=?new?WeakMap();?//?弱引用
        ?function?fn1()?{
        ??const?obj?=?{?x:?100?}
        ??wMap.set(obj,?100)?//?WeakMap的key,只能是引用類型
        ?}
        ?fn1()
        ?//?WeakSet
        </script>
        Ajax-Fetch-Axios三者有什么區(qū)別
        1. Ajax(Asynchronous Javascript and XML),一種技術(shù)統(tǒng)稱
        2. Fetch,一個具體的原生API 瀏覽器原生API,用于網(wǎng)絡(luò)請求 和XMLHttpRequest一個級別 Fetch語法更加簡潔,易用,支持Promise
        3. Axios,是一個第三方庫 最常用的網(wǎng)絡(luò)請求lib 內(nèi)部可用XMLHttpRequest和Fetch來實現(xiàn)
        4. lib(庫)和API(原生的函數(shù))的區(qū)別
        5. fetch 和 XMLHttpRequest 全局的API
        用XMLHttpRequest實現(xiàn)Ajax
              
              function?ajax1(url,?sucessFn)?{
        ?const?xhr?=?new?XMLHttpRequest();
        ?xhr.open("GET",?url,?false);
        ?xhr.onreadystatechange?=?function?()?{
        ??//?這里的函數(shù)異步執(zhí)行
        ??if?(xhr.readyState?==?4)?{
        ???if?(xhr.status?==?200)?{
        ????successFn(xhr.responseText);
        ???}
        ??}
        ?}
        ?xhr.send(null);
        }

        function?ajax2(url)?{
        ?return?fetch(url).then(res?=>?res.json());
        }
        請描述TPC三次握手和四次揮手

        建立TCP連接

        1. 先建立連接(確保雙方都有收發(fā)消息的能力)
        2. 再傳輸內(nèi)容(如發(fā)送給一個get請求)
        3. 網(wǎng)絡(luò)連接是TCP協(xié)議,傳輸內(nèi)容是HTTP協(xié)議
        4. SYN SYN+ACK ACK

        四次揮手-關(guān)閉連接

              
              1.?FIN?->
        2.?ACK?<-
        3.?FIN?<-
        4.?ACK?->
        HTTP跨域時為何要發(fā)送options請求

        跨域請求

        1. 瀏覽器同源策略
        2. 同源策略一般限制Ajax網(wǎng)絡(luò)請求,不能跨域請求server
        3. 不會限制<link> <img> <script> <iframe>加載第三方資源

        JSONP

              
              //?www.aaa.com網(wǎng)頁
        <script>
        ?window.onSuccess?=?function(data)?{
        ??console.log(data)
        ?}
        </script>
        <script?src="https:/
        /www.bbb.com/api/getData"></script>

        //?https://www.bbb.com...?返回了一段字符串
        'onSuccess({?errno:?0,?data:?{}?})'
              
              //?CORS?配置允許跨域(服務(wù)端)
        response.setHeader("Access-Control-Allow-Origin",?"http://localhost:8011")?//?或者"*"
        response.setHeader("Access-Control-Allow-Headers",?"X-Requested-With")
        response.setHeader("Access-Control-Allow-Methods",?"PUT,POST,GET,DELETE,OPTIONS")
        response.setHeader("Access-Control-Allow-Credentials",?"true")?//?允許跨域接收?cookie

        options請求,是跨域請求之前的預檢查;瀏覽器自行發(fā)起的,無需我們干預,不會影響實際的功能

        瀏覽器和nodejs事件循環(huán)(EventLoop)有什么

        單線程和異步

        1. JS是單線程的(無論在瀏覽器還是nodejs)
        2. 瀏覽器中JS執(zhí)行和DOM渲染共用一個線程
        3. 異步 宏任務(wù) 和 微任務(wù) 宏任務(wù),如 setTimeout setInterval 網(wǎng)絡(luò)請求 微任務(wù),如 promise async / await 微任務(wù)在下一輪DOM渲染之前執(zhí)行,宏任務(wù)在之后執(zhí)行 微任務(wù): MutationObserver 監(jiān)聽DOM樹的變化,Mutation observer 是用于代替 Mutation ?events 作為觀察DOM樹結(jié)構(gòu)發(fā)生變化時,做出相應(yīng)處理的API MutationObserver接口提供了監(jiān)視對DOM樹所做更改的能力。它被設(shè)計為舊的Mutation Events功能的替代品,該功能是DOM3 Events規(guī)范的一部分。
              
              const?p?=?document.createElement('p')
        p.innerHTML?=?'new?paragraph'
        document.body.appendChild(p)

        const?list?=?document.getElementsByTagName('p')
        console.log('length---',?listh.length)

        console.log('start')
        //?渲染之后
        setTimeout(()?=>?{
        ?const?list?=?document.getElementsByTagName('p')
        ?console.log('length?on?timeout---',?list.length)?//?2
        ?alert('阻塞?timeout')
        })
        //?渲染之前
        Promise.resolve().then(()?=>?{
        ?const?list?=?document.getElementsByTagName('p')
        ?console.log('length?on?promise.then---',?list.length)?//?2
        ?alert('阻塞?promise')
        })
        console.log('end')
              
              //?同步任務(wù)?->?異步任務(wù)?->?宏任務(wù)
        //?微任務(wù)要比宏任務(wù)要快
        //?Event?Loop

        <script>
        ?console.log('start')
        ?setTimeout(()?=>?{
        ??console.log('timeout')
        ?})
        ?Promise.resolve().then(()?=>?{
        ??console.log('promise?then')
        ?))
        ?console.log('end')

        ?//?ajax(url,?fn)?//?300ms
        ?
        ?//?Event?Loop?繼續(xù)監(jiān)聽
        ?//?宏任務(wù)?MarcoTask?Queue
        ?//?()?=>?{
        ?//???console.log('timeout')
        ?//?}
        ?//?fn
        ?
        ?//?DOM?渲染
        ?//?微任務(wù)?MicroTask?Queue
        ?//?()?=>?{
        ?//???console.log('promise?then')
        ?//?}
        </script>

        Nodejs異步

        1. Nodejs同樣使用ES語法,也是單線程,也需要異步
        2. 異步任務(wù)也分:宏任務(wù)+微任務(wù)
        3. 但是,它的宏任務(wù)和微任務(wù),分不同類型,有不同優(yōu)先級

        虛擬DOM(vdom)真的很快嗎

        1. vdom: Virtual DOM,虛擬DOM 用JS對象模擬DOM節(jié)點數(shù)據(jù)
        2. 組件化 數(shù)據(jù)視圖分離,數(shù)據(jù)驅(qū)動視圖 只關(guān)注業(yè)務(wù)數(shù)據(jù),而不用再關(guān)心DOM變化
        3. vdom并不快,js直接操作dom才是最快的 但”數(shù)據(jù)驅(qū)動視圖“要有合適的技術(shù)方案,不能全部dom重建 vdom就是目前最合適的技術(shù)方案(并不是因為它快,而是合適)

        遍歷一個數(shù)組用for和forEach哪個更快

        • for更快
        • forEach每次都要創(chuàng)建一個函數(shù)來調(diào)用,而for不會創(chuàng)建函數(shù)
        • 函數(shù)需要獨立的作用域,會有額外的開銷

        nodejs如何開啟多進程,進程如何通訊-進程和線程的

        進程 process vs 線程 thread 進程,OS 進行資源分配和調(diào)度的最小單位,有獨立內(nèi)存空間 線程,OS 進行運算調(diào)度的最小單位,共享進程內(nèi)存空間 JS是單線程的,但可以開啟多進程執(zhí)行,如WebWorker js 不可以開啟一個線程

        為何需要多進程?

        1. 多核CPU,更適合處理多進程
        2. 內(nèi)存較大,多個進程才能更好的利用(單進程有內(nèi)存上限)
        3. 總之,“壓榨”機器資源,更快,更節(jié)省 單個進程內(nèi)存2G左右
              
              nodejs如何開啟多進程

        //?console.info(process.pid)
        const?http?=?require('http')

        const?server?=?http.createServer()
        server.listen(3000,?()?=>?{
        ?console.log('localhost:?3000')
        })

        console.info(process.pid)

        //?WebWorker?進程
        //?fork
        const?http?=?require('http')
        const?server?=?http.createServer((req,?res)?=>?{
        ?if?(req.url?===?'/get-sum')?{
        ???console.info('主進程?id',?process.id)
        ???
        ???res.end('hello')
        ?}
        })
        server.listen(3000,?()?=>?{
        ?console.info('localhost:?3000')
        })

        //?cluster?進程
              
              //?子進程,計算
        function?getSum()?{
        ?let?sum?=?0
        ?for?(let?i?=?0;?i?<?10000;?i++)?{
        ??sum?+=?i
        ?}
        ?return?sum
        }

        process.on('message',?data?=>?{
        ?console.log('子進程?id',?process.pid)
        ?console.log(‘子進程接受到的信息:',?data)

        ?const?sum?=?getSum()
        ?//?發(fā)送消息給主進程
        ?process.send(sum)
        })
              
              const?http?=?require('http')
        const?fork?=?require('child_process').fork

        const?server?=?http.createServer((req,?res)?=>?{
        ?if?(req.url?===?'/get-sum')?{
        ??console.info('主進程?id',?process.pid)

        ???//?開啟子進程
        ??const??computeProcess?=?fork('./compute.js')
        ??computeProcess.send('開始計算')

        ??computeProcess.on('message',?data?=>?{
        ????console.info('主進程接受到的信息:',?data)
        ????res.end('sum?is'?+?data)
        ??})

        ??computeProcess.on('close',?()?=>?{
        ????console.info('子進程因報錯而退出')
        ????computeProcess.kill()
        ????res.end('error')
        ??})
        ?}
        })

        server.listen(3000,?()?=>?{
        ?console.info('localhost:?3000')
        })
              
              const?http?=?require('http')
        const?cpuCoreLength?=?require('os').cpus().length
        const?cluster?=?require('cluster')

        if?(cluster.isMaster)?{
        ?for?(let?i?=?0;?i?<?cpuCoreLength;?i++)?{
        ??cluster.fork()?//?開啟子進程
        ?}
        ?cluster.on('exit',?worker?=>?{
        ??console.log('子進程退出')
        ??cluster.fork()?//?進程守護
        ?})
        }?else?{
        ?//?多個子進程會共享一個?TCP?連接,提供一份網(wǎng)絡(luò)服務(wù)
        ??const?server?=?http.createServer((req,?res)?=>?{
        ??res.writeHead(200)
        ??res.end('done')
        ?})
        ?server.listen(3000)
        }

        開啟子進程 child_process.fork 和 cluster.fork 使用 send 和 on 傳遞消息

        請描述js-bridge的實現(xiàn)原理
        1. JS無法直接調(diào)用 native API
        2. 需要通過一些特定的“格式”來調(diào)用
        3. JS Bridge的常見實現(xiàn)方式
          1. 注冊全局API
          2. URL Scheme
              
              //?封裝?JS-bridge
        const?sdk?=?{
        ?invoke(url,?data?=?{},?onSuccess,?onError)?{
        ???const?iframe?=?document.createElement('iframe')
        ???iframe.style.visibility?=?'hidden'
        ???document.body.appendChild(iframe)
        ???
        ???iframe.onload?=?()?=>?{
        ????const?content?=?iframe1.contentWindow.document.body.innerHTML
        ???}
        ?}
        }
        requestIdleCallback和request

        由React fiber引起的關(guān)注

        1. 組建樹轉(zhuǎn)換為鏈表,可分段渲染
        2. 渲染時可以暫停,去執(zhí)行其他高優(yōu)任務(wù),空閑時再繼續(xù)渲染
        3. 如何判斷空閑? - requestIdleCallback

        區(qū)別

        1. requestAnimationFrame 每次渲染完都會執(zhí)行,高優(yōu)
        2. requestIdleCallback 空閑時才執(zhí)行,低優(yōu)
              
              <p>requestAnimationFrame</p>
        <button?id="btn1">change</
        button>
        <div?id="box"></div>

        <script>
        const?box?=?document.getElementById('box')
        document.getElementById('btn1').addEventListener('click',?()?=>?{
        ?let?curWidth?=?100
        ?const?maxWidth?=?400
        ?function?addWidth()?{
        ??curWidth?=?curWidth?+?3
        ??box.style.width?=?`${curWidth}px`
        ??if?(curWidth?<?maxWidth)?{
        ???window.requestIdleCallback(addWidth)?//?時間不用自己控制
        ??}
        ?}
        })
        </script>

              
              start
        end
        timeout
        requestAnimationFrame
        requestIdleCallback

        window.onload?=?()?=>?{

        ?console.info('start')
        ?setTimeout(()?=>?{
        ??console.info('timeout')
        ?})
        ?//?宏任務(wù),順序交換也一樣
        ?//?高優(yōu)
        ?window.requestAnimationFrame(()?=>?{
        ??console.info('requestAnimationFrame')
        ?})
        ?//?低優(yōu)
        ?window.requestIdleCallback(()?=>?{
        ??console.info('requestIdleCallback')
        ?})

        ?console.info('end')
        }
        Vue每個生命周期都做了什么
        • beforeCreate 創(chuàng)建一個空白的Vue實例 data method 尚未被初始化,不可使用

        • created vue實例初始化完成,完成響應(yīng)式綁定 data method都已經(jīng)初始化完成,可調(diào)用 尚未開始渲染模板

        • beforeMount 編譯模版,調(diào)用render生成vdom 還沒有開始渲染DOM

          $el null element沒有

        • mounted 完成DOM渲染 組件創(chuàng)建完成 開始由“創(chuàng)建階段”進入“運行階段”

        • beforeUpdate data發(fā)生變化之后 準備更新DOM(尚未更新DOM)

        • updated data發(fā)生變化,且DOM更新完成 (不要在updated中修改data,可能會導致死循環(huán))

        • beforeUnmount 組件進入銷毀階段(尚未銷毀,可正常使用) 可移除,解綁一些全局事件,自定義事件

        • unmounted 組件被銷毀了 所有子組件也都被銷毀了

        • keep-alive組件 onActivated 緩存組件被激活 onDeactivated 緩存組件被隱藏

              
              <keep-alive>
        ?<Child1?v-if="num?===?1"></Child1>
        ?<Child2?v-else></Child2>
        </keep-alive>

        /
        /?Child1?2
        created()?{
        ?console.log()?/
        /?keep-alive?中只創(chuàng)建
        }
        activated()?{}
        deactivated()?{}

        /
        /?創(chuàng)建一次被緩存
              
              child1?created
        child1?activated
        child2?created
        child1?deactivated
        child2?activated
        child2?deactivated
        child1?activated
        • vue什么時候操作DOM比較合適 mounted和updated都不能保證子組件全部掛載完成 使用$nextTick渲染DOM

          只有nextTick操作DOM才是最安全的

              
              $nextTick
        mounted()?{
        ?this.$nextTick(function?()?{
        ??//?僅在整個視圖都被渲染之后才會運行的代碼
        ?})
        }
        • ajax 應(yīng)該在那個生命周期? 有兩個選擇:created 和 mounted 推薦:mounted
        • vue3 Composition API 生命周期有何區(qū)別? 用setup代替了beforeCreate和created 使用Hooks函數(shù)的形式,如mounted改為onMounted()
              
              import?{?onUpdated,?onMounted?}?from?'vue'
        export?default?{
        ?setup()?{
        ??onMounted(()?=>?{
        ?
        ??})
        ??onUpdated(()?=>?{
        ??
        ??})
        ?}
        }
        Vue2和Vue3和React三者的diff算法有什么

        介紹diff算法 diff算法很早就有

        tree diff優(yōu)化 只比較同一層級,不跨級比較 tag 不同則刪掉重建(不再去比較內(nèi)部的細節(jié)) 子節(jié)點通過key區(qū)分(key的重要性)

        vue3最長遞增子序列 vue2 雙端比較 React 僅右移

        Vue-router的MemoryHistory是什么

        Hash, WebHistory, MemoryHistory( v4 之前叫做 abstract history)

        移動端H5點擊有300ms延遲,該如何解決

        FastClick原理 監(jiān)聽touchend事件(touchstart touchend會先于click觸發(fā)) 使用自定義DOM事件模擬一個click事件 把默認的click事件(300ms之后觸發(fā))禁止掉

        現(xiàn)代瀏覽器的改進

              
              <head>
        ?<meta?charset="UTF-8">
        ?<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
        ?<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
        </head>
        HTTP請求中token和cookie有什么區(qū)別-cookie
        1. cookie HTTP無狀態(tài),每次請求都要帶cookie,以幫助識別身份 服務(wù)端也可以向客戶端set-cookie,cookie大小限制4kb 默認有跨域限制:不可跨域共享、傳遞cookie
        2. withCredentials 前端設(shè)置跨域cookie共享 cookie本地存儲 HTML5之前cookie常被用于本地存儲 HTML5之后推薦使用localStorage和sessionStorage
        3. 現(xiàn)在瀏覽器開始禁止第三方cookie 和跨域限制不同。這里是:禁止網(wǎng)頁引入的第三方JS設(shè)置cookie 打擊第三方廣告,保護用戶隱私 新增屬性 SameSite: Strict/Lax/None;值可自己選擇
        4. 瀏覽器的Cookie新增加了一個SameSite屬性,用來防止CSRF攻擊和用戶追蹤
        5. cookie和session cookie用于登錄驗證,存儲用戶標識 session在服務(wù)端,存儲用戶詳細信息,和cookie信息一一對應(yīng) cookie和session是常見登錄驗證解決方案
        HTTP請求中token和cookie有什么區(qū)別-token
        1. token vs cookie cookie是HTTP規(guī)范,而token是自定義傳遞 cookie會默認被瀏覽器存儲,而token需自己存儲 token默認沒有跨域限制
        2. jwt (json web token) 可以取代 cookie和session 前端發(fā)起登錄,后端驗證成功之后,返回一個加密的token 前端自行存儲這個token(其中包含了用戶信息,加密了) 以后訪問服務(wù)端接口,都帶著這個token,作為用戶信息
        3. cookie:HTTP標準;跨域限制;配合session使用
        4. token:無標準;無跨域限制;用于JWT
        session和JWT哪個更好
        1. session缺點 占用服務(wù)端內(nèi)存,硬件成本高 多進程,多服務(wù)器時,不好同步,需使用第三方緩存,如redis 默認有跨域限制
        2. session優(yōu)點 原理簡單,易于學習 用戶信息存儲在服務(wù)端,可快速禁某個用戶
        3. jwt 優(yōu)點 不占用服務(wù)端內(nèi)存 多進程,多服務(wù)器 不受影響 沒有跨域限制
        4. jwt 缺點 用戶信息存儲在客戶端,無法快速封禁某用戶 萬一服務(wù)端秘鑰被泄漏,則用戶信息全部丟失 token體積一般大于cookie,會增加請求的數(shù)據(jù)量

        如有嚴格管理用戶信息的需求(保密,快速封禁)推薦session 如沒有特殊要求,則使用jwt

        如何實現(xiàn)SSO單點登錄
        1. 基于cookie cookie默認不可跨域共享,但有些情況下可設(shè)置為共享 主域名相同,如www.baidu.com image.baidu.com 設(shè)置cookie domain為主域名,即可共享cookie
        2. sso 主域名完全不同,則cookie無法共享 可使用sso技術(shù)方案
        HTTP協(xié)議和UDP協(xié)議有什么區(qū)別

        網(wǎng)絡(luò)協(xié)議 HTT P協(xié)議在應(yīng)用層 TCP UDP 協(xié)議再傳輸層 嚴格來說,應(yīng)該拿TCP和UDP進行比較

        OSI的體系結(jié)構(gòu)

              
              7.?應(yīng)用層
        6.?表示層
        5.?會話層
        4.?運輸層
        3.?網(wǎng)絡(luò)層
        2.?數(shù)據(jù)鏈路層
        1.?物理層

        TCP/IP的體系結(jié)構(gòu)

              
              1.?應(yīng)用層(各種應(yīng)用層協(xié)議,如DNS,HTTP,SMTP等)
        2.?運輸層(TCP或UDP)
        3.?網(wǎng)際層(IP)
        4.?網(wǎng)絡(luò)接口層

        TCP協(xié)議

        1. 有連接(三次握手)
        2. 有斷開(四次揮手)
        3. 穩(wěn)定傳輸

        UDP協(xié)議

        1. 無連接,無斷開
        2. 不穩(wěn)定傳輸,但效率高
        3. 如視頻會議,語音通話

        HTTP是應(yīng)用層,TCP UDP是傳輸層 TCP有連接,有斷開,穩(wěn)定傳輸 UDP無連接,無斷開,不穩(wěn)定傳輸,但效率高

        HTTP協(xié)議1.0和1.1和2.0有什么區(qū)別
        1. HTTP1.0 棄用 最基礎(chǔ)的HTTP協(xié)議 支持基本的GET,POST的方法
        2. HTTP1.1 緩存策略 cache-control E-tag等 支持長連接Connection: keep-alive,一次TCP連接多次請求 斷點續(xù)傳,狀態(tài)碼 206 支持新的方法PUT DELETE等,可用于Restful API
        3. HTTP2.0 可壓縮header,減少體積 多路復用,一次TCP連接中可以多個HTTP并行請求 服務(wù)端推送
        什么是HTTPS中間人攻擊,如何預防

        HTTP S 加密傳輸 HTTP明文傳輸 HTTP S 加密傳輸 HTTP+TLS/SSL

        script標簽的defer和async有什么區(qū)別

        <script src="xxx.js" async 或 defer></script>

        無:HTML暫停解析,下載JS,執(zhí)行JS,再繼續(xù)解析HTMl defer:HTML繼續(xù)解析,并行下載JS,HTML解析完再執(zhí)行JS async: HTML繼續(xù)解析,并行下載JS,執(zhí)行JS,再解析HTM L

        prefetch和dns-prefetch分別

        preload和prefetch preload資源在當前頁面使用,會優(yōu)先加載 prefetch資源在未來頁面使用,空閑時加載

              
              <head>

        <link?rel="preload"?href="style.css"?as="style">
        <link?rel="preload"?href="main.js"?as="script">

        <link?rel="prefetch"?href="other.js"?as="script">

        <link?rel="stylesheet"?href="style.css">

        </head>
        <body>
        <script?src="main.js"?defer></script>
        </body>

        dns-prefetch 和 preconnect dns-prefetch即DNS預查詢 preconnect即DNS預連接

        多個域名時,當前已經(jīng)解析完,預查詢,預連接

              
              <link?rel="dns-prefetch"?href="域名">
        <link?rel="dns-preconnect"?href=""?crossorigin></link>

        prefetch 是資源預獲?。ê蚿reload相關(guān)) dns-prefetch 是DNS預查詢(和preconnect相關(guān))

        前端攻擊手段有哪些,該如何預防
        1. xss Cross Site Script 跨站腳本攻擊 手段:黑客將JS代碼插入到網(wǎng)頁內(nèi)容中,渲染時執(zhí)行JS代碼 預防:特殊字符替換(前端或者后端)

        const newStr = str.replaceAll('<', '&lt;').replaceAll('>', '&gt;')

        1. Vue React 默認屏蔽xss攻擊 除了用 vue v-html react dangerouslySetInnerHTML
        2. CSRF Cross Site Request Forgery 跨站請求偽造 手段:黑客誘導用戶去訪問另一個網(wǎng)站的接口,偽造請求 預防:嚴格的跨站限制 + 驗證碼機制
        3. CSRF詳細過程 用戶登錄了A網(wǎng)站,有了cookie 黑客誘導用戶到B網(wǎng)站,并發(fā)起A網(wǎng)站的請求 A網(wǎng)站的API發(fā)現(xiàn)有cookie,認為是用戶自己操作的
        4. CSRF預防手段 嚴格的跨域請求限制,如判斷referrer(請求來源) 為cookie設(shè)置SameSite,禁止跨域傳遞cookie 關(guān)鍵接口使用短信驗證碼
        5. 點擊劫持 Click Jacking 手段:誘導界面上蒙一個通明的iframe,誘導用戶點擊 預防:讓iframe不能跨域加載
        6. 點擊劫持 預防
              
              if?(top.location.hostname?!==?self.location.hostname)?{
        ?alert("您正在訪問不安全的頁面,即將跳轉(zhuǎn)到安全頁面!“)
        ?top.location.href?=?self.location.href
        }

        hearders

        X-Frame-Options:?sameorigin
        1. DDoS DIstribute denial-of-service分布式拒絕服務(wù) 手段:分布式的,大規(guī)模的流量訪問,使服務(wù)器癱瘓 預防:軟件層不好做,需硬件預防(如阿里云WAF)
        2. SQL注入 手段:黑客提交內(nèi)容時寫入SQL語句,破壞數(shù)據(jù)庫 預防:處理輸入的內(nèi)容,替換特殊字符
        3. xss, ddos, csrf, sql注入, 點擊劫持
        WebSocket和HTTP協(xié)議有什么區(qū)別
        1. WebSocket 支持端對端通訊 可以由client發(fā)起,也可以由server發(fā)起 用于:消息通知,直播間討論區(qū),聊天室,協(xié)同編輯
              
              npm?init?-y
        npm?install?ws?--save
        npm?install?nodemon?--save-dev
              
              const?{?WebSocketServer?}?=?require('ws')

        const?wsServer?=?new?WebSocketServer({?port:?3000?})

        wsServer.on('connection',?ws?=>?{
        ?console.info('connected')
        ?
        ?ws.on('message',?msg?=>?{
        ??console.info('收到了信息',?msg.toString)
        ??
        ??//?服務(wù)端向客戶端發(fā)送信息
        ??setTimeout(()?=>?{
        ???ws.send('服務(wù)端已經(jīng)收到了信息:'?+?msg.toString())
        ??},?2000)
        ?})
        })



        <button?id="btn-send">發(fā)送消息</button>

        const?ws?=?new?WebSocket('ws:/
        /127..0.0.1:3000')
        ws.onopen?=?()?=>?{
        ?console.info('opened')
        ?ws.send('client?opened')
        }
        ws.onmessage?=?event?=?{
        ?console.info('收到了信息',?event.data)
        }

        const?btnSend?=?document.getElementById('btn-send')
        btnSend.addEventListener('click',?()?=>?{
        ?console.info('clicked')
        ?ws.send('當前時間'?+?Date.now())
        })

        WebSocket 連接過程 先發(fā)起一個 HTTP 請求 成功之后再升級到 WebSocket 協(xié)議,再通訊

        WebSocket 和 HTTP 區(qū)別 WebSocket 協(xié)議名是 ws:// , 可雙端發(fā)起請求 WebSocket 沒有跨域限制 通過send和onmessage通訊(HTTP通過req和res)

              
              ws可升級為?wss?(像https)
        import?{?createServer?}?from?'https'
        import?{?readFileSync?}?from?'fs'
        import?{?WebSocketServer?}?from?'ws'

        const?server?=?createServer?({
        ?cert:?readFileSync('/path/to/cert.pem'),
        ?key:?readFileSync('/path/to/key.pem')
        })

        const?wss?=?new?WebSocketServer({?server?})
              
              擴展:實際項目推薦socket.io,?api更簡潔
        io.on('connection',?socket?=>?{
        ?socket.emit('request',?/*...*/)
        ?io.emit('broadcast',?...)
        ?socket.on('reply',?()?=>?{})
        })
              
              const?{?WebSocketServer?}?=?require('ws')

        const?wsServer?=?new?WebSocketServer({?port:?3000?})

        const?list?=?new?Set()

        wsServer.on('connection',?curWs?=>?{
        ?console.info('connected')

        ?list.add(curWs)

        ?curWs.on('message',?msg?=>?{
        ??console.info('received?message',?msg.toString())
        ??
        ??//?傳遞給其他客戶端
        ??list.forEach(ws?=>?{
        ???if?(ws?===?curWs)?return
        ???ws.send(msg.toString())
        ??})
        ?})
        })
        WebSocket和HTTP長輪詢的區(qū)別
        1. 區(qū)別 HTTP長輪詢:客戶端發(fā)起請求,服務(wù)端等待,不會立即返回 WebSocket:客戶端可發(fā)起請求,服務(wù)端也可發(fā)起請求
        2. 注意: HTTP長輪詢,需處理timeout,即 timeout 之后重新發(fā)請求
        從輸入URL到網(wǎng)頁顯示的完整過程

        步驟: 網(wǎng)絡(luò)請求: DNS查詢(得到IP),建立TCP連接(三次握手) 瀏覽器發(fā)起HTTP請求 收到請求響應(yīng),得到HTML源代碼

        繼續(xù)請求靜態(tài)資源 解析HTML過程中,遇到靜態(tài)資源還會繼續(xù)發(fā)起網(wǎng)絡(luò)請求 JS CSS 圖片 視頻等 注意:靜態(tài)資源可能有強緩存,此時不必請求

        解析:字符串 -> 結(jié)構(gòu)化數(shù)據(jù) HTML構(gòu)建DOM樹 CSS構(gòu)建CSSOM樹(style tree) 兩者結(jié)合,形成 render tree

        渲染 解析過程很復雜 CSS 可能來自 <style> <link>JS 可能內(nèi)嵌,或外鏈,還有 defer async 邏輯 img 可能內(nèi)嵌(base64),可能外鏈

        優(yōu)化解析 CSS放在<head>中,不要異步加載CSS JS放在<body>最下面(或合理使用 defer async)<img> 提前定義 width height

        渲染:Render Tree 繪制到頁面 計算各個DOM的尺寸,定位,最后繪制到頁面 遇到JS可能會執(zhí)行(參考 defer async) 異步CSS,圖片加載,可能會觸發(fā)重新渲染

        網(wǎng)絡(luò)請求:DNS解析,HTTP請求 解析:DOM樹,CSSOM樹,Render Tree 渲染:計算,繪制,同時執(zhí)行JS

        網(wǎng)頁重繪repaint和重排reflow有什么
        1. 網(wǎng)頁動畫
        2. Modal Dialog 彈窗
        3. 增加/刪除一個元素,顯示/隱藏一個元素

        重繪 repaint

        1. 元素外觀改變,如顏色,背景色
        2. 但元素的尺寸,定位不變,不會影響其他元素的位置

        重排 reflow

        1. 重新計算尺寸和布局,可能會影響其他元素的位置
        2. 如元素高度增加,可能會使相鄰元素位置下移

        區(qū)別

        1. 重排比重繪要影響更大,消耗也更大
        2. 所以,要盡量避免無意義的重排

        減少重排的方法 1/2

        1. 集中修改樣式,或直接切換 css class
        2. 修改之前先設(shè)置 display: none, 脫離文檔流
        3. 使用bfc特性,不影響其他元素位置

        減少重排的方法 2/2

        1. 頻繁觸發(fā)(resize scroll)使用節(jié)流和防抖
        2. 使用 createDocumentFragment 批量操作 DOM
        3. 優(yōu)化動畫,使用 CSS3 和 requestAnimationFrame

        擴展:BFC

        1. Block Format Context 塊級格式化上下文
        2. 內(nèi)部的元素無論如何改動,都不會影響其他元素的位置

        觸發(fā) BFC 的條件 1/2

        1. 根節(jié)點 <html>
        2. float: left/right
        3. overflow: auto/scroll/hidden;

        觸發(fā) BFC 的條件 2/2

        1. display: inline-block / table / table-row / table-cell;
        2. display: flex/grid; 的直接子元素
        3. position: absolute / fixed;
        如何實現(xiàn)網(wǎng)頁多標簽tab通訊

        使用 WebSocket

        1. 無跨域限制
        2. 需要服務(wù)端支持,成本高

        通過 localStorage 通訊

        1. 同域的 A 和 B 兩個頁面
        2. A頁面設(shè)置 localStorage
        3. B頁面可監(jiān)聽到 localStorage 值的修改

        通過 SharedWorker 通訊

        1. SharedWorker 是 WebWorker 的一種
        2. WebWorker 可開啟子進程執(zhí)行 JS,但不能操作 DOM
        3. SharedWorker 可單獨開啟一個進程,用于同域頁面通訊
        瀏覽 38
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲视频无码字幕在线看 | 777色综合 | 涩涩涩综合 | 啊别了快cao我啊h女同 | 特级西西人体www高清大胆 | 黄色三级片免费 | 日韩免费无码电影 | 一区二区自拍 | 激情无码人妻又粗又大 | 97精品人妻一区二区三区香蕉 |