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>

        前端基礎(chǔ)知識(shí)整理匯總(中)

        共 14927字,需瀏覽 30分鐘

         ·

        2021-02-26 10:41


        接上昨天的《前端基礎(chǔ)知識(shí)整理匯總(上)》,這些知識(shí)雖然是很基礎(chǔ)的,但是對(duì)于系統(tǒng)的梳理還是非常有幫助的,也希望這些內(nèi)容對(duì)你有所幫助。


        Call, bind, apply實(shí)現(xiàn)

        // callFunction.prototype.myCall = function (context) {  context = context ? Object(context) : window   context.fn = this;
        let args = [...arguments].slice(1); const result = context.fn(...args); delete context.fn; return result;}
        // applyFunction.prototype.myApply = function (context) { context = context ? Object(context) : window; context.fn = this;
        let args = [...arguments][1]; let result; if (args.length === 0) { result = context.fn(); } else { result = context.fn(args); } delete context.fn; return result;}
        // bindFunction.prototype.myBind = function (context) { let self = this; let args = [...arguments].slice(1); return function() { let newArgs = [...arguments]; return self.apply(context, args.concat(newArgs)); }}

        原型與原型鏈

        每一個(gè)JavaScript對(duì)象(null除外)在創(chuàng)建的時(shí)候會(huì)關(guān)聯(lián)另一個(gè)對(duì)象,這個(gè)被關(guān)聯(lián)的對(duì)象就是原型。每一個(gè)JavaScript對(duì)象(除了 null)都具有的__proto__屬性會(huì)指向該對(duì)象的原型。
        JavaScript中所有的對(duì)象都是由它的原型對(duì)象繼承而來,而原型也是一個(gè)對(duì)象,它也有自己的原型對(duì)象,這樣層層上溯,就形成了一個(gè)類似鏈表的結(jié)構(gòu),這就是原型鏈。
        每一個(gè)對(duì)象都會(huì)從原型"繼承"屬性。
        實(shí)例對(duì)象和構(gòu)造函數(shù)都可以指向原型, 原型可以指向構(gòu)造函數(shù),不能指向?qū)嵗?因?yàn)榭梢杂卸鄠€(gè)實(shí)例)。
        原型對(duì)象有兩個(gè)屬性,constructor 和 __proto__。
        function Person() {}var person = new Person();
        // 實(shí)例原型 === 構(gòu)造函數(shù)原型person.__proto__ === Person.prototype // true// 原型構(gòu)造函數(shù) === 構(gòu)造函數(shù)Person.prototype.constructor === Person // true

        react diff

        • React 通過制定大膽的 diff 策略,將 O(n3) 復(fù)雜度的問題轉(zhuǎn)換成 O(n) 復(fù)雜度的問題;

        • React 通過分層求異的策略,對(duì) tree diff 進(jìn)行算法優(yōu)化;

          對(duì)樹進(jìn)行分層比較,兩棵樹只會(huì)對(duì)同一層次的節(jié)點(diǎn)進(jìn)行比較。

        • React 通過相同類生成相似樹形結(jié)構(gòu),不同類生成不同樹形結(jié)構(gòu)的策略,對(duì) component diff 進(jìn)行算法優(yōu)化;

          1. 如果是同一類型的組件,按照原策略繼續(xù)比較 virtual DOM tree。

          2. 如果不是,則將該組件判斷為 dirty component,從而替換整個(gè)組件下的所有子節(jié)點(diǎn)。

          3. 對(duì)于同一類型的組件,有可能其 Virtual DOM 沒有任何變化,如果能夠確切的知道這點(diǎn)那可以節(jié)省大量的 diff 運(yùn)算時(shí)間,因此 React 允許用戶通過 shouldComponentUpdate() 來判斷該組件是否需要進(jìn)行 diff。

        • React 通過設(shè)置唯一 key的策略,對(duì) element diff 進(jìn)行算法優(yōu)化;

        • 建議,在開發(fā)組件時(shí),保持穩(wěn)定的 DOM 結(jié)構(gòu)會(huì)有助于性能的提升;

        遍歷對(duì)象

        對(duì)象遍歷方法總結(jié):

        • for...in:遍歷對(duì)象自身, 包含繼承, 可枚舉,不含 Symbol 的屬性。

        • Object.keys(obj):遍歷對(duì)象自身, 不含繼承,可枚舉,不含 Symbol 的屬性?!緑alues, entries】

        • Object.getOwnPropertyNames(obj):遍歷對(duì)象自身, 不含繼承, 不含 Symbol 的屬性, 不管是否可枚舉

        • Object.getOwnPropertySymbols(obj): 遍歷對(duì)象自身, 不含繼承, 所有 Symbol 的屬性, 不管是否可枚舉

        • Reflect.ownKeys(obj): 遍歷對(duì)象自身,不含繼承,所有鍵名,不管是否Symbol 和可枚舉。

          對(duì)象其他方法:

        • JSON.stringify():只串行化對(duì)象自身,不含繼承,可枚舉,不含 Symbol屬性。【function,undefined, Symbol會(huì)丟失, set、map會(huì)處理成空對(duì)象】

        • Object.assign():只拷貝對(duì)象自身,不含繼承, 可枚舉屬性, 不管是否是Symbol 。【全部數(shù)據(jù)類型屬性值】

        方法自身屬性繼承屬性可枚舉屬性Symbol屬性
        for...in..必須
        Object.keys()必須
        Object.getOwnPropertyNames(obj)非必須
        Object.getOwnPropertySymbols(obj)非必須
        Reflect.ownKeys(obj)非必須非必須
        JSON.stringify()必須
        Object.assign()必須非必須


        異步加載腳本

        默認(rèn)情況下,瀏覽器是同步加載 JavaScript 腳本,即渲染引擎遇到<script>標(biāo)簽就會(huì)停下來,等到執(zhí)行完腳本,再繼續(xù)向下渲染。如果是外部腳本,還必須加入腳本下載的時(shí)間。

        異步加載腳本方法:defer與async。

        defer與async的區(qū)別是:defer要等到整個(gè)頁面在內(nèi)存中正常渲染結(jié)束(DOM 結(jié)構(gòu)完全生成,以及其他腳本執(zhí)行完成),才會(huì)執(zhí)行;async一旦下載完,渲染引擎就會(huì)中斷渲染,執(zhí)行這個(gè)腳本以后,再繼續(xù)渲染。一句話,defer是“渲染完再執(zhí)行”,async是“下載完就執(zhí)行”。另外,如果有多個(gè)defer腳本,會(huì)按照它們在頁面出現(xiàn)的順序加載,而多個(gè)async腳本是不能保證加載順序的。

        瀏覽器對(duì)于帶有type="module"的<script>,都是異步加載,不會(huì)造成堵塞瀏覽器,即等到整個(gè)頁面渲染完,再執(zhí)行模塊腳本,等同于打開了<script>標(biāo)簽的defer屬性。

        ES6 模塊與 CommonJS 模塊的差異

        • CommonJS 模塊輸出的是一個(gè)值的拷貝,ES6 模塊輸出的是值的引用。

        • CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。

          因?yàn)?CommonJS 加載的是一個(gè)對(duì)象(即module.exports屬性),該對(duì)象只有在腳本運(yùn)行完才會(huì)生成。而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。

        • CommonJS 模塊的require()是同步加載模塊,ES6 模塊的import命令是異步加載,有一個(gè)獨(dú)立的模塊依賴的解析階段。

        回流Reflow與重繪Repaint

        回流:元素的大小或者位置發(fā)生了變化,觸發(fā)了重新布局,導(dǎo)致渲染樹重新計(jì)算布局和渲染。頁面第一次加載的時(shí)候,至少發(fā)生一次回流。

        1. 添加或刪除可見的DOM元素;

        2. 元素的位置發(fā)生變化;

        3. 元素的尺寸發(fā)生變化;

        4. 內(nèi)容發(fā)生變化(比如文本變化或圖片被另一個(gè)不同尺寸的圖片所替代);

        5. 頁面一開始渲染的時(shí)候(這個(gè)無法避免);

        6. 瀏覽器的窗口尺寸變化, 因?yàn)榛亓魇歉鶕?jù)視口的大小來計(jì)算元素的位置和大小的;

        重繪:元素的外觀,風(fēng)格改變,而不會(huì)影響布局(不包含寬高、大小、位置等不變)。
        如:outline, visibility, color, background-color......等

        Reflow 的成本比 Repaint 高得多的多。DOM Tree 里的每個(gè)結(jié)點(diǎn)都會(huì)有 reflow 方法,一個(gè)結(jié)點(diǎn)的 reflow 很有可能導(dǎo)致子結(jié)點(diǎn),甚至父點(diǎn)以及同級(jí)結(jié)點(diǎn)的 reflow。。回流一定會(huì)觸發(fā)重繪,而重繪不一定會(huì)回流

        減少重繪與回流

        1. CSS方法

          • 使用 visibility 替換 display: none ,因?yàn)榍罢咧粫?huì)引起重繪,后者會(huì)引發(fā)回流

          • 避免使用table布局,可能很小的一個(gè)小改動(dòng)會(huì)造成整個(gè) table 的重新布局。

          • 避免設(shè)置多層內(nèi)聯(lián)樣式,CSS 選擇符從右往左匹配查找,避免節(jié)點(diǎn)層級(jí)過多。

          • 將動(dòng)畫效果應(yīng)用到position屬性為absolute或fixed的元素上,避免影響其他元素的布局,這樣只是一個(gè)重繪,而不是回流,同時(shí),控制動(dòng)畫速度可以選擇 requestAnimationFrame

          • 避免使用CSS表達(dá)式,可能會(huì)引發(fā)回流。

          • 將頻繁重繪或者回流的節(jié)點(diǎn)設(shè)置為圖層,圖層能夠阻止該節(jié)點(diǎn)的渲染行為影響別的節(jié)點(diǎn),例如will-change、video、iframe等標(biāo)簽,瀏覽器會(huì)自動(dòng)將該節(jié)點(diǎn)變?yōu)閳D層。

          • CSS3 硬件加速(GPU加速),使用css3硬件加速,可以讓transform、opacity、filters這些動(dòng)畫不會(huì)引起回流重繪 。但是對(duì)于動(dòng)畫的其它屬性,比如background-color這些,還是會(huì)引起回流重繪的,不過它還是可以提升這些動(dòng)畫的性能。

        2. JavaScript方法

          • 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。

          • 避免頻繁操作DOM,創(chuàng)建一個(gè)documentFragment,在它上面應(yīng)用所有DOM操作,最后再把它添加到文檔中。

          • 避免頻繁讀取會(huì)引發(fā)回流/重繪的屬性,如果確實(shí)需要多次使用,就用一個(gè)變量緩存起來。

        CSS3硬件加速(GPU加速)

        CSS3 硬件加速又叫做 GPU 加速,是利用 GPU 進(jìn)行渲染,減少 CPU 操作的一種優(yōu)化方案。

        render tree -> 渲染元素 -> 圖層 -> GPU 渲染 -> 瀏覽器復(fù)合圖層 -> 生成最終的屏幕圖像。

        瀏覽器在獲取 render tree后,渲染樹中包含了大量的渲染元素,每一個(gè)渲染元素會(huì)被分到一個(gè)個(gè)圖層中,每個(gè)圖層又會(huì)被加載到 GPU 形成渲染紋理。GPU 中 transform 是不會(huì)觸發(fā) repaint ,最終這些使用 transform 的圖層都會(huì)由獨(dú)立的合成器進(jìn)程進(jìn)行處理。

        CSS3觸發(fā)硬件加速的屬性:

        1. transform

        2. opacity

        3. filter

        4. will-change

        http請求方法

        HTTP1.0定義了三種請求方法:GET, POST 和 HEAD方法。
        HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

        1. OPTIONS:即預(yù)檢請求,可用于檢測服務(wù)器允許的http方法。當(dāng)發(fā)起跨域請求時(shí),由于安全原因,觸發(fā)一定條件時(shí)瀏覽器會(huì)在正式請求之前自動(dòng)先發(fā)起OPTIONS請求,即CORS預(yù)檢請求,服務(wù)器若接受該跨域請求,瀏覽器才繼續(xù)發(fā)起正式請求。

        2. HEAD: 向服務(wù)器索與GET請求相一致的響應(yīng),只不過響應(yīng)體將不會(huì)被返回,用于獲取報(bào)頭。

        3. GET:向特定的資源發(fā)出請求。注意:GET方法不應(yīng)當(dāng)被用于產(chǎn)生“副作用”的操作中

        4. POST:向指定資源提交數(shù)據(jù)進(jìn)行處理請求(例如提交表單或者上傳文件)。數(shù)據(jù)被包含在請求體中。POST請求可能會(huì)導(dǎo)致新的資源的建立和/或已有資源的修改。

        5. PUT:向指定資源位置上傳其最新內(nèi)容

        6. DELETE:請求服務(wù)器刪除Request-URL所標(biāo)識(shí)的資源

        7. TRACE:回顯服務(wù)器收到的請求,主要用于測試或診斷

        8. CONNECT:HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器

        js判斷數(shù)據(jù)類型

        1. typeof 操作符

        • 對(duì)于基本類型,除 null 以外,均可以返回正確的結(jié)果。

        • 對(duì)于引用類型,除 function 以外,一律返回 object 類型。

        • 對(duì)于 null ,返回 object 類型。

        • 對(duì)于 function 返回 function 類型。

        2. instanceof
        用來判斷 A 是否為 B 的實(shí)例,檢測的是原型。instanceof 只能用來判斷兩個(gè)對(duì)象是否屬于實(shí)例關(guān)系, 而不能判斷一個(gè)對(duì)象實(shí)例具體屬于哪種類型。
        instanceof 主要的實(shí)現(xiàn)原理就是只要右邊變量的 prototype 在左邊變量的原型鏈上即可。

        3. constructor

        • null 和 undefined 是無效的對(duì)象,不會(huì)有 constructor 存在的

        • 函數(shù)的 constructor 是不穩(wěn)定的,這個(gè)主要體現(xiàn)在自定義對(duì)象上,當(dāng)開發(fā)者重寫 prototype 后,原有的 constructor 引用會(huì)丟失,constructor 會(huì)默認(rèn)為 Object。為了規(guī)范開發(fā),在重寫對(duì)象原型時(shí)一般都需要重新給 constructor 賦值。

        4. toString

        toString() 是 Object 的原型方法,調(diào)用該方法,默認(rèn)返回當(dāng)前對(duì)象的 [[Class]] 。這是一個(gè)內(nèi)部屬性,其格式為 [object Xxx] ,其中 Xxx 就是對(duì)象的類型。

        瀏覽器事件模型

        DOM事件流(event flow )存在三個(gè)階段:事件捕獲階段、處于目標(biāo)階段、事件冒泡階段。

        // useCapture:true, 即采用事件捕獲方式window.addEventListener("click", function(e){  console.log("window 捕獲");}, true);
        // useCapture:false【默認(rèn)為false】,即采用事件冒泡方式window.addEventListener("click", function(e){ console.log("window 冒泡");}, false);

        目標(biāo)元素(被點(diǎn)擊的元素)綁定的事件都會(huì)發(fā)生在目標(biāo)階段,在綁定捕獲代碼之前寫了綁定的冒泡階段的代碼,所以在目標(biāo)元素上就不會(huì)遵守先發(fā)生捕獲后發(fā)生冒泡這一規(guī)則,而是先綁定的事件先發(fā)生。

        不是目標(biāo)元素,它上面綁定的事件會(huì)遵守先發(fā)生捕獲后發(fā)生冒泡的規(guī)則。

        e.stopPropagation():阻止事件傳播。不僅可以阻止事件在冒泡階段的傳播,還能阻止事件在捕獲階段的傳播。
        e.preventDefault(): 阻止事件的默認(rèn)行為。默認(rèn)行為是指:點(diǎn)擊a標(biāo)簽就轉(zhuǎn)跳到其他頁面、拖拽一個(gè)圖片到瀏覽器會(huì)自動(dòng)打開、點(diǎn)擊表單的提交按鈕會(huì)提交表單等

        http緩存: 強(qiáng)制緩存和協(xié)商緩存

        良好的緩存策略可以降低資源的重復(fù)加載提高網(wǎng)頁的整體加載速度。

        緩存原理

        1. 瀏覽器在加載資源時(shí),根據(jù)請求頭的expires和cache-control判斷是否命中強(qiáng)緩存,是則直接從緩存讀取資源,不會(huì)發(fā)請求到服務(wù)器。

        2. 如果沒有命中強(qiáng)緩存,瀏覽器會(huì)發(fā)送一個(gè)請求到服務(wù)器,通過last-modified和etag驗(yàn)證是否命中協(xié)商緩存。當(dāng)向服務(wù)端發(fā)起緩存校驗(yàn)的請求時(shí),服務(wù)端會(huì)返回 200 ok表示返回正常的結(jié)果或者 304 Not Modified(不返回body)表示瀏覽器可以使用本地緩存文件。304的響應(yīng)頭也可以同時(shí)更新緩存文檔的過期時(shí)間

        3. 如果前面兩者都沒有命中,直接從服務(wù)器加載資源。

        實(shí)現(xiàn)方式

        強(qiáng)緩存通過Expires和Cache-Control實(shí)現(xiàn)。
        協(xié)商緩存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】這兩對(duì)Header來管理的。

        Expires
        Expires是http1.0提出的一個(gè)表示資源過期時(shí)間的header,它是一個(gè)絕對(duì)時(shí)間,由服務(wù)器返回。Expires 受限于本地時(shí)間,如果修改了本地時(shí)間,可能會(huì)造成緩存失效。
        Expires: Wed, 11 May 2018 07:20:00 GMT

        Cache-Control
        Cache-Control 出現(xiàn)于 HTTP / 1.1,優(yōu)先級(jí)高于 Expires , 表示的是相對(duì)時(shí)間。

        no-store:沒有緩存。緩存中不得存儲(chǔ)任何關(guān)于客戶端請求和服務(wù)端響應(yīng)的內(nèi)容。每次由客戶端發(fā)起的請求都會(huì)下載完整的響應(yīng)內(nèi)容。no-cache: 緩存但重新驗(yàn)證。每次有請求發(fā)出時(shí),緩存會(huì)將此請求發(fā)到服務(wù)器(譯者注:該請求應(yīng)該會(huì)帶有與本地緩存相關(guān)的驗(yàn)證字段),服務(wù)器端會(huì)驗(yàn)證請求中所描述的緩存是否過期,若未過期(返回304),則緩存才使用本地緩存副本。private:只允許客戶端瀏覽器緩存。public: 允許所有用戶緩存。例如中間代理、CDN等max-age=<seconds>:表示資源能夠被緩存的最大時(shí)間。相對(duì)Expires而言,max-age是距離請求發(fā)起的時(shí)間的秒數(shù)。針對(duì)應(yīng)用中那些不會(huì)改變的文件,通??梢允謩?dòng)設(shè)置一定的時(shí)長以保證緩存有效,例如圖片、css、js等靜態(tài)資源。must-revalidate:觸發(fā)緩存驗(yàn)證。驗(yàn)證它的狀態(tài),已過期的緩存將不被使用

        Last-Modified,If-Modified-Since
        Last-Modifie表示本地文件最后修改日期,瀏覽器會(huì)在request header加 If-Modified-Since(上次返回的Last-Modified的值),詢問服務(wù)器在該日期后資源是否有更新,有更新的話就會(huì)將新的資源發(fā)送回來。

        但是如果在本地打開緩存文件,就會(huì)造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現(xiàn)了 ETag。

        ETag、If-None-Match
        Etag就像一個(gè)指紋,資源變化都會(huì)導(dǎo)致ETag變化,跟最后修改時(shí)間沒有關(guān)系,ETag可以保證每一個(gè)資源是唯一的。

        If-None-Match的header會(huì)將上次返回的Etag發(fā)送給服務(wù)器,詢問該資源的Etag是否有更新,有變動(dòng)就會(huì)發(fā)送新的資源回來。

        ETag的優(yōu)先級(jí)比Last-Modified更高。

        具體為什么要用ETag,主要出于下面幾種情況考慮:

        • 一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間),這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;

        • 某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級(jí)的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);

        • 某些服務(wù)器不能精確的得到文件的最后修改時(shí)間。

        防抖和節(jié)流

        防抖:當(dāng)你在頻繁調(diào)用方法時(shí),并不會(huì)執(zhí)行,只有當(dāng)你在指定間隔內(nèi)沒有再調(diào)用,才會(huì)執(zhí)行函數(shù)。
        節(jié)流:在一個(gè)單位時(shí)間內(nèi),只能觸發(fā)一次函數(shù)。如果這個(gè)單位時(shí)間內(nèi)觸發(fā)多次函數(shù),只有一次生效。

        防抖

        function debounce(fn, wait) {  let time = null;
        return (function() { const context = this; const args = arguments;
        if (time) { clearTimeout(time); time = null; } time = setTimeout(() => { fn.call(context, args); }, wait); });}

        節(jié)流

        function throttle(fn, wait) {  let lastTime;
        return ( function() { const context = this; const args = arguments; let nowTime = + new Date();
        if (nowTime > lastTime + wait || !lastTime) { fn.call(context, args); lastTime = nowTime; } } );

        大小單位區(qū)別

        px:像素。
        em:參考物是父元素的font-size,具有繼承的特點(diǎn)。如果自身定義了font-size按自身來計(jì)算,整個(gè)頁面內(nèi)1em不是一個(gè)固定的值。
        rem:相對(duì)于根元素html的font-size計(jì)算,不會(huì)像em那樣,依賴于父元素的字體大小,而造成混亂。
        vw:視窗寬度,1vw等于視窗寬度的1%。
        vh:視窗高度,1vh等于視窗高度的1%。
        vm:min(vw, vh)。
        %:是相對(duì)于父元素的大小設(shè)定的比率,position:absolute;的元素是相對(duì)于已經(jīng)定位的父元素,position:fixed;的元素是相對(duì)可視窗口。
        瀏覽器默認(rèn)字體是16px, body設(shè)置font-size:62.5%, 那么1rem =62.5% * 16=10px 。
        谷歌瀏覽器強(qiáng)制最小字體為12號(hào),即使設(shè)置成 10px 最終都會(huì)顯示成 12px,當(dāng)把html的font-size設(shè)置成10px,子節(jié)點(diǎn)rem的計(jì)算還是以12px為基準(zhǔn)。

        Box-sizing

        • content-box:這是默認(rèn)情況,整個(gè)元素的高度和寬度就是元素內(nèi)容

        • border-box:這種情況下,你設(shè)置的width和height屬性值就是針對(duì)整個(gè)元素,包括了border,padding,和元素內(nèi)容。

        函數(shù)聲明和函數(shù)表達(dá)式

        // 函數(shù)聲明function wscat(type){  return 'wscat';}
        // 函數(shù)表達(dá)式var oaoafly = function(type){ return "oaoafly";}
        • JavaScript 解釋器中存在一種變量聲明被提升的機(jī)制,也就是說函數(shù)聲明會(huì)被提升到作用域的最前面,即使寫代碼的時(shí)候是寫在最后面,也還是會(huì)被提升至最前面。

        • 用函數(shù)表達(dá)式創(chuàng)建的函數(shù)是在運(yùn)行時(shí)進(jìn)行賦值,且要等到表達(dá)式賦值完成后才能調(diào)用

        函數(shù)聲明在JS解析時(shí)進(jìn)行函數(shù)提升,因此在同一個(gè)作用域內(nèi),不管函數(shù)聲明在哪里定義,該函數(shù)都可以進(jìn)行調(diào)用。而函數(shù)表達(dá)式的值是在JS運(yùn)行時(shí)確定,并且在表達(dá)式賦值完成后,該函數(shù)才能調(diào)用。這個(gè)微小的區(qū)別,可能會(huì)導(dǎo)致JS代碼出現(xiàn)意想不到的bug,讓你陷入莫名的陷阱中。

        事件循環(huán)EventLoop

        JavaScript是一個(gè)單線程的腳本語言。

        所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧 (Execution Context Stack);而異步任務(wù)會(huì)被放置到 Task Table(異步處理模塊),當(dāng)異步任務(wù)有了運(yùn)行結(jié)果,就將注冊的回調(diào)函數(shù)移入任務(wù)隊(duì)列(兩種隊(duì)列)。

        一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,引擎就會(huì)讀取任務(wù)隊(duì)列,然后將任務(wù)隊(duì)列中的第一個(gè)任務(wù)取出放到執(zhí)行棧中運(yùn)行。(所有會(huì)進(jìn)入的異步都是指的事件回調(diào)中的那部分代碼)

        只要主線程空了,就會(huì)去讀取任務(wù)隊(duì)列,該過程不斷重復(fù),這就是所謂的 事件循環(huán)。

        宏任務(wù)和微任務(wù)

        宏任務(wù)會(huì)進(jìn)入一個(gè)隊(duì)列,微任務(wù)會(huì)進(jìn)入到另一個(gè)隊(duì)列,且微任務(wù)要優(yōu)于宏任務(wù)執(zhí)行。
        宏任務(wù):script(整體代碼)、setTimeout、setInterval、I/O、事件、postMessage、 MessageChannel、setImmediate (Node.js)
        微任務(wù):Promise.then、 MutaionObserver、process.nextTick (Node.js)

        宏任務(wù)會(huì)進(jìn)入一個(gè)隊(duì)列,而微任務(wù)會(huì)進(jìn)入到另一個(gè)不同的隊(duì)列,且微任務(wù)要優(yōu)于宏任務(wù)執(zhí)行。

        Promise

        1. Promise.all: 全部fulfilled,  才進(jìn)入then, 否則 catch2. Promise.race: 任一個(gè)返回,不管是fulfilled還是rejected,  進(jìn)入相應(yīng)的then/catch3. Promise.allSettled: 全部返回,不管是fulfilled還是rejected,  進(jìn)入then4. Promise.any: 任一個(gè)返回fulfilled,  就進(jìn)入then, 否則 catch

        虛擬dom原理

        Virtual DOM是對(duì)DOM的抽象,本質(zhì)上是JavaScript對(duì)象,這個(gè)對(duì)象就是更加輕量級(jí)的對(duì)DOM的描述.

        箭頭函數(shù)與普通函數(shù)區(qū)別

        • 語法更加簡潔、清晰

        • 不綁定this,會(huì)捕獲其所在的上下文的this值,作為自己的this值

        • 箭頭函數(shù)繼承而來的this指向永遠(yuǎn)不變

        • .call()/.apply()/.bind()無法改變箭頭函數(shù)中this的指向

        • 不能作為構(gòu)造函數(shù)使用, 因?yàn)闆]有自己的 this,無法調(diào)用 call,apply;沒有 prototype 屬性 ,而 new 命令在執(zhí)行時(shí)需要將構(gòu)造函數(shù)的 prototype 賦值給新的對(duì)象的__prpto__ 。

        • 沒有自己的arguments,在箭頭函數(shù)中訪問arguments實(shí)際上獲得的是外層局部(函數(shù))執(zhí)行環(huán)境中的值。如果要用,可以用 rest 參數(shù)代替。

        • 沒有原型prototype, 指向 undefined

        • 不能使用yeild關(guān)鍵字

        new

        new 關(guān)鍵字會(huì)進(jìn)行如下的操作:

        1. 創(chuàng)建一個(gè)空的簡單JavaScript對(duì)象(即{});

        2. 鏈接該對(duì)象(設(shè)置該對(duì)象的__proto__)到構(gòu)造器函數(shù)的原型 ;

        3. 將新創(chuàng)建的對(duì)象作為this的上下文 ;

        4. 返回。如果該函數(shù)沒有返回對(duì)象,則返回this。

        function newFunc(father, ...rest) {  // 首先創(chuàng)建一個(gè)空對(duì)象  var result = {};  // 將空對(duì)象的原型賦值為構(gòu)造器函數(shù)的原型  result.__proto__ = father.prototype;  // 更改構(gòu)造器函數(shù)內(nèi)部this,將其指向新創(chuàng)建的空對(duì)象  var result2 = father.apply(result, rest);
        if ((typeof result2 === 'object' || typeof result2 === 'function') && result2 !== null) { return result2; } return result;}


        水平與垂直居中實(shí)現(xiàn)方式

        水平居中

        • text-align: center; 行內(nèi)元素適用

        • margin: 0 auto; 適用塊級(jí)元素

        • width: fit-content; 若子元素包含 float:left 屬性, 為了讓子元素水平居中, 則可讓父元素寬度設(shè)置為fit-content, 并且配合margin。

        .parent {  width:fit-content;  margin:0 auto;}
        • flex

        .parent {  display: flex;  justify-content: center;}
        • 盒模型, 使用flex 2009年版本

        .parent {  display: box;  box-orient: horizontal;  box-pack: center;}
        • transform

        .son {  position: absolute;  left: 50%;  transform: translate(-50%, 0);}
        • 兩種不同的絕對(duì)定位方法

        .son {  position: absolute;  width: 固定;  left: 50%;  margin-left: -0.5 * 寬度;}
        .son { position: absolute; width: 固定; left: 0; right: 0; margin: 0 auto;}

        垂直居中

        • 單行文本, line-height

        • 行內(nèi)塊級(jí)元素, 使用 display: inline-block, vertical-align: middle; 加上偽元素輔助實(shí)現(xiàn)

        .parent::after, .son {    display:inline-block;    vertical-align:middle;}.parent::after {    content:'';    height:100%;}
        • vertical-align。vertical-align只有在父層為 td 或者 th 時(shí), 才會(huì)生效, 對(duì)于其他塊級(jí)元素, 例如 div、p 等, 默認(rèn)情況是不支持的. 為了使用vertical-align, 我們需要設(shè)置父元素display:table, 子元素 display:table-cell;vertical-align:middle;

        • flex

        .parent {  display: flex;  align-items: center;}
        • 盒模型

        .parent {  display: box;  box-orient: vertical;  box-pack: center;}
        • transform

        .son {  position: absolute;  top: 50%;  transform: translate(0, -50%);}
        • 兩種不同的絕對(duì)定位方法

        .son {  position: absolute;  height: 固定;  top: 50%;  margin-top: -0.5 * height;}
        .son { position: absolute; height: 固定; top: 0; bottom: 0; margin: auto 0;}

        flex, 盒模型, transform, 絕對(duì)定位, 這幾種方法同時(shí)適用于水平居中和垂直居中

        排序

        冒泡排序

        function bubbleSort(arr) {  const len = arr.length;  for (let i = 0; i < len - 1; i++) {    for (let j = i + 1; j < len; j++) {      if (arr[j] < arr[i]) {        [arr[j], arr[i]] = [arr[i], arr[j]];      }    }  }  return arr;}

        選擇排序

        選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最?。ù螅┰兀缓蠓诺揭雅判蛐蛄械哪┪?。以此類推,直到所有元素均排序完畢。

        function selectionSort(arr) {  const len = arr.length;  for (let i = 0; i < len - 1; i++) {    let index = i;    for (let j = i + 1; j < len; j++) {      if (arr[j] < arr[index]) {        index = j;      }    }    if (index !== i) {      [arr[i], arr[index]] = [arr[index], arr[i]];    }  }  return arr;}

        插入排序

        插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構(gòu)建有序序列,對(duì)于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。

        插入排序在實(shí)現(xiàn)上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復(fù)把已排序元素逐步向后挪位,為最新元素提供插入空間。

        function insertionSort(arr) {  const len = arr.length;  for (let i = 1; i < len; i++) {    let j = i - 1;    const value = arr[i];    while (arr[j] > value && j >= 0) {      arr[j + 1] = arr[j];      j--;    }    arr[j + 1] = value;  }  return arr;}

        歸并排序

        歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。歸并排序是一種穩(wěn)定的排序方法。先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為2-路歸并。

        function mergeSort(arr) {  //采用自上而下的遞歸方法  var len = arr.length;  if (len < 2) return arr;
        const middle = Math.floor(len / 2); let left = arr.slice(0, middle); let right = arr.slice(middle); return merge(mergeSort(left), mergeSort(right));}
        function merge(left, right) { let result = []; while (left.length && right.length) { if (left[0] <= right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right);}

        快速排序

        快速排序的基本思想:通過一趟排序?qū)⒋庞涗浄指舫瑟?dú)立的兩部分,其中一部分記錄的關(guān)鍵字均比另一部分的關(guān)鍵字小,則可分別對(duì)這兩部分記錄繼續(xù)進(jìn)行排序,以達(dá)到整個(gè)序列有序。

        function quickSort(arr) {  if (arr.length <= 1) return arr;  const pivotIndex = Math.floor(arr.length / 2);  const pivot = arr.splice(pivotIndex, 1)[0];  let left = [];  let right = [];  for (let i = 0; i < arr.length; i++){    if (arr[i] < pivot) {      left.push(arr[i]);    } else {      right.push(arr[i]);    }  }  return quickSort(left).concat([pivot], quickSort(right));};};
        洗牌算法

        function shuffle(arr){  const length = arr.length;  while (length > 0) {    const random = Math.floor(Math.random() * length);    length--;    [arr[length], arr[random]] = [arr[random], arr[length]];  }  return arr;}
        // 或arr.sort(function(){ return .5 - Math.random();});

        本文完?

        瀏覽 56
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        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>
            麻豆一区二区99久久久久 | 看逼的视频 | 色戒未删减免费在线观看完整版 | 成年人在线观看网站 | 日本xxxxxxxxx68中国 | 欧美日韩一二 | 18禁超污无遮挡无码黄网站 | 日韩欧美一级精品久久 | 中文字幕一区日韩精品欧美 | 骚屄视频 |