web前端面经
注冊(cè)登錄是怎么實(shí)現(xiàn)的
1.登陸注冊(cè)要做成受控組件,組件定義state,和表單綁定2.redux-saga調(diào)用數(shù)據(jù)請(qǐng)求,發(fā)送action修改數(shù)據(jù),useEffect中dispatch發(fā)送數(shù)據(jù)請(qǐng)求,后端比對(duì)用戶名是否重復(fù),返回state3.前端根據(jù)返回的信息成功跳轉(zhuǎn)登陸頁4.登陸發(fā)送數(shù)據(jù)請(qǐng)求,數(shù)據(jù)庫對(duì)比用戶名密碼是否正確, 根據(jù)后端返回的結(jié)果進(jìn)入首頁5.setCookie將用戶登錄名密碼token存cookie中 通過JWT(Json web token)6.免密登陸 getCookie獲取token 發(fā)給后端對(duì)比 根據(jù)返回結(jié)果是否自動(dòng)登陸7.注冊(cè)通過Ant Design ,validator中進(jìn)行表單正則的驗(yàn)證8.用戶體驗(yàn) 注冊(cè)的時(shí)候跳轉(zhuǎn)其他頁面的時(shí)候給用戶提示是否需要跳轉(zhuǎn),避免因?yàn)樘D(zhuǎn)后導(dǎo)致注冊(cè)信息沒有了 用組件內(nèi)后置守衛(wèi)做如果輸入框都沒有填信息,不攔截跳轉(zhuǎn)如果用戶輸入信息,彈窗提示,點(diǎn)確定,跳轉(zhuǎn),點(diǎn)取消,不跳轉(zhuǎn)項(xiàng)目中遇到什么困難,怎么解決的?
1.react中配置二級(jí)路由 地址變化 但是界面不更新 使用dva/router中的withRouter高階組件解決的2.圖表聯(lián)動(dòng)怎么實(shí)現(xiàn)我們只需要把當(dāng)前被選中圖表的事件,直接發(fā)給其他圖表即可,然后判斷被選中的圖表是哪個(gè)作為區(qū)分onTouchEvent(event)普通事件傳遞3.產(chǎn)品經(jīng)理要求智能匹配產(chǎn)品 找網(wǎng)上類似功能的網(wǎng)站 查看源碼 和主管討論需要一個(gè)設(shè)計(jì)一個(gè)投資習(xí)慣和風(fēng)險(xiǎn)承受能力測試,從后端獲取這個(gè)客戶測試的結(jié)果 以及客戶平常投資的習(xí)慣 生成不同的關(guān)鍵字根據(jù)關(guān)鍵字從數(shù)據(jù)庫中匹配產(chǎn)品 展示界面4.后臺(tái)管理系統(tǒng)遇到遇到什么奇葩的需求后臺(tái)管理系統(tǒng)和普通App面向用戶的區(qū)別
toB和toC的項(xiàng)目面向企業(yè)內(nèi)部和面向用戶的項(xiàng)目的區(qū)別后臺(tái)管理系統(tǒng)權(quán)限比較細(xì) App高并發(fā)比較多 做性能優(yōu)化正則表達(dá)式
\d 匹配數(shù)字 \D 匹配非數(shù)字 \w 匹配數(shù)字字母下劃線 \W 匹配非數(shù)字字母下劃線 \n 匹配一個(gè)換行符 \s 匹配任何不可見字符包括空格、制表符、換頁符等等 \S 匹配任何可見字符 ^ 匹配輸入字行首 $匹配輸入行尾 *(0到多次)匹配前面的子表達(dá)式任意次 +(1到多) 匹配前面的子表達(dá)式一次或多次(大于等于1次) ?(0或1)匹配前面的子表達(dá)式零次或一次 {n}n是一個(gè)非負(fù)整數(shù),匹配確定的n次 {n,}n是一個(gè)非負(fù)整數(shù)。至少匹配n次Ajax
我對(duì) ajax 的理解是,它是一種異步通信的方法,通過直接由 js 腳本向服務(wù)器發(fā)起 http 通信,然后根據(jù)服務(wù)器返回的數(shù)據(jù),更新網(wǎng)頁的相應(yīng)部分,而不用刷新整個(gè)頁面的一種方法。 創(chuàng)建步驟:創(chuàng)建xhr對(duì)象->配置Ajax請(qǐng)求地址通過open方法->發(fā)送請(qǐng)求通過send方法->監(jiān)聽請(qǐng)求,接收響應(yīng) //1:創(chuàng)建Ajax對(duì)象 var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// 兼容IE6及以下版本 //2:配置 Ajax請(qǐng)求地址 xhr.open('get','index.xml',true); //3:發(fā)送請(qǐng)求 xhr.send(null); // 嚴(yán)謹(jǐn)寫法 //4:監(jiān)聽請(qǐng)求,接受響應(yīng) xhr.onreadysatechange=function(){if(xhr.readySate==4&&xhr.status==200 || xhr.status==304)console.log(xhr.responseXML) }js 延遲加載的方式
js 的加載、解析和執(zhí)行會(huì)阻塞頁面的渲染過程,因此我們希望 js 腳本能夠盡可能的延遲加載,提高頁面的渲染速度。 我了解到的幾種方式是:1、將 js 腳本放在文檔的底部,來使 js 腳本盡可能的在最后來加載執(zhí)行。 2、給 js 腳本添加 defer 屬性,這個(gè)屬性會(huì)讓腳本的加載與文檔的解析同步解析,然后在文檔解析完成后再執(zhí)行這個(gè)腳本文件,這樣的話就能使頁面的渲染不被阻塞。多個(gè)設(shè)置了 defer 屬性的腳本按規(guī)范來說最后是順序執(zhí)行的,但是在一些瀏覽器中可能不是這樣。 3、給 js 腳本添加 async屬性,這個(gè)屬性會(huì)使腳本異步加載,不會(huì)阻塞頁面的解析過程,但是當(dāng)腳本加載完成后立即執(zhí)行 js腳本,這個(gè)時(shí)候如果文檔沒有解析完成的話同樣會(huì)阻塞。多個(gè) async 屬性的腳本的執(zhí)行順序是不可預(yù)測的,一般不會(huì)按照代碼的順序依次執(zhí)行。 4、動(dòng)態(tài)創(chuàng)建 DOM 標(biāo)簽的方式,我們可以對(duì)文檔的加載事件進(jìn)行監(jiān)聽,當(dāng)文檔加載完成后再動(dòng)態(tài)的創(chuàng)建 script 標(biāo)簽來引入 js 腳本。模塊化開發(fā)的理解
我對(duì)模塊的理解是,一個(gè)模塊是實(shí)現(xiàn)一個(gè)特定功能的一組方法。在最開始的時(shí)候,js 只實(shí)現(xiàn)一些簡單的功能, 所以并沒有模塊的概念,但隨著程序越來越復(fù)雜,代碼的模塊化開發(fā)變得越來越重要。由于函數(shù)具有獨(dú)立作用域的特點(diǎn),最原始的寫法是使用函數(shù)來作為模塊,幾個(gè)函數(shù)作為一個(gè)模塊, 但是這種方式容易造成全局變量的污染,并且模塊間沒有聯(lián)系。后面提出了對(duì)象寫法,通過將函數(shù)作為一個(gè)對(duì)象的方法來實(shí)現(xiàn),這樣解決了直接使用函數(shù)作為模塊的一些缺點(diǎn), 但是這種辦法會(huì)暴露所有的所有的模塊成員,外部代碼可以修改內(nèi)部屬性的值。現(xiàn)在最常用的是立即執(zhí)行函數(shù)的寫法,通過利用閉包來實(shí)現(xiàn)模塊私有作用域的建立,同時(shí)不會(huì)對(duì)全局作用域造成污染。js 的幾種模塊規(guī)范
js 中現(xiàn)在比較成熟的有四種模塊加載方案:第一種是 CommonJS 方案,它通過 require 來引入模塊,通過 module.exports 定義模塊的輸出接口。這種模塊加載方案是服務(wù)器端的解決方案,它是以同步的方式來引入模塊的,因?yàn)樵诜?wù)端文件都存儲(chǔ)在本地磁盤,所以讀取非常快,所以以同步的方式加載沒有問題。但如果是在瀏覽器端,由于模塊的加載是使用網(wǎng)絡(luò)請(qǐng)求,因此使用異步加載的方式更加合適。第二種是 AMD 方案,這種方案采用異步加載的方式來加載模塊,模塊的加載不影響后面語句的執(zhí)行,所有依賴這個(gè)模塊的語句都定義在一個(gè)回調(diào)函數(shù)里,等到加載完成后再執(zhí)行回調(diào)函數(shù)。require.js 實(shí)現(xiàn)了 AMD 規(guī)范。第三種是 CMD 方案,這種方案和 AMD 方案都是為了解決異步模塊加載的問題,sea.js 實(shí)現(xiàn)了 CMD 規(guī)范。它和require.js的區(qū)別在于模塊定義時(shí)對(duì)依賴的處理不同和對(duì)依賴模塊的執(zhí)行時(shí)機(jī)的處理不同。第四種方案是 ES6 提出的方案,使用 import 和 export 的形式來導(dǎo)入導(dǎo)出模塊。AMD和CMD規(guī)范的區(qū)別?
它們之間的主要區(qū)別有兩個(gè)方面。 第一個(gè)方面是在模塊定義時(shí)對(duì)依賴的處理不同。AMD推崇依賴前置,在定義模塊的時(shí)候就要聲明其依賴的模塊。而 CMD 推崇就近依賴,只有在用到某個(gè)模塊的時(shí)候再去 require。 第二個(gè)方面是對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同。首先 AMD 和 CMD 對(duì)于模塊的加載方式都是異步加載,不過它們的區(qū)別在于模塊的執(zhí)行時(shí)機(jī),AMD 在依賴模塊加載完成后就直接執(zhí)行依賴模塊,依賴模塊的執(zhí)行順序和我們書寫的順序不一定一致。而 CMD在依賴模塊加載完成后并不執(zhí)行,只是下載而已,等到所有的依賴模塊都加載好后,進(jìn)入回調(diào)函數(shù)邏輯,遇到 require 語句 的時(shí)候才執(zhí)行對(duì)應(yīng)的模塊,這樣模塊的執(zhí)行順序就和我們書寫的順序保持一致了。ES6模塊與CommonJS 模塊、AMD、CMD的差異
1.CommonJS 模塊輸出的是一個(gè)值的拷貝, ES6 模塊輸出的是值的引用。 CommonJS 模塊輸出的是值的,也就是說,一旦輸出一個(gè)值,模塊內(nèi)部的變化就影響不到這個(gè)值。 ES6 模塊的運(yùn)行機(jī)制與 CommonJS 不一樣。JS 引擎對(duì)腳本靜態(tài)分析的時(shí)候,遇到模塊加載命令 import,就會(huì)生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。 2.CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。CommonJS 模塊就是對(duì)象,即在輸入時(shí)是先加載整個(gè)模塊,生成一個(gè)對(duì)象,然后再從這個(gè)對(duì)象上面讀取方法,這種加載稱為“運(yùn)行時(shí)加載”。 而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。requireJS的核心原理
require.js 的核心原理是通過動(dòng)態(tài)創(chuàng)建 script 腳本來異步引入模塊,然后對(duì)每個(gè)腳本的 load 事件進(jìn)行監(jiān)聽,如果每個(gè)腳本都加載完成了,再調(diào)用回調(diào)函數(shù)js的原理(運(yùn)行機(jī)制)
首先js是單線程運(yùn)行的,在代碼執(zhí)行的時(shí)候,通過將不同函數(shù)的執(zhí)行上下文壓入執(zhí)行棧中來保證代碼的有序執(zhí)行。 在執(zhí)行同步代碼的時(shí)候,如果遇到了異步事件,js引擎并不會(huì)一直等待其返回結(jié)果,而是會(huì)將這個(gè)事件掛起,繼續(xù)執(zhí)行執(zhí)行棧中的其他任務(wù)所有任務(wù)可以分成兩種,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)。 同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù); 異步任務(wù)指的是,不進(jìn)入主線程、而進(jìn)入"任務(wù)隊(duì)列"(task queue)的任務(wù),只有等主線程任務(wù)執(zhí)行完畢,"任務(wù)隊(duì)列"開始通知主線程,請(qǐng)求執(zhí)行任務(wù),該任務(wù)才會(huì)進(jìn)入主線程執(zhí)行。當(dāng)同步事件執(zhí)行完畢后,再將異步事件對(duì)應(yīng)的回調(diào)加入到與當(dāng)前執(zhí)行棧中不同的另一個(gè)任務(wù)隊(duì)列中等待執(zhí)行。 任務(wù)隊(duì)列可以分為宏任務(wù)對(duì)列和微任務(wù)對(duì)列,當(dāng)當(dāng)前執(zhí)行棧中的事件執(zhí)行完畢后,js 引擎首先會(huì)判斷微任務(wù)對(duì)列中是否有任務(wù)可以執(zhí)行,如果有就將微任務(wù)隊(duì)首的事件壓入棧中執(zhí)行。 當(dāng)微任務(wù)對(duì)列中的任務(wù)都執(zhí)行完成后再去判斷宏任務(wù)對(duì)列中的任務(wù)。異步運(yùn)行機(jī)制如下: (1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)。 (2)主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件。 (3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列",看看里面有哪些事件。那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。 (4)主線程不斷重復(fù)上面的第三步。arguments 的對(duì)象
arguments對(duì)象是函數(shù)中傳遞的參數(shù)值的集合。它是一個(gè)類似數(shù)組的對(duì)象,因?yàn)樗幸粋€(gè)length屬性, 我們可以使用數(shù)組索引表示法arguments[1]來訪問單個(gè)值,但它沒有數(shù)組中的內(nèi)置方法, 如:forEach、reduce、filter和map。我們可以使用Array.prototype.slice將arguments對(duì)象轉(zhuǎn)換成一個(gè)數(shù)組。Array.prototype.slice.call(arguments)V8 引擎的垃圾回收機(jī)制
v8的垃圾回收機(jī)制基于分代回收機(jī)制,這個(gè)機(jī)制又基于世代假說,這個(gè)假說有兩個(gè)特點(diǎn),一是新生的對(duì)象容易早死,另一個(gè)是不死的對(duì)象會(huì)活得更久。基于這個(gè)假說,v8 引擎將內(nèi)存分為了新生代和老生代。 新創(chuàng)建的對(duì)象或者只經(jīng)歷過一次的垃圾回收的對(duì)象被稱為新生代。經(jīng)歷過多次垃圾回收的對(duì)象被稱為老生代。 新生代被分為 From 和 To 兩個(gè)空間,To 一般是閑置的。當(dāng) From 空間滿了的時(shí)候會(huì)執(zhí)行 Scavenge(斯蓋V橘) 算法進(jìn)行垃圾回收。當(dāng)我們執(zhí)行垃圾回收算法的時(shí)候應(yīng)用邏輯將會(huì)停止,等垃圾回收結(jié)束后再繼續(xù)執(zhí)行。這個(gè)算法分為三步: (1)首先檢查 From 空間的存活對(duì)象,如果對(duì)象存活則判斷對(duì)象是否滿足晉升到老生代的條件,如果滿足條件則晉升到老生代。如果不滿足條件則移動(dòng) To 空間。 (2)如果對(duì)象不存活,則釋放對(duì)象的空間。 (3)最后將 From 空間和 To 空間角色進(jìn)行交換。 新生代對(duì)象晉升到老生代有兩個(gè)條件: (1)第一個(gè)是判斷是對(duì)象否已經(jīng)經(jīng)過一次 Scavenge 回收。若經(jīng)歷過,則將對(duì)象從 From 空間復(fù)制到老生代中;若沒有經(jīng)歷,則復(fù)制到 To 空間。 (2)第二個(gè)是 To 空間的內(nèi)存使用占比是否超過限制。當(dāng)對(duì)象從 From 空間復(fù)制到 To 空間時(shí),若 To 空間使用超過 25%,則對(duì)象直接晉升到老生代中。設(shè)置 25% 的原因主要是因?yàn)樗惴ńY(jié)束后,兩個(gè)空間結(jié)束后會(huì)交換位置,如果 To 空間的內(nèi)存太小,會(huì)影響后續(xù)的內(nèi)存分配。老生代采用了標(biāo)記清除法和標(biāo)記壓縮法。 標(biāo)記清除法首先會(huì)對(duì)內(nèi)存中存活的對(duì)象進(jìn)行標(biāo)記,標(biāo)記結(jié)束后清除掉那些沒有標(biāo)記的對(duì)象。由于標(biāo)記清除后會(huì)造成很多的內(nèi)存碎片,不便于后面的內(nèi)存分配。所以了解決內(nèi)存碎片的問題引入了標(biāo)記壓縮法。 由于在進(jìn)行垃圾回收的時(shí)候會(huì)暫停應(yīng)用的邏輯,對(duì)于新生代方法由于內(nèi)存小,每次停頓的時(shí)間不會(huì)太長,但對(duì)于老生代來說每次垃圾回收的時(shí)間長,停頓會(huì)造成很大的影響。 為了解決這個(gè)問題 V8 引入了增量標(biāo)記的方法,將一次停頓進(jìn)行的過程分為了多步,每次執(zhí)行完一小步就讓運(yùn)行邏輯執(zhí)行一會(huì),就這樣交替運(yùn)行垃圾回收機(jī)制的兩種方法
現(xiàn)在各大瀏覽器通常用采用的垃圾回收有兩種方法:標(biāo)記清除、引用計(jì)數(shù)。1、標(biāo)記清除這是javascript中最常用的垃圾回收方式。當(dāng)變量進(jìn)入執(zhí)行環(huán)境是,就標(biāo)記這個(gè)變量為“進(jìn)入環(huán)境”。從邏輯上講,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存,因?yàn)橹灰獔?zhí)行流進(jìn)入相應(yīng)的環(huán)境,就可能會(huì)用到他們。當(dāng)變量離開環(huán)境時(shí),則將其標(biāo)記為“離開環(huán)境”。垃圾收集器在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。然后,它會(huì)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的標(biāo)記。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后。垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值,并回收他們所占用的內(nèi)存空間。2、引用計(jì)數(shù)另一種不太常見的垃圾回收策略是引用計(jì)數(shù)。引用計(jì)數(shù)的含義是跟蹤記錄每個(gè)值被引用的次數(shù)。當(dāng)聲明了一個(gè)變量并將一個(gè)引用類型賦值給該變量時(shí),則這個(gè)值的引用次數(shù)就是1。相反,如果包含對(duì)這個(gè)值引用的變量又取得了另外一個(gè)值,則這個(gè)值的引用次數(shù)就減1。當(dāng)這個(gè)引用次數(shù)變成0時(shí),則說明沒有辦法再訪問這個(gè)值了,因而就可以將其所占的內(nèi)存空間給收回來。這樣,垃圾收集器下次再運(yùn)行時(shí),它就會(huì)釋放那些引用次數(shù)為0的值所占的內(nèi)存。會(huì)造成內(nèi)存泄漏的操作
1.意外的全局變量 2.被遺忘的計(jì)時(shí)器或回調(diào)函數(shù) 3.脫離 DOM 的引用 4.閉包第一種情況是我們由于使用未聲明的變量,而意外的創(chuàng)建了一個(gè)全局變量,而使這個(gè)變量一直留在內(nèi)存中無法被回收。 第二種情況是我們?cè)O(shè)置了setInterval定時(shí)器,而忘記取消它,如果循環(huán)函數(shù)有對(duì)外部變量的引用的話,那么這個(gè)變量會(huì)被一直留在內(nèi)存中,而無法被回收。 第三種情況是我們獲取一個(gè)DOM元素的引用,而后面這個(gè)元素被刪除,由于我們一直保留了對(duì)這個(gè)元素的引用,所以它也無法被回收。 第四種情況是不合理的使用閉包,從而導(dǎo)致某些變量一直被留在內(nèi)存當(dāng)中。ECMAScript(ES)
ECMAScript 是編寫腳本語言的標(biāo)準(zhǔn),ECMA(European Computer Manufacturers Association)規(guī)定一下他的標(biāo)準(zhǔn),因?yàn)楫?dāng)時(shí)有java語言了,又想強(qiáng)調(diào)這個(gè)東西是讓ECMA這個(gè)人定的規(guī)則,所以就這樣一個(gè)神奇的東西誕生了,這個(gè)東西的名稱就叫做ECMAScript。 javaScript = ECMAScript + DOM + BOMES2015(ES6)新特性
塊作用域 類 箭頭函數(shù) 模板字符串 對(duì)象解構(gòu) Promise 模塊 Symbol 代理(proxy)Set 函數(shù)默認(rèn)參數(shù) rest 擴(kuò)展運(yùn)算符 數(shù)組和對(duì)象的擴(kuò)展ES2016(ES7)新特性
求冪運(yùn)算符(**)(因顆錄此) Array.prototype.includes()方法數(shù)組原型的方法,查找一個(gè)數(shù)值是否在數(shù)組中,只能判斷一些簡單類型的數(shù)據(jù),對(duì)于復(fù)雜類型的數(shù)據(jù)無法判斷。該方法接受兩個(gè)參數(shù),分別是查詢的數(shù)據(jù)和初始的查詢索引值。ES2017(ES8)新特性
async await函數(shù)參數(shù)列表結(jié)尾允許逗號(hào)es2017允許函數(shù)對(duì)象的定義調(diào)用時(shí)參數(shù)可以加入尾逗號(hào),以及json對(duì)象array對(duì)象都允許Object.values()values: [obj],返回obj自身可枚舉屬性的屬性值的集合(安吹斯) Object.entries()entries:[obj], 與values類似,返回的一個(gè)2元素的數(shù)組Object.getOwnPropertyDescriptors()getOwnpropertyDescriptors: [obj],返回obj對(duì)象的屬性描述符(get 哦 潑破踢 迪斯虧不踢斯) String padding: padStart()和padEnd(),填充字符串達(dá)到當(dāng)前長度在字符串首位開始添加string直到滿足length為止并返回新的字符串ShareArrayBuffer和Atomics對(duì)象,用于從共享內(nèi)存位置讀取和寫入 (夏爾 啊銳 八法兒) (啊偷沒此)ES2018(ES9)新特性
異步迭代 Promise.finally()(飯的嘞) Rest/Spread 屬性 (銳斯特)(斯破銳的) 正則表達(dá)式命名捕獲組(Regular Expression Named Capture Groups) 正則表達(dá)式反向斷言(lookbehind) 正則表達(dá)式dotAll模式 正則表達(dá)式 Unicode 轉(zhuǎn)義 (右內(nèi)扣的) 非轉(zhuǎn)義序列的模板字符串ES2019(ES10)新特性
行分隔符(U + 2028)和段分隔符(U + 2029)符號(hào)現(xiàn)在允許在字符串文字中,與JSON匹配 更加友好的JSON.stringify 新增了Array的flat()方法和flatMap()方法 新增了String的trimStart()方法和trimEnd()方法 Object.fromEntries() Symbol.prototype.description String.prototype.matchAll Function.prototype.toString()現(xiàn)在返回精確字符,包括空格和注釋 簡化try{} catch{},修改catch綁定 新的基本數(shù)據(jù)類型BigInt globalThis import() Legacy RegEx 私有的實(shí)例方法和訪問器ES2020(ES11)新特性
私有變量ES11在類中新增私有變量控制符#,在內(nèi)部變量或者函數(shù)前添加一個(gè)hash符號(hào)#,可以將它們?cè)O(shè)置為私有屬性,只能在類的內(nèi)部可以使用。 空值合并運(yùn)算符空值合并操作符就是 ?? :如果左側(cè)的值為null或者undefined就返回左側(cè)的值,如果沒有就返回右側(cè)的值 可選鏈操作符可選鏈操作符 (?.) :如果左側(cè)表達(dá)式有值,就會(huì)繼續(xù)訪問右側(cè)的字段 BigInt使用BigInt的方式有兩種:1.在數(shù)字后面加n2.使用BigInt函數(shù) 動(dòng)態(tài)導(dǎo)入globalThis提供一種標(biāo)準(zhǔn)化的方式去訪問全局對(duì)象,可以在任意上下文中獲取全局對(duì)象自身,并且不用擔(dān)心環(huán)境的問題 Promise.all缺陷與Promise.allSettledpromise.all可以并發(fā)執(zhí)行異步任務(wù),如果其中某個(gè)任務(wù)執(zhí)行出現(xiàn)了異常,所有任務(wù)都會(huì)over,Promise會(huì)直接進(jìn)入reject狀態(tài)使用Promise.allSettled,它會(huì)創(chuàng)建一個(gè)新的promise,在所有promise完成后返回一個(gè)包含每個(gè)promise結(jié)果的數(shù)組var,let和const的區(qū)別
1.var聲明的變量會(huì)掛載在window上,而let和const聲明的變量不會(huì): 2.var聲明變量存在變量提升,let和const不存在變量提升 3.let和const聲明形成塊作用域 4.同一作用域下let和const不能聲明同名變量,而var可以const 一旦聲明必須賦值,不能使用null占位。聲明后不能再修改如果聲明的是復(fù)合類型數(shù)據(jù),可以修改其屬性暫存死區(qū) var a = 100; if(1){a = 10;//在當(dāng)前塊作用域中存在a使用let/const聲明的情況下,給a賦值10時(shí),只會(huì)在當(dāng)前作用域找變量a,// 而這時(shí),還未到聲明時(shí)候,所以控制臺(tái)Error:a is not definedlet a = 1; }var和let在for循環(huán)的一些不同表現(xiàn)
在var中執(zhí)行的時(shí)候: 因?yàn)関ar是沒有塊級(jí)作用域的,所以在for循環(huán)中聲明的i會(huì)存在于test()函數(shù)作用域中。每一次for循環(huán)就會(huì)聲明一次i,但后面聲明的變量會(huì)覆蓋前面聲明的變量。 在let中執(zhí)行的時(shí)候:因?yàn)閴K級(jí)作用域的原因,let聲明的i都會(huì)存在于for塊級(jí)作用域中,每一次for循環(huán)都會(huì)生成一個(gè)塊級(jí)作用域。箭頭函數(shù)
箭頭函數(shù)表達(dá)式的語法比函數(shù)表達(dá)式更簡潔箭頭函數(shù)沒有自己的this值。箭頭函數(shù)里的this指向的是父級(jí)的this. 箭頭函數(shù)表達(dá)式更適用于那些本來需要匿名函數(shù)的地方,并且它不能用作構(gòu)造函數(shù)。在箭頭函數(shù)版本中,當(dāng)只有一個(gè)表達(dá)式或值需要返回,我們只需要()括號(hào), 不需要 return 語句,箭頭函數(shù)就會(huì)有一個(gè)隱式的返回。如果我們?cè)谝粋€(gè)箭頭函數(shù)中有一個(gè)參數(shù),則可以省略括號(hào)。箭頭函數(shù)不能訪問arguments對(duì)象。所以調(diào)用第一個(gè)getArgs函數(shù)會(huì)拋出一個(gè)錯(cuò)誤。 相反,我們可以使用rest參數(shù)來獲得在箭頭函數(shù)中傳遞的所有參數(shù)。模板字符串
模板字符串是在 JS 中創(chuàng)建字符串的一種新方法。我們可以通過使用反引號(hào)使模板字符串化。在ES5版本中,我們需要添加\n以在字符串中添加新行。在模板字符串中,我們不需要這樣做。在 ES5 版本中,如果需要在字符串中添加表達(dá)式或值,則需要使用`+`運(yùn)算符。 在模板字符串s中,我們可以使用${expr}嵌入一個(gè)表達(dá)式,這使其比 ES5 版本更整潔。對(duì)象解構(gòu)
對(duì)象解構(gòu)是從對(duì)象或數(shù)組中獲取或提取值的一種新的、更簡潔的方法 我們還可以為屬性取別名 let { firstName: fName, position } = employee; 當(dāng)然如果屬性值為 undefined 時(shí),我們還可以指定默認(rèn)值 let { firstName = "Mark" } = employee;Set及應(yīng)用場景
一、創(chuàng)建Set對(duì)象實(shí)例 Set 對(duì)象允許你存儲(chǔ)任何類型的唯一值,無論是原始值或者是對(duì)象引用 1.構(gòu)造函數(shù) (伊特波)語法:new Set([iterable])參數(shù):iterable 如果傳遞一個(gè)可迭代對(duì)象,它的所有元素將被添加到新的Set中;如果不指定此參數(shù)或其值為null,則新的 Set為空二、Set實(shí)例屬性size屬性將會(huì)返回Set對(duì)象中元素的個(gè)數(shù)三、Set實(shí)例方法 1.add() 方法用來向一個(gè) Set 對(duì)象的末尾添加一個(gè)指定的值語法:mySet.add(value)參數(shù):value 必需,需要添加到 Set 對(duì)象的元素的值 2.delete() 方法可以從一個(gè) Set 對(duì)象中刪除指定的元素語法:mySet.delete(value)參數(shù):value 將要?jiǎng)h除的元素返回值:成功刪除返回 true,否則返回 false 3.clear() 方法用來清空一個(gè) Set 對(duì)象中的所有元素語法:mySet.clear() 4.has() 方法返回一個(gè)布爾值來指示對(duì)應(yīng)的值value是否存在Set對(duì)象中語法:mySet.has(value)參數(shù):value 必須,是否存在于Set的值返回值:如果指定的值(value)存在于Set對(duì)象當(dāng)中,返回true; 否則返回 false 5.entries() (安吹斯)語法:mySet.entries()返回值:一個(gè)新的包含 [value, value] 形式的數(shù)組迭代器對(duì)象,value 是給定集合中的每個(gè)元素,迭代器 對(duì)象元素的順序即集合對(duì)象中元素插入的順序 6.values()語法:mySet.values() 或者 mySet.keys()返回值:返回一個(gè) Iterator(因特瑞特) 對(duì)象,這個(gè)對(duì)象以插入Set對(duì)象的順序包含了原 Set 對(duì)象里的每個(gè)元素 7.forEach()語法:mySet.forEach(callback[, thisArg]) (this傲歌)參數(shù):callback 每個(gè)元素都會(huì)執(zhí)行的函數(shù)thisArg 當(dāng)執(zhí)行callback函數(shù)時(shí)候,可以當(dāng)作this來使用 5、什么是WeakSet()? 和Set結(jié)構(gòu)類似,也是不重復(fù)的值的集合,但WeakSet的成員只能是對(duì)象(null 除外)。 而且 WeakMap 的鍵名所指向的對(duì)象,不計(jì)入垃圾回收機(jī)制。應(yīng)用場景: 1、簡單數(shù)組去重 2、JSON數(shù)組去重JSON數(shù)組是比較常見的一種數(shù)據(jù)結(jié)構(gòu),形如[{…},…{…}]假如你需要統(tǒng)計(jì)某個(gè)屬性中不同的值。step1:先使用.map將JSON數(shù)組變成簡單數(shù)組,然后用set執(zhí)行去重step2: 由于生成的Set屬于可迭代對(duì)象,所以可以使用數(shù)組解構(gòu)符進(jìn)行解構(gòu) 3、二維數(shù)組去重我們可以將Set用作存儲(chǔ)每項(xiàng)的唯一值,結(jié)合reduce進(jìn)行對(duì)比,得出無重復(fù)的項(xiàng)目。當(dāng)然,上面的代碼缺點(diǎn)還是不少的。因?yàn)橹皇呛唵蔚貙⑵滢D(zhuǎn)變成字符串作為對(duì)比的鍵,所以不能區(qū)分[1,2]、[‘1’ ,‘2’]、[‘1,2’]等子數(shù)組。 4、數(shù)組之間的對(duì)比Set的特性不單單可以可以用于單數(shù)組,對(duì)于數(shù)組之間的比較也是十分在行。什么是WeakSet()?和Set結(jié)構(gòu)類似,也是不重復(fù)的值的集合,但WeakSet的成員只能是對(duì)象。WeakSet的API:add() //增delete() //刪has() //是否存在為什么WeakSet不可遍歷?因?yàn)閃eakSet的成員都是弱引用,隨時(shí)可能消失,成員是不穩(wěn)定的。WeakSet的用處:使用ws儲(chǔ)存DOM節(jié)點(diǎn),就不用擔(dān)心節(jié)點(diǎn)從文檔移除時(shí),會(huì)引發(fā)內(nèi)存泄漏(即在被移除的節(jié)點(diǎn)上綁定的click等事件)。Proxy
Proxy 可以理解成,在目標(biāo)對(duì)象之前架設(shè)一層“攔截”,外界對(duì)該對(duì)象的訪問,都必須先通過這層攔截,因此提供了一種機(jī)制,可以對(duì)外界的訪問進(jìn)行過濾和改寫。Proxy 這個(gè)詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”函數(shù)式編程
函數(shù)式編程(通常縮寫為FP)是通過編寫純函數(shù),避免共享狀態(tài)、可變數(shù)據(jù)、副作用 來構(gòu)建軟件的過程。數(shù)式編程是聲明式 的而不是命令式 的,應(yīng)用程序的狀態(tài)是通過純函數(shù)流動(dòng)的。與面向?qū)ο缶幊绦纬蓪?duì)比,面向?qū)ο笾袘?yīng)用程序的狀態(tài)通常與對(duì)象中的方法共享和共處。 函數(shù)式編程是一種編程范式 ,這意味著它是一種基于一些基本的定義原則(如上所列)思考軟件構(gòu)建的方式。當(dāng)然,編程范式的其他示例也包括面向?qū)ο缶幊毯瓦^程編程。 函數(shù)式的代碼往往比命令式或面向?qū)ο蟮拇a更簡潔,更可預(yù)測,更容易測試高階函數(shù)
首先高階函數(shù)肯定是函數(shù),不同的是輸入的參數(shù)和返回的值這兩項(xiàng)中的一項(xiàng)必須是函數(shù)才能叫高階函數(shù)。 這個(gè)問題在回答的時(shí)候可以稍微拓展一下,介紹一下常用的的高階函數(shù), 比如:map、flatMap、filter、reduce、fold。為什么函數(shù)被稱為一等公民
在JavaScript中,函數(shù)不僅擁有一切傳統(tǒng)函數(shù)的使用方式(聲明和調(diào)用),而且可以做到像簡單值一樣:賦值(var func = function(){})、 傳參(function func(x,callback){callback();})、 返回(function(){return function(){}}),這樣的函數(shù)也稱之為第一級(jí)函數(shù)(First-class Function)。不僅如此,JavaScript中的函數(shù)還充當(dāng)了類的構(gòu)造函數(shù)的作用,同時(shí)又是一個(gè)Function類的實(shí)例(instance)(因斯疼斯)。這樣的多重身份讓JavaScript的函數(shù)變得非常重要。. new操作符的實(shí)現(xiàn)
1、創(chuàng)建一個(gè)空對(duì)象 {} 2、將構(gòu)造函數(shù)中的this指向新創(chuàng)建的對(duì)象 (原型鏈)obj.__proto__ = Dog.prototype // 設(shè)置原型鏈 3、鏈接該對(duì)象到另一個(gè)對(duì)象 __proto__ 4、如果該函數(shù)沒有返回對(duì)象,則返回this回調(diào)函數(shù)?回調(diào)函數(shù)有什么缺點(diǎn)
回調(diào)函數(shù)是一個(gè)匿名函數(shù),它作為一個(gè)參數(shù)傳遞給其他的代碼,其作用是在需要的時(shí)候方便調(diào)用這段(回調(diào)函數(shù))代碼。可以讓異步代碼同步執(zhí)行。 回調(diào)函數(shù)有一個(gè)致命的弱點(diǎn),就是容易寫出回調(diào)地獄(Callback hell)instanceof的原理
instanceof 可以正確的判斷對(duì)象的類型,因?yàn)閮?nèi)部機(jī)制是通過判斷對(duì)象的原型鏈中是不是能找到類型的 prototype。 實(shí)現(xiàn) instanceof:首先獲取類型的原型 然后獲得對(duì)象的原型 然后一直循環(huán)判斷對(duì)象的原型是否等于類型的原型,直到對(duì)象原型為 null,因?yàn)樵玩溩罱K為 nullfunction myInstanceof(left, right) {let prototype = right.prototypeleft = left.__proto__while (true) {if (left === null || left === undefined)return falseif (prototype === left)return trueleft = left.__proto__} }設(shè)計(jì)模式
設(shè)計(jì)模式是一套被反復(fù)使用的、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 1、單例模式 2、工廠模式 3、觀察者模式 4、代理模式 5、策略模式 6、迭代器模式單例模式(Singleton Pattern)單例模式中Class的實(shí)例個(gè)數(shù)最多為1。當(dāng)需要一個(gè)對(duì)象去貫穿整個(gè)系統(tǒng)執(zhí)行某些任務(wù)時(shí),單例模式就派上了用場。而除此之外的場景盡量避免單例模式的使用,因?yàn)閱卫J綍?huì)引入全局狀態(tài),而一個(gè)健康的系統(tǒng)應(yīng)該避免引入過多的全局狀態(tài)。工廠模式工廠模式定義一個(gè)用于創(chuàng)建對(duì)象的接口,這個(gè)接口由子類決定實(shí)例化哪一個(gè)類。該模式使一個(gè)類的實(shí)例化延遲到了子類。而子類可以重寫接口方法以便創(chuàng)建的時(shí)候指定自己的對(duì)象類型。 使用場景:如果你不想讓某個(gè)子系統(tǒng)與較大的那個(gè)對(duì)象之間形成強(qiáng)耦合,而是想運(yùn)行時(shí)從許多子系統(tǒng)中進(jìn)行挑選的話,那么工廠模式是一個(gè)理想的選擇 class Product {constructor(name) {this.name = name}init() {console.log('init')}} class Factory {create(name) {return new Product(name)} } // use let factory = new Factory() let p = factory.create('p1') p.init() https://juejin.im/post/6844904200917221389#heading-81js的基本數(shù)據(jù)類型、值是如何存儲(chǔ)的
JavaScript一共有8種數(shù)據(jù)類型 7種基本數(shù)據(jù)類型: Undefined、Null、Boolean、Number、String、Symbol(es6新增,表示獨(dú)一無二的值)和BigInt(es10新增)1種引用數(shù)據(jù)類型 Object(Object本質(zhì)上是由一組無序的名值對(duì)組成的)。 里面包含 function、Array、Date等。JavaScript不支持任何創(chuàng)建自定義類型的機(jī)制,而所有值最終都將是上述 8 種數(shù)據(jù)類型之一。 原始數(shù)據(jù)類型:直接存儲(chǔ)在棧(stack)中,占據(jù)空間小、大小固定,屬于被頻繁使用數(shù)據(jù),所以放入棧中存儲(chǔ)。 引用數(shù)據(jù)類型:同時(shí)存儲(chǔ)在棧(stack)和堆(heap)中,占據(jù)空間大、大小不固定。引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針,該指針指向堆中該實(shí)體的起始地址。當(dāng)解釋器尋找引用值時(shí),會(huì)首先檢索其在棧中的地址,取得地址后從堆中獲得實(shí)體。&& 、||和!! 運(yùn)算符
&& 叫邏輯與,在其操作數(shù)中找到第一個(gè)虛值表達(dá)式并返回它,如果沒有找到任何虛值表達(dá)式,則返回最后一個(gè)真值表達(dá)式。它采用短路來防止不必要的工作。 || 叫邏輯或,在其操作數(shù)中找到第一個(gè)真值表達(dá)式并返回它。這也使用了短路來防止不必要的工作。在支持 ES6 默認(rèn)函數(shù)參數(shù)之前,它用于初始化函數(shù)中的默認(rèn)參數(shù)值。 !! 運(yùn)算符可以將右側(cè)的值強(qiáng)制轉(zhuǎn)換為布爾值,這也是將值轉(zhuǎn)換為布爾值的一種簡單方法js的數(shù)據(jù)類型的轉(zhuǎn)換
在 JS 中類型轉(zhuǎn)換只有三種情況,分別是:轉(zhuǎn)換為布爾值(調(diào)用Boolean()方法) 轉(zhuǎn)換為數(shù)字(調(diào)用Number()、parseInt()和parseFloat()方法) 轉(zhuǎn)換為字符串(調(diào)用.toString()或者String()方法)js 內(nèi)置對(duì)象
js 中的內(nèi)置對(duì)象主要指的是 在程序執(zhí)行前存在全局作用域里的由 js定義的一些全局值屬性、函數(shù)和用來實(shí)例化其他對(duì)象的構(gòu)造函數(shù)對(duì)象。 一般我們經(jīng)常用到的如全局變量值 NaN、undefined, 全局函數(shù)如 parseInt()、parseFloat() 用來實(shí)例化對(duì)象的構(gòu)造函數(shù)如 Date、Object 等, 還有提供數(shù)學(xué)計(jì)算的單體內(nèi)置對(duì)象如 Math 對(duì)象。null 和 undefined 的區(qū)別
首先 Undefined 和 Null 都是基本數(shù)據(jù)類型,這兩個(gè)基本數(shù)據(jù)類型分別都只有一個(gè)值,就是 undefined 和 null。 undefined 代表的含義是未定義, null 代表的含義是空對(duì)象(其實(shí)不是真的對(duì)象,請(qǐng)看下面的注意!)。一般變量聲明了但還沒有定義的時(shí)候會(huì)返回 undefined,null 主要用于賦值給一些可能會(huì)返回對(duì)象的變量,作為初始化。 當(dāng)我們對(duì)兩種類型使用 typeof 進(jìn)行判斷的時(shí)候,Null 類型化會(huì)返回 “object”,這是一個(gè)歷史遺留的問題。當(dāng)我們使用雙等 號(hào)對(duì)兩種類型的值進(jìn)行比較時(shí)會(huì)返回 true,使用三個(gè)等號(hào)時(shí)會(huì)返回 false。{}和[]的valueOf和toString的結(jié)果
{} 的 valueOf 結(jié)果為 {} ,toString 的結(jié)果為 "[object Object]" [] 的 valueOf 結(jié)果為 [] ,toString 的結(jié)果為 ""js 的作用域和作用域鏈
作用域: 作用域是定義變量的區(qū)域,它有一套訪問變量的規(guī)則,這套規(guī)則來管理瀏覽器引擎如何在當(dāng)前作用域以及嵌套的作用域中根據(jù)變量(標(biāo)識(shí)符)進(jìn)行變量查找。作用域鏈: 作用域鏈的作用是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問,通過作用域鏈,我們可以訪問到外層環(huán)境的變量和函數(shù)。作用域鏈的本質(zhì)上是一個(gè)指向變量對(duì)象的指針列表。變量對(duì)象是一個(gè)包含了執(zhí)行環(huán)境中所有變量和函數(shù)的對(duì)象。作用域鏈的前端始終都是當(dāng)前執(zhí)行上下文的變量對(duì)象。全局執(zhí)行上下文的變量對(duì)象(也就是全局對(duì)象)始終是作用域鏈的最后一個(gè)對(duì)象。 當(dāng)我們查找一個(gè)變量時(shí),如果當(dāng)前執(zhí)行環(huán)境中沒有找到,我們可以沿著作用域鏈向后查找。js 創(chuàng)建對(duì)象的方式
我們一般使用字面量的形式直接創(chuàng)建對(duì)象,但是這種創(chuàng)建方式對(duì)于創(chuàng)建大量相似對(duì)象的時(shí)候,會(huì)產(chǎn)生大量的重復(fù)代碼。但 js和一般的面向?qū)ο蟮恼Z言不同,在 ES6 之前它沒有類的概念。但是我們可以使用函數(shù)來進(jìn)行模擬,從而產(chǎn)生出可復(fù)用的對(duì)象創(chuàng)建方式,我了解到的方式有這么幾種:(1)第一種是工廠模式,工廠模式的主要工作原理是用函數(shù)來封裝創(chuàng)建對(duì)象的細(xì)節(jié),從而通過調(diào)用函數(shù)來達(dá)到復(fù)用的目的。但是它有一個(gè)很大的問題就是創(chuàng)建出來的對(duì)象無法和某個(gè)類型聯(lián)系起來,它只是簡單的封裝了復(fù)用代碼,而沒有建立起對(duì)象和類型間的關(guān)系。(2)第二種是構(gòu)造函數(shù)模式。js 中每一個(gè)函數(shù)都可以作為構(gòu)造函數(shù),只要一個(gè)函數(shù)是通過 new 來調(diào)用的,那么我們就可以把它稱為構(gòu)造函數(shù)。執(zhí)行構(gòu)造函數(shù)首先會(huì)創(chuàng)建一個(gè)對(duì)象,然后將對(duì)象的原型指向構(gòu)造函數(shù)的 prototype 屬性,然后將執(zhí)行上下文中的 this 指向這個(gè)對(duì)象,最后再執(zhí)行整個(gè)函數(shù),如果返回值不是對(duì)象,則返回新建的對(duì)象。因?yàn)?this 的值指向了新建的對(duì)象,因此我們可以使用 this 給對(duì)象賦值。構(gòu)造函數(shù)模式相對(duì)于工廠模式的優(yōu)點(diǎn)是,所創(chuàng)建的對(duì)象和構(gòu)造函數(shù)建立起了聯(lián)系,因此我們可以通過原型來識(shí)別對(duì)象的類型。但是構(gòu)造函數(shù)存在一個(gè)缺點(diǎn)就是,造成了不必要的函數(shù)對(duì)象的創(chuàng)建,因?yàn)樵?js 中函數(shù)也是一個(gè)對(duì)象,因此如果對(duì)象屬性中如果包含函數(shù)的話,那么每次我們都會(huì)新建一個(gè)函數(shù)對(duì)象,浪費(fèi)了不必要的內(nèi)存空間,因?yàn)楹瘮?shù)是所有的實(shí)例都可以通用的。(3)第三種模式是原型模式,因?yàn)槊恳粋€(gè)函數(shù)都有一個(gè) prototype 屬性,這個(gè)屬性是一個(gè)對(duì)象,它包含了通過構(gòu)造函數(shù)創(chuàng)建的所有實(shí)例都能共享的屬性和方法。因此我們可以使用原型對(duì)象來添加公用屬性和方法,從而實(shí)現(xiàn)代碼的復(fù)用。這種方式相對(duì)于構(gòu)造函數(shù)模式來說,解決了函數(shù)對(duì)象的復(fù)用問題。但是這種模式也存在一些問題,一個(gè)是沒有辦法通過傳入?yún)?shù)來初始化值,另一個(gè)是如果存在一個(gè)引用類型如 Array 這樣的值,那么所有的實(shí)例將共享一個(gè)對(duì)象,一個(gè)實(shí)例對(duì)引用類型值的改變會(huì)影響所有的實(shí)例。(4)第四種模式是組合使用構(gòu)造函數(shù)模式和原型模式,這是創(chuàng)建自定義類型的最常見方式。因?yàn)闃?gòu)造函數(shù)模式和原型模式分開使用都存在一些問題,因此我們可以組合使用這兩種模式,通過構(gòu)造函數(shù)來初始化對(duì)象的屬性,通過原型對(duì)象來實(shí)現(xiàn)函數(shù)方法的復(fù)用。這種方法很好的解決了兩種模式單獨(dú)使用時(shí)的缺點(diǎn),但是有一點(diǎn)不足的就是,因?yàn)槭褂昧藘煞N不同的模式,所以對(duì)于代碼的封裝性不夠好。(5)第五種模式是動(dòng)態(tài)原型模式,這一種模式將原型方法賦值的創(chuàng)建過程移動(dòng)到了構(gòu)造函數(shù)的內(nèi)部,通過對(duì)屬性是否存在的判斷,可以實(shí)現(xiàn)僅在第一次調(diào)用函數(shù)時(shí)對(duì)原型對(duì)象賦值一次的效果。這一種方式很好地對(duì)上面的混合模式進(jìn)行了封裝。(6)第六種模式是寄生構(gòu)造函數(shù)模式,這一種模式和工廠模式的實(shí)現(xiàn)基本相同,我對(duì)這個(gè)模式的理解是,它主要是基于一個(gè)已有的類型,在實(shí)例化時(shí)對(duì)實(shí)例化的對(duì)象進(jìn)行擴(kuò)展。這樣既不用修改原來的構(gòu)造函數(shù),也達(dá)到了擴(kuò)展對(duì)象的目的。它的一個(gè)缺點(diǎn)和工廠模式一樣,無法實(shí)現(xiàn)對(duì)象的識(shí)別。對(duì)this、call、apply和bind的理解
1、在瀏覽器里,在全局范圍內(nèi)this 指向window對(duì)象; 2、在函數(shù)中,this永遠(yuǎn)指向最后調(diào)用他的那個(gè)對(duì)象; 3、構(gòu)造函數(shù)中,this指向new出來的那個(gè)新的對(duì)象; 4、call、apply、bind中的this被強(qiáng)綁定在指定的那個(gè)對(duì)象上; 5、箭頭函數(shù)中this比較特殊,箭頭函數(shù)this為父作用域的this,不是調(diào)用時(shí)的this.要知道前四種方式,都是調(diào)用時(shí)確定,也就是動(dòng)態(tài)的,而箭頭函數(shù)的this指向是靜態(tài)的,聲明的時(shí)候就確定了下來; 6、apply、call、bind都是js給函數(shù)內(nèi)置的一些API,調(diào)用他們可以為函數(shù)指定this的執(zhí)行,同時(shí)也可以傳參。什么是 DOM 和 BOM
DOM指的是文檔對(duì)象模型,它指的是把文檔當(dāng)做一個(gè)對(duì)象來對(duì)待,這個(gè)對(duì)象主要定義了處理網(wǎng)頁內(nèi)容的方法和接口。 BOM指的是瀏覽器對(duì)象模型,它指的是把瀏覽器當(dāng)做一個(gè)對(duì)象來對(duì)待,這個(gè)對(duì)象主要定義了與瀏覽器進(jìn)行交互的法和接口。BOM的核心是 window,而 window 對(duì)象具有雙重角色,它既是通過 js 訪問瀏覽器窗口的一個(gè)接口, 又是一個(gè) Global(全局)(歌樓波)對(duì)象。 這意味著在網(wǎng)頁中定義的任何對(duì)象,變量和函數(shù),都作為全局對(duì)象的一個(gè)屬性或者方法存在。 window 對(duì)象含有 location 對(duì)象、navigator(那V給特)對(duì)象、screen(斯歌銳)對(duì)象等子對(duì)象, 并且 DOM 的最根本的對(duì)象 document 對(duì)象也是 BOM 的 window 對(duì)象的子對(duì)象。三種事件模型
事件 是用戶操作網(wǎng)頁時(shí)發(fā)生的交互動(dòng)作或者網(wǎng)頁本身的一些操作,現(xiàn)代瀏覽器一共有三種事件模型。 DOM0級(jí)模型: 這種模型不會(huì)傳播,所以沒有事件流的概念,同元素 綁定多個(gè)事件,只會(huì)綁定最后一次的事件,前面的會(huì)被覆蓋。IE 事件模型:在該事件模型中,一次事件共有兩個(gè)過程,事件處理階段,和事件冒泡階段。事件處理階段會(huì)首先執(zhí)行目標(biāo)元素綁定的監(jiān)聽事件。然后是事件冒泡階段,冒泡指的是事件從目標(biāo)元素冒泡到 document,依次檢查經(jīng)過的節(jié)點(diǎn)是否綁定了事件監(jiān)聽函數(shù),如果有則執(zhí)行。這種模型通過 attachEvent 來添加監(jiān)聽函數(shù),可以添加多個(gè)監(jiān)聽函數(shù),會(huì)按順序依次執(zhí)行。detachEvent刪除事件DOM2 級(jí)事件模型: 在該事件模型中,一次事件共有三個(gè)過程,第一個(gè)過程是事件捕獲階段事件處理階段,和事件冒泡階段。捕獲指的是事件從 document 一直向下傳播到目標(biāo)元素,依次檢查經(jīng)過的節(jié)點(diǎn)是否綁定了事件監(jiān)聽函數(shù),如果有則執(zhí)行。。這種事件模型,事件綁定的函數(shù)是 addEventListener,其中第三個(gè)參數(shù)可以指定事件是否在捕獲階段執(zhí)行。取消事件removeEventListener事件委托(代理)
本質(zhì)上是利用了事件冒泡的機(jī)制。 并且父節(jié)點(diǎn)可以通過事件對(duì)象獲取到目標(biāo)節(jié)點(diǎn),因此可以把子節(jié)點(diǎn)的監(jiān)聽函數(shù)定義在父節(jié)點(diǎn)上, 由父節(jié)點(diǎn)的監(jiān)聽函數(shù)統(tǒng)一處理多個(gè)子元素的事件,這種方式稱為事件委托 支持為同一個(gè)DOM元素注冊(cè)多個(gè)同類型事件,可將事件分成事件捕獲和事件冒泡機(jī)制事件傳播
事件傳播有三個(gè)階段: 捕獲階段–事件從 window 開始,然后向下到每個(gè)元素,直到到達(dá)目標(biāo)元素事件或event.target。 目標(biāo)階段–事件已達(dá)到目標(biāo)元素。 冒泡階段–事件從目標(biāo)元素冒泡,然后上升到每個(gè)元素,直到到達(dá) window。什么是事件捕獲 當(dāng)事件發(fā)生在 DOM 元素上時(shí),該事件并不完全發(fā)生在那個(gè)元素上。在捕獲階段,事件從window開始,一直到觸發(fā)事件的元素。 什么是事件冒泡? 事件冒泡剛好與事件捕獲相反,當(dāng)前元素---->body ----> html---->document ---->window。當(dāng)事件發(fā)生在DOM元素上時(shí),該事件并不完全發(fā)生在那個(gè)元素上。在冒泡階段,事件冒泡,或者事件發(fā)生在它的父代,祖父母,祖父母的父代,直到到達(dá)window為止。DOM 操作
(1)創(chuàng)建新節(jié)點(diǎn)createDocumentFragment() //創(chuàng)建一個(gè)DOM片段 (科瑞A特)(法歌們特)createElement() //創(chuàng)建一個(gè)具體的元素createTextNode() //創(chuàng)建一個(gè)文本節(jié)點(diǎn)(2)添加、移除、替換、插入appendChild(node) removeChild(node)replaceChild(new,old) (銳普利斯)insertBefore(new,old) (因色特比佛)(3)獲取、查找getElementById();getElementsByName();getElementsByTagName();getElementsByClassName();querySelector(); (斯來科特)querySelectorAll();(4)屬性操作getAttribute(key); (去比又特)setAttribute(key, value);hasAttribute(key);removeAttribute(key);數(shù)據(jù)檢測類型判斷
檢測方法4種1、Object.prototype.toString.call()作用: 可以檢測所有數(shù)據(jù)類型所有數(shù)據(jù)類型都可以檢測,而且非常正確語法: Object.prototype.toString.call( 'xxx'/11/[ ] )返回值: [object Xxx], Xxx 就是對(duì)象的類型2、constructor作用: 可以檢測基本數(shù)據(jù)類型和引用數(shù)據(jù)類型弊端: 把類的原型進(jìn)行重寫, 很有可能把之前的constructor覆蓋 檢測出來的結(jié)果就會(huì)不準(zhǔn)確語法: ("xx")/([])/(function(){}).constructor === String/Array/Function 返回值: true/false 3、instanceOf原理: 判斷對(duì)象類型,基于原型鏈去判斷(obj instanceof Object)左邊對(duì)象的原型鏈proto上是否有右邊構(gòu)造函數(shù)的proptotype屬性作用: 判斷左邊的對(duì)象是否是右邊構(gòu)造函數(shù)的實(shí)例弊端: 用于引用類型的檢測, 對(duì)于基本數(shù)據(jù)類型不生效語法: " "/[ ]/true instanceOf String/Array/Boolean返回值: true/false 4、typeOf作用: 用于檢測基本數(shù)據(jù)類型和函數(shù)弊端: 引用數(shù)據(jù)類型(Arrary/function/object)只會(huì)返回Object, 不起作用語法: typeOf " "/[ ]/xx返回值: "string"/"boolean"/"object" (無法區(qū)分)原型/原型鏈
原型: Javascript規(guī)定,每一個(gè)函數(shù)都有一個(gè)prototype對(duì)象屬性,指向另一個(gè)對(duì)象 prototype就是調(diào)用構(gòu)造函數(shù)所創(chuàng)建的那個(gè)實(shí)例對(duì)象的原型原型鏈: 實(shí)例對(duì)象與原型之間的連接,叫做原型鏈。 JS在創(chuàng)建對(duì)象的時(shí)候,都有一個(gè)叫做__proto__的內(nèi)置屬性,用于指向創(chuàng)建它的函數(shù)對(duì)象的原型對(duì)象prototype。獲取原型的方法 p.proto p.constructor.prototype Object.getPrototypeOf(p)prototype、proto、constructor三者的關(guān)系
1、prototype: 每一個(gè)函數(shù)都有一個(gè)prototype這個(gè)屬性,而這個(gè)屬性指向一個(gè)對(duì)象,這個(gè)對(duì)象我們叫做原型對(duì)象 作用:節(jié)約內(nèi)存擴(kuò)展屬性和方法可以實(shí)現(xiàn)類之間的繼承 2、__proto__: 每一個(gè)對(duì)象都有一個(gè)__proto__屬性,__proto__指向創(chuàng)建自己的那個(gè)構(gòu)造函數(shù)的原型對(duì)象對(duì)象可以直接訪問__proto__里面的屬性和方法 3、constructor: 指向創(chuàng)建自己的那個(gè)構(gòu)造函數(shù) ,是原型上的方法總結(jié): 當(dāng)我們創(chuàng)建一個(gè)構(gòu)造函數(shù)的時(shí)候這個(gè)構(gòu)造函數(shù)自帶了一個(gè)prototype屬性,而這個(gè)屬性指向一個(gè)對(duì)象,也就是原型對(duì)象。 這個(gè)原型對(duì)象里面有一個(gè)constructor構(gòu)造器,它的作用是指向創(chuàng)建自己的構(gòu)造函數(shù)。 除此之外 prototype還可以存放公共的屬性和方法。 當(dāng)我們實(shí)例化一個(gè)對(duì)象的時(shí)候(被new調(diào)用的時(shí)候),這個(gè)對(duì)象自帶了一個(gè) proto 屬性, 這個(gè)proto 指向創(chuàng)建自己的構(gòu)造函數(shù)的原型對(duì)象。可以使用這個(gè)原型對(duì)象里面的屬性和方法constructor與class的區(qū)別
傳統(tǒng)的javascript中只有對(duì)象,沒有類的概念。它是基于原型的面向?qū)ο笳Z言。 原型對(duì)象特點(diǎn)就是將自身的屬性共享給新對(duì)象。 ES6引入了Class(類)這個(gè)概念,通過class關(guān)鍵字可以定義類。 該關(guān)鍵字的出現(xiàn)使得其在對(duì)象寫法上更加清晰,更像是一種面向?qū)ο蟮恼Z言constructor: constructor()方法是類的默認(rèn)方法,通過new命令生成對(duì)象實(shí)例時(shí),自動(dòng)調(diào)用該方法。 一個(gè)類必須有constructor()方法,如果沒有顯式定義,一個(gè)空的 constructor()方法會(huì)被默認(rèn)添加。構(gòu)造函數(shù)與普通函數(shù)的區(qū)別
1. 返回值類型的區(qū)別:構(gòu)造函數(shù)是沒有返回值類型的,普通函數(shù)是有返回值類型的,即使函數(shù)沒有返回值,返回值類型也要寫上void。 2. 函數(shù)名的區(qū)別:構(gòu)造函數(shù)的函數(shù)名必須要與類名一致,普通函數(shù)的函數(shù)名只要符合標(biāo)識(shí)符的命名規(guī)則即可。 3. 調(diào)用方式的區(qū)別:構(gòu)造函數(shù)是在創(chuàng)建對(duì)象的時(shí)候由jvm調(diào)用的。普通函數(shù)是由我們使用對(duì)象調(diào)用的,一個(gè)對(duì)象可以對(duì)象多次普通的函數(shù), 4. 作用上的區(qū)別:構(gòu)造函數(shù)的作用用于初始化一個(gè)對(duì)象。普通函數(shù)是用于描述一類事物的公共行為的。跨域出現(xiàn)的原因/解決方法
1. 為什么出現(xiàn)了跨域 2. 跨域解決方式有哪些?原因:由于瀏覽器的同源策略,即屬于不同域的?面之間不能相互訪問各自的?面內(nèi)容。哪些情況下產(chǎn)生跨域 1、域名不同 2、端口號(hào)不同 3、協(xié)議不同(http/https) 4、域名和域名對(duì)應(yīng)ip 5、主域名相同(127.0.01 和 localhost) 多域名匹配一個(gè)ip地址 6、子域名不同(一級(jí)和二級(jí)域名)解決方法1、后端設(shè)置白名單 后端不存在跨域(后端代碼脫離瀏覽器,后端是服務(wù)器端) 利用后端(自己公司的后端)去獲取接口數(shù)據(jù),將數(shù)據(jù)傳給前端 2、jsonp 原理:利用瀏覽器的"漏洞" src不受同源策略的影響,可以請(qǐng)求任何鏈接 。動(dòng)態(tài)創(chuàng)建script標(biāo)簽,將事先寫好的函數(shù)名傳給服務(wù)器,供服務(wù)器使用 (1)script標(biāo)簽src屬性不存在跨域 (2)get方式--傳遞函數(shù)名 --弊端 (3)callback回調(diào)函數(shù)(傳遞函數(shù)名) 3、反向代理 proxy webpack配置(采用Socket協(xié)議) "proxy": {"/index.php": {"target": "http://qinqin.net","changeOrigin": true}} 4、CORS解決跨域(xhr2)(后端)后端配置響應(yīng)頭,如果需要有特殊的約定字符,前端需要配置請(qǐng)求頭 CORS是一個(gè)W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源(協(xié)議 + 域名 + 端口)服務(wù)器,發(fā)出XMLHttpRequest請(qǐng)求,從而克服了AJAX只能同源使用的限制。 需要服務(wù)器(提供接口的源碼里面)添加下面兩句話。 header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Method:POST,GET');jsonp是一種非正式傳輸協(xié)議,用于解決跨域問題流程: 1、創(chuàng)建一個(gè)全局函數(shù) 2、創(chuàng)建一個(gè)script標(biāo)簽 3、給script添加src 4、給src添加回調(diào)函數(shù)test(callback=test) callback是傳給后端的一個(gè)參數(shù) 5、將script放到?面上 6、script請(qǐng)求完成,將自己從?面上刪除閉包原理/優(yōu)點(diǎn)/缺點(diǎn)/使用場景
1. 什么是閉包 what 函數(shù)嵌套函數(shù) 能夠讀取其他函數(shù)內(nèi)部變量的函數(shù) 2. 優(yōu)缺點(diǎn)優(yōu)點(diǎn): 1、使用閉包是不會(huì)污染全局環(huán)境,2、方便進(jìn)行模塊化開發(fā),缺點(diǎn): 就是不恰當(dāng)使用會(huì)造成內(nèi)存泄漏 【解決方式:清除變量】 3. 閉包的應(yīng)用場景函數(shù)防抖計(jì)數(shù)器閉包原理:定義在一個(gè)函數(shù)內(nèi)部的函數(shù)(函數(shù)嵌套函數(shù)),閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。 打破了作用域鏈的規(guī)則 閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù) 優(yōu)點(diǎn): 1、使用閉包是不會(huì)污染全局環(huán)境, 2、方便進(jìn)行模塊化開發(fā), 3、減少形參個(gè)數(shù),延長了形參的生命周期,壞處: 1、就是不恰當(dāng)使用會(huì)造成內(nèi)存泄漏 閉包的不適用于返回閉包的函數(shù)是個(gè)特別大的函數(shù),很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn).使用場景 1、通過循環(huán)給頁面上多個(gè)dom節(jié)點(diǎn)綁定事件 2、封裝私有變量(計(jì)數(shù)器) 3、延續(xù)局部變量的壽命 4、高階組件 5、函數(shù)防抖模塊化的就是以閉包為基礎(chǔ)構(gòu)建的;內(nèi)存泄漏
1、意外的全局變量 2、被遺忘的定時(shí)器 3、沒有清除的dom應(yīng)用 ,故要及時(shí)清除, 4、濫用閉包清除內(nèi)存泄漏方法有兩種,一是標(biāo)記清除,二便是引用計(jì)數(shù)清除。promise/async&await
Promise是es6新增的,異步編程的一種解決方案,用來取代回調(diào)函數(shù)和事件,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。Promise 對(duì)象用于延遲(deferred) 計(jì)算和異步(asynchronous)計(jì)算。一個(gè)Promise對(duì)象代表著一個(gè)還未完成,但預(yù)期將來會(huì)完成的操作。Promise 對(duì)象是一個(gè)返回值的代理,這個(gè)返回值在promise對(duì)象創(chuàng)建時(shí)未必已知。它允許你為異步操作的成功或失敗指定處理方法。這使得異步方法可以像同步方法那樣返回值:異步方法會(huì)返回一個(gè)包含了原返回值的 promise 對(duì)象來替代原返回值。有三種狀態(tài):pending(進(jìn)行中)、fulfilled(resolve已成功)和rejected(銳杰克騰德)(已失敗)promise的特點(diǎn): (1)對(duì)象的狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作。 (2)一旦狀態(tài)設(shè)定,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。Promise對(duì)象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閞esolve和從pending變?yōu)閞ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了promise的方法: promise實(shí)例方法:Promise.prototype.then Promise.prototype.catch一:resolve函數(shù)的作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤俺晒Α?#xff08;即從 pending 變?yōu)?resolved),在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去;二:reject函數(shù)的作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 ?#xff08;即從 pending 變?yōu)?rejected),在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤,作為參數(shù)傳遞出去。三:Promise.prototype.finallyfinally方法用于指定不管 Promise 對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的操作。該方法是 ES2018 引入標(biāo)準(zhǔn)的。promise的靜態(tài)方法 Promise.all():用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例,接受一個(gè)數(shù)組作為參數(shù),只有數(shù)組里面的每個(gè)狀態(tài)都變成resolve,則新的 Promise 實(shí)例狀態(tài)才會(huì)變成resolve.Promise.race():將Promise對(duì)象數(shù)組中最先執(zhí)行完成的內(nèi)容通過后面then傳出promise的基本使用: 通過new promise創(chuàng)建一個(gè)promise對(duì)象,里面有一個(gè)參數(shù),參數(shù)是一個(gè)回調(diào)函數(shù), 回調(diào)函數(shù)中有2個(gè)參數(shù):resolve、reject resolve()當(dāng)異步執(zhí)行成功的時(shí)候調(diào)用的方法,reject()當(dāng)異步失敗的時(shí)候調(diào)用的方法。 除此之外promise有一個(gè)then方法,當(dāng)成功的時(shí)候執(zhí)行第一個(gè)回調(diào)函數(shù),當(dāng)失敗的時(shí)候執(zhí)行第二個(gè)回調(diào)函數(shù)。 第二個(gè)回調(diào)函數(shù)也可以通過promise對(duì)象.catch調(diào)用 Promise.all():當(dāng)所有的異步代碼都執(zhí)行完畢以后才會(huì)執(zhí)行.then中的操作 Promise.race():只要有一個(gè)promise執(zhí)行完畢后就會(huì)執(zhí)行.then操作promise的三種狀態(tài): 1.pending - 進(jìn)行中 2.fulfilled - 成功 3.rejected - 失敗鏈?zhǔn)秸{(diào)用: promise俗稱鏈?zhǔn)秸{(diào)用,它是es6中最重要的特性之一 簡單的說可以不停的then調(diào)用嵌套在調(diào)用(異步之后,鏈?zhǔn)秸{(diào)用方式執(zhí)行回調(diào)),這種操作方式稱為promiseasync異步能干什么? 就是用來修飾函數(shù),使該函數(shù)異步執(zhí)行,不阻礙后續(xù)函數(shù)的執(zhí)行 同時(shí)我們注意到,async修飾的函數(shù)也帶有then catch方法, 因此,經(jīng)async修飾的函數(shù)也 是一個(gè)promise await只能放在async中,且只能修飾promise對(duì)象 1. promise的誕生是為了簡化函數(shù)嵌套調(diào)用流程,也便于后續(xù)維護(hù) 2. async/await定義了異步函數(shù),并在其內(nèi)部可通過await等待promise對(duì)象,阻塞后 續(xù)的執(zhí)行 await關(guān)鍵字必須在async函數(shù)里面 await會(huì)阻塞當(dāng)前直到完成 async返回reject的方法,當(dāng)拋出異常等同于reject async / await與 Promise的主要區(qū)別是: Promise代碼完全都是Promise的API(then、catch等等),操作本身的語義反而不容易看出來, async / await函數(shù)的實(shí)現(xiàn)最簡潔,最符合語義,幾乎沒有語義不相關(guān)的代碼 async / await 函數(shù)就是 Generator 函數(shù)的語法糖async/await函數(shù)的優(yōu)勢(shì) 1. 使用async函數(shù)可以讓代碼簡潔很多,不需要像Promise一樣需要些then,不需要寫匿名函數(shù)處理Promise的resolve值,也不需要定義多余的data變量,還避免了嵌套代碼 2. 使用aync/await的話,catch能處理JSON.parse錯(cuò)誤 promise中不能處理 3. 條件語句也和錯(cuò)誤捕獲是一樣的,在 Async 中也可以像平時(shí)一般使用條件語句promise的狀態(tài)處理的原理:promise.all和promise.race
Pomise.all的使用Promise.all可以將多個(gè)Promise實(shí)例包裝成一個(gè)新的Promise實(shí)例。同時(shí),成功和失敗的返回值是不同的,成功的時(shí)候返回的是一個(gè)結(jié)果數(shù)組,而失敗的時(shí)候則返回最先被reject失敗狀態(tài)的值。Promise.all獲得的成功結(jié)果的數(shù)組里面的數(shù)據(jù)順序和Promise.all接收到的數(shù)組順序是一致的,在前端開發(fā)請(qǐng)求數(shù)據(jù)的過程中,偶爾會(huì)遇到發(fā)送多個(gè)請(qǐng)求并根據(jù)請(qǐng)求順序獲取和使用數(shù)據(jù)的場景,使用Promise.all毫無疑問可以解決這個(gè)問題。Promise.race的使用Promise.race就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])里面哪個(gè)結(jié)果獲得的快,就返回那個(gè)結(jié)果,不管結(jié)果本身是成功狀態(tài)還是失敗狀態(tài)。Generator
Generator 的中文名稱是生成器,它是ECMAScript6中提供的新特性。 在過去,封裝一段運(yùn)算邏輯的單元是函數(shù)。函數(shù)只存在“沒有被調(diào)用”或者“被調(diào)用”的情況, 不存在一個(gè)函數(shù)被執(zhí)行之后還能暫停的情況,而Generator的出現(xiàn)讓這種情況成為可能。通過 function* 來定義的函數(shù)稱之為“生成器函數(shù)”(generator function),它的特點(diǎn)是可以中斷函數(shù)的執(zhí)行, 每次執(zhí)行yield語句之后,函數(shù)即暫停執(zhí)行,直到調(diào)用返回的生成器對(duì)象的next()函數(shù)它才會(huì)繼續(xù)執(zhí)行。也就是說 Generator 函數(shù)是一個(gè)狀態(tài)機(jī),封裝了多個(gè)內(nèi)部狀態(tài)。 執(zhí)行 Generator 函數(shù)返回一個(gè)遍歷器對(duì)象(一個(gè)指向內(nèi)部狀態(tài)的指針對(duì)象), 調(diào)用遍歷器對(duì)象的next方法,使得指針移向下一個(gè)狀態(tài)。每次調(diào)用next方法, 內(nèi)部指針就從函數(shù)頭部或上一次停下來的地方開始執(zhí)行,直到遇到下一個(gè)yield表達(dá)式(或return語句)為止。yield關(guān)鍵字 真正讓Generator具有價(jià)值的是yield關(guān)鍵字,這個(gè)yield關(guān)鍵字讓 Generator內(nèi)部的邏輯能夠切割成多個(gè)部分。 發(fā)現(xiàn)函數(shù)執(zhí)行到第一個(gè)yield關(guān)鍵字的時(shí)候就停止了。要讓業(yè)務(wù)邏輯繼續(xù)執(zhí)行完,需要反復(fù)調(diào)用.next() 可以簡單地理解為yield關(guān)鍵字將程序邏輯劃分成幾部分,每次.next()執(zhí)行時(shí)執(zhí)行一部分。 這使得程序的執(zhí)行單元再也不是函數(shù),復(fù)雜的邏輯可以通過yield來暫停。.next()調(diào)用時(shí),返回一個(gè)對(duì)象,這個(gè)對(duì)象具備兩個(gè)屬性。 其中一個(gè)屬性是布爾型的done。它表示這個(gè)Generator對(duì)象的邏輯塊是否執(zhí)行完成。 另一個(gè)屬性是value,它來自于yield語句后的表達(dá)式的結(jié)果。通過.next()傳遞參數(shù),可以賦值給yield關(guān)鍵字前面的變量聲明。堆/棧
1、堆——引用類型地址傳遞堆:動(dòng)態(tài)分配的內(nèi)存,大小不定,不會(huì)自動(dòng)釋放。存放引用類型的值 先進(jìn)后出FILO引用類型: Object(Arrary, Date, Math,Function, Object)訪問方法: JS不能直接訪問內(nèi)存中的值, 只能操作對(duì)象的地址, 所以產(chǎn)生深/淺拷貝問題棧--基本類型值傳遞 2、棧——自動(dòng)分配內(nèi)存空間,系統(tǒng)自動(dòng)釋放,存放基本類型的值和引用類型的地址先進(jìn)先出FIFO基本類型: Undefined、Null、Boolean、Number 和 String, Symbol(ES6新增)訪問方法: 按值訪問, 直接操作內(nèi)存中的值深/淺拷貝及方法
深/淺拷貝針對(duì)的是引用類型淺拷貝 淺拷貝只復(fù)制指向某個(gè)對(duì)象的指針,而不復(fù)制對(duì)象本身,新舊對(duì)象還是共享同一塊內(nèi)存。 新舊互相影響,改變的是地址 新值===原值,只能拷貝一層數(shù)組方法: slice截取, concat拼接, filter過濾, map 對(duì)象方法: Object.assign({},obj), Object.create(obj)展開運(yùn)算符: {...obj},[...arr] 深拷貝 深拷貝會(huì)另外創(chuàng)造一個(gè)一模一樣的對(duì)象,新對(duì)象跟原對(duì)象不共享內(nèi)存,修改新對(duì)象不會(huì)改到原對(duì)象 新舊互不影響,改變的是值 新值=/=原值,可以拷貝多層1、JSON序列化JSON.parse(JSON.stringify(obj))對(duì)象-->字符串-->對(duì)象這個(gè)方式的弊端:1、如果obj里面有時(shí)間對(duì)象,則JSON.stringify后再JSON.parse的結(jié)果,時(shí)間將只是字符串的形式,而不是對(duì) 象的形式2、如果obj里有RegExp(正則表達(dá)式的縮寫)、Error對(duì)象,則序列化的結(jié)果將只得到空對(duì)象;3、如果obj里有函數(shù),undefined,則序列化的結(jié)果會(huì)把函數(shù)或 undefined丟失;4、如果obj里有NaN、Infinity和-Infinity,則序列化的結(jié)果會(huì)變成null5、JSON.stringify()只能序列化對(duì)象的可枚舉的自有屬性,不可枚舉的不能被復(fù)制可枚舉:可枚舉性(enumerable)用來控制所描述的屬性,是否將被包括在for...in循環(huán)之中。具體來說,如果一個(gè)屬性的enumerable為false,下面三個(gè)操作不會(huì)取到該屬性。for..in循環(huán)、Object.keys方法、JSON.stringify方法 2、原生實(shí)現(xiàn)遞歸+淺拷貝3、工具實(shí)現(xiàn)【第三方封裝庫】 loadsh _.cloneDeep(obj).DeepClone()用于 Model / Entity / ... ... 等引用類型對(duì)象的深度克隆特性說明1.不需要對(duì)對(duì)象做任何特殊處理,直接 .DeepClone() 即可得到該對(duì)象的深度克隆2.不受對(duì)象層次深度限制,均可實(shí)現(xiàn)深度克隆(下面會(huì)給出幾個(gè)簡單示例 ... ...) Immutable Object.create()set和map
Set:它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。 Set本身是一個(gè)構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu),數(shù)組作為參數(shù)。不說set 數(shù)據(jù)結(jié)構(gòu)Set new set()存儲(chǔ)數(shù)據(jù) set.size得到存儲(chǔ)的數(shù)據(jù)長度 has()判斷某個(gè)值是否存在set中 foreach遍歷set不說map : new map map.set map.get map.delete都是用來存儲(chǔ)數(shù)據(jù)用的,但是存儲(chǔ)的數(shù)據(jù)格式不同 set 直接存儲(chǔ) 任意類型數(shù)據(jù) map 存儲(chǔ)數(shù)據(jù)的時(shí)候,必須以key,value的形式, set 使用forEach 遍歷的時(shí)候,key和value值是一樣的 而map 遍歷的時(shí)候,key就是存進(jìn)去的對(duì)象的key,value就是存在的值for循環(huán)這種寫法比較麻煩,因此數(shù)組提供內(nèi)置的forEach方法。forEach沒有返回值,無法中途跳出forEach循環(huán),break命令或return命令都不能奏效。for...in循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的,不適用于遍歷數(shù)組**for...of循環(huán)相比上面幾種做法,有一些顯著的優(yōu)點(diǎn)。 有著同for...in一樣的簡潔語法,但是沒有for...in那些缺點(diǎn)。 不同于forEach方法,它可以與break、continue和return配合使用。 提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口。宏任務(wù)和微任務(wù)
js 是單線程執(zhí)行的,js中的任務(wù)按順序一個(gè)一個(gè)的執(zhí)行,但是一個(gè)任務(wù)耗時(shí)太長,那么后面的任務(wù)就需要等待,為了解決這種情況,將任務(wù)分為了同步任務(wù)和異步任務(wù),而異步任務(wù)又可以分為微任務(wù)和宏任務(wù)概念 1.宏任務(wù):當(dāng)前調(diào)用棧中執(zhí)行的代碼成為宏任務(wù)。(主代碼快,定時(shí)器等等)。 2.微任務(wù):當(dāng)前(此次事件循環(huán)中)宏任務(wù)執(zhí)行完,在下一個(gè)宏任務(wù)開始之前需要執(zhí)行的任務(wù),可以理解為回調(diào)事件。(promise.then,proness.nextTick等等)。 3.宏任務(wù)中的事件放在callback queue中,由事件觸發(fā)線程維護(hù);微任務(wù)的事件放在微任務(wù)隊(duì)列中,由js引擎線程維護(hù)。運(yùn)行機(jī)制 1. 在執(zhí)行棧中執(zhí)行一個(gè)宏任務(wù)。 2. 執(zhí)行過程中遇到微任務(wù),將微任務(wù)添加到微任務(wù)隊(duì)列中。 3. 當(dāng)前宏任務(wù)執(zhí)行完畢,立即執(zhí)行微任務(wù)隊(duì)列中的任務(wù)。 4. 當(dāng)前微任務(wù)隊(duì)列中的任務(wù)執(zhí)行完畢,檢查渲染,GUI線程接管渲染。 5. 渲染完畢后,js線程接管,開啟下一次事件循環(huán),執(zhí)行下一次宏任務(wù)(事件隊(duì)列中取)。微任務(wù):process.nextTick、MutationObserver、Promise.then catch finally 宏任務(wù):I/O、setTimeout、setInterval、setImmediate、requestAnimationFramejs執(zhí)行順序,(先執(zhí)行宏任務(wù)列,微任務(wù)隊(duì)列) 先同步再異步,在此基礎(chǔ)上先宏任務(wù)再微任務(wù)流程:同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行“場所”,同步進(jìn)入主線程,異步進(jìn)入Event Table并注冊(cè)函數(shù)。當(dāng)指定的事情完成時(shí),Event Table會(huì)將這個(gè)函數(shù)移入Event Queue。主線程內(nèi)的任務(wù)執(zhí)行完畢為空,回去了Event Queue讀取對(duì)應(yīng)的函數(shù),進(jìn)入主線程。上述過程會(huì)不斷重復(fù),也就是常說的Event Loop(事件循環(huán))。但是,JS異步還有一個(gè)機(jī)制,就是遇到宏任務(wù),先執(zhí)行宏任務(wù),將宏任務(wù)放入event queue,然后再執(zhí)行微任務(wù),將微任務(wù)放入eventqueue,但是,這兩個(gè)queue不是一個(gè)queue。當(dāng)你往外拿的時(shí)候先從微任務(wù)里拿這個(gè)回調(diào)函數(shù),然后再從宏任務(wù)的queue拿宏任務(wù)的回調(diào)函數(shù),js異步操作
1、定時(shí)器都是異步操作 2、事件綁定都是異步操作 3、AJAX中一般我們都采取異步操作(也可以同步) 4、回調(diào)函數(shù)可以理解為異步(不是嚴(yán)謹(jǐn)?shù)漠惒讲僮?#xff09; 5、promise 6、generator(ES6) 通過yield關(guān)鍵字可以讓任務(wù)在需要的地方暫停,每一步的值可以通過next獲取 7、async/await(ES7) await得到的就是async異步返回值,底層原理還是promise中的resolve方法 8、設(shè)計(jì)模式-發(fā)布訂閱模式 9、事件監(jiān)聽表單只能輸入數(shù)字
正則 type numberProxy和Reflect
Proxy用于修改某些操作的默認(rèn)行為,即對(duì)編程語言層面進(jìn)行修改,屬于“元編程”,Proxy意思為“代理”,即在訪問對(duì)象之前建立一道“攔截”,任何訪問該對(duì)象的操作之前都會(huì)通過這道“攔截”,即執(zhí)行Proxy里面定義的方法let pro = new Proxy(target,handler)其中 new Proxy相當(dāng)于創(chuàng)建了一個(gè)Proxy實(shí)例,target為所要攔截的目標(biāo)對(duì)象,handler也是一個(gè)對(duì)象,里面定義的是對(duì)攔截對(duì)象所要進(jìn)行的攔截方法Proxy也可以作為其他對(duì)象的原型對(duì)象使用上述實(shí)例將pro作為obj的原型對(duì)象使用,雖然obj本身沒有name這個(gè)屬性,但是根據(jù)原型鏈,會(huì)在pro上讀取到name屬性,之后會(huì)執(zhí)行相對(duì)應(yīng)的攔截操作。let pro = new Proxy(target,handler); let obj = Object.create(pro);Proxy常用的攔截方法
get(target,name,property)方法 用于攔截某個(gè)讀取屬性的操作,第一個(gè)參數(shù)為目標(biāo)對(duì)象,第二個(gè)參數(shù)為屬性名稱,第三個(gè)屬性為操作所針對(duì)的對(duì)象(可選參數(shù))set(target,name,value,property) 用于攔截某個(gè)屬性的賦值操作,第一個(gè)參數(shù)為目標(biāo)對(duì)象,第二個(gè)參數(shù)為屬性名,第三個(gè)參數(shù)為屬性值,第四個(gè)參數(shù)為操作行為所針對(duì)的對(duì)象(可選參數(shù))has(target,key) 用來攔截對(duì)象是否具有某個(gè)屬性值的操作,第一個(gè)參數(shù)為目標(biāo)對(duì)象,第二個(gè)參數(shù)為屬性名Reflect(銳付萊克特)對(duì)象: Reflect設(shè)計(jì)的目的是為了優(yōu)化Object的一些操作方法以及合理的返回Object操作返回的結(jié)果,對(duì)于一些命令式的Object行為,Reflect對(duì)象可以將其變?yōu)楹瘮?shù)式的行為Reflect(target,name,property) Reflect.has(obj,"name") Reflect.get(target,name,property)瀏覽器優(yōu)化
減少請(qǐng)求數(shù)量圖片處理雪碧圖gulp Base64 使用字體圖標(biāo)來代替圖片 - 自定義字體 @font-face{} 在安卓下可以使用webp格式的圖片減小資源大小 - webpack優(yōu)化HTML壓縮CSS壓縮JS壓縮與混亂圖片壓縮優(yōu)化網(wǎng)絡(luò)連接cdnCDN即內(nèi)容分發(fā)網(wǎng)絡(luò),它能夠?qū)崟r(shí)地根據(jù)網(wǎng)絡(luò)流量和各節(jié)點(diǎn)的連接、負(fù)載狀用戶可就近取得所需內(nèi)容,解決 Internet網(wǎng)絡(luò)擁擠的狀況,提高用戶訪問網(wǎng)站的響應(yīng)速度優(yōu)化資源加載資源加載位置1、CSS文件放在head中,先外鏈,后本頁2、JS文件放在body底部,先外鏈,后本頁3、body中間盡量不寫style標(biāo)簽和script標(biāo)簽資源加載時(shí)機(jī)1、異步script標(biāo)簽2、模塊按需加載需要根據(jù)路由來加載當(dāng)前頁面需要的業(yè)務(wù)模塊3、資源懶加載與資源預(yù)加載減少重繪回流當(dāng)render tree中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸,布局,隱藏等改變而需要重新構(gòu)建。這就稱為回流當(dāng)render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風(fēng)格,而不會(huì)影響布局的,比如 background-color。則就叫稱為重繪。回流必將引起重繪,而重繪不一定會(huì)引起回流。css3硬件加速(GPU加速)六.【DOM優(yōu)化】 1、緩存DOM 2、減少DOM深度及DOM數(shù)量 3、批量操作DOM 4、批量操作CSS樣式 5、在內(nèi)存中操作DOM 6、DOM元素離線更新 7、DOM讀寫分離 8、事件代理 9、防抖和節(jié)流 10、及時(shí)清理環(huán)境請(qǐng)求頭
Accept(艾可塞克特) 告訴WEB服務(wù)器自己接受什么介質(zhì)類型,*/* 表示任何類型,type/* 表示該類型下的所有子類型,type/sub-type。Accept-Charset(恰斯特) 瀏覽器告訴服務(wù)器自己能接收的字符集。Accept-Encoding(因扣定) 瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支持壓縮,支持什么壓縮方法(gzip,deflate)Accept-Language 瀏覽器申明自己接收的語言。語言跟字符集的區(qū)別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等。Authorization(哦瑟惹C遜) 當(dāng)客戶端接收到來自WEB服務(wù)器的 WWW-Authenticate 響應(yīng)時(shí),用該頭部來回應(yīng)自己的身份驗(yàn)證信息給WEB服務(wù)器。If-Match 如果對(duì)象的 ETag 沒有改變,其實(shí)也就意味著對(duì)象沒有改變,才執(zhí)行請(qǐng)求的動(dòng)作,獲取文檔。If-None-Match 如果對(duì)象的 ETag 改變了,其實(shí)也就意味著對(duì)象也改變了,才執(zhí)行請(qǐng)求的動(dòng)作,獲取文檔。(莫得反得) If-Modified-Since(森恩斯) 如果請(qǐng)求的對(duì)象在該頭部指定的時(shí)間之后修改了,才執(zhí)行請(qǐng)求的動(dòng)作(比如返回對(duì)象),否則返回代碼304,告訴瀏覽器該對(duì)象沒有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMTIf-Unmodified-Since 如果請(qǐng)求的對(duì)象在該頭部指定的時(shí)間之后沒修改過,才執(zhí)行請(qǐng)求的動(dòng)作(比如返回對(duì)象)。If-Range /reinge/ 瀏覽器告訴 WEB 服務(wù)器,如果我請(qǐng)求的對(duì)象沒有改變,就把我缺少的部分給我,如果對(duì)象改變了,就把整個(gè)對(duì)象給我。瀏覽器通過發(fā)送請(qǐng)求對(duì)象的ETag 或者自己所知道的最后修改時(shí)間給 WEB 服務(wù)器,讓其判斷對(duì)象是否改變了。總是跟 Range 頭部一起使用。Range 瀏覽器(比如 Flashget 多線程下載時(shí))告訴 WEB 服務(wù)器自己想取對(duì)象的哪部分。例如:Range: bytes=1173546Proxy-Authenticate(噢三特K特) 代理服務(wù)器響應(yīng)瀏覽器,要求其提供代理身份驗(yàn)證信息。Proxy-Authorization 瀏覽器響應(yīng)代理服務(wù)器的身份驗(yàn)證請(qǐng)求,提供自己的身份信息。Host 客戶端指定自己想訪問的WEB服務(wù)器的域名/IP 地址和端口號(hào)。如Host:rss.sina.com.cnReferer(銳佛爾) 瀏覽器向WEB 服務(wù)器表明自己是從哪個(gè)網(wǎng)頁URL獲得點(diǎn)擊當(dāng)前請(qǐng)求中的網(wǎng)址/URL, 例如:Referer:http://www.ecdoer.com/User-Agent(A就特) 瀏覽器表明自己的身份(是哪種瀏覽器)。 例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN;rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14static有什么特性
new出來一個(gè)實(shí)例對(duì)象是否帶有static屬性 static用ES5怎么寫沒有創(chuàng)建對(duì)象,也能使用屬性和調(diào)用方法用來形成靜態(tài)代碼塊以優(yōu)化程序性能。因?yàn)橹粫?huì)在類加載的時(shí)候執(zhí)行一次。因此,很多時(shí)候會(huì)將一些只需要進(jìn)行一次的初始化操作都放在static代碼塊中進(jìn)行。static塊可以置于類中的任何地方,類中可以有多個(gè)static塊。在類初次被加載的時(shí)候,會(huì)按照static塊的順序來執(zhí)行每個(gè)static塊,并且只會(huì)執(zhí)行一次被static修飾的變量或者方法是獨(dú)立于該類的任何對(duì)象,也就是說,這些變量和方法不屬于任何一個(gè)實(shí)例對(duì)象,而是被類的實(shí)例對(duì)象所共享。類第一次加載初始化的時(shí)候就去加載static部分,后面可以重新賦值static用ES5怎么寫: 靜態(tài)是通過類名直接調(diào)用 class A staticB 直接用A.B 將B綁定在A上async await
同步還是異步 await同步 async異步async和await有兩個(gè)關(guān)鍵字,一個(gè)寫在函數(shù)外面,一個(gè)寫在函數(shù)里面,函數(shù)外面是異步的,函數(shù)里面是同步的,調(diào)用函數(shù)的那一行其實(shí)是異步的,下一行 函數(shù)里面轉(zhuǎn)成阻塞的async await => promise 改寫async函數(shù)中 let a=await promise 的a函數(shù) let b=await promise 的b函數(shù)promise.all改寫 Promise.allSettled Promise.anypromise實(shí)現(xiàn)promise.all的方法async使用的時(shí)候報(bào)錯(cuò),如何捕獲try...catchvar test3 = async function () {try {await p1();await p2();p3();} catch (e) {console.log('p1失敗了', e)}}await后面有個(gè)接口 接口要2S才能完成 接口2S才會(huì)執(zhí)行$.ajax中async:false的阻塞和await這種阻塞有什么區(qū)別
沒區(qū)別怎么攜帶cookie發(fā)送給后端
設(shè)置請(qǐng)求頭 請(qǐng)求頭中攜帶cookie對(duì)象淺拷貝在react中用到哪些地方,為什么
為什么在react中要使用淺拷貝redux中要求:狀態(tài)是只讀的,唯一且不可修改的,reducer必須是一個(gè)純函數(shù)因?yàn)閞edux中數(shù)據(jù)不可更改,所以redux中的數(shù)據(jù)應(yīng)該要拷貝 返回一個(gè)新值ajax、axios、fetch之間的詳細(xì)區(qū)別以及優(yōu)缺點(diǎn)
1.jQuery ajax $.ajax({type: 'POST',url: url,data: data,dataType: dataType,success: function () {},error: function () {}}); 優(yōu)缺點(diǎn):是對(duì)原生XHR的封裝,除此以外還增添了對(duì)JSONP的支持。本身是針對(duì)MVC的編程,不符合現(xiàn)在前端MVVM的浪潮基于原生的XHR開發(fā),XHR本身的架構(gòu)不清晰,已經(jīng)有了fetch的替代方案JQuery整個(gè)項(xiàng)目太大,單純使用ajax卻要引入整個(gè)JQuery非常的不合理(采取個(gè)性化打包的方案又不能享受CDN服務(wù))2.axiosaxios({method: 'post',url: '/user/12345',data: {firstName: 'Fred',lastName: 'Flintstone'}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);}); 優(yōu)缺點(diǎn):Axios本質(zhì)上也是對(duì)原生XHR的封裝,只不過它是Promise的實(shí)現(xiàn)版本,符合最新的ES規(guī)范,從它的官網(wǎng)上可以看到它有以下幾條特性:從 node.js 創(chuàng)建 http 請(qǐng)求支持 Promise API客戶端支持防止CSRF提供了一些并發(fā)請(qǐng)求的接口(重要,方便了很多的操作)3.fetchtry {let response = await fetch(url);let data = response.json();console.log(data);} catch(e) {console.log("Oops, error", e);} 優(yōu)缺點(diǎn):符合關(guān)注分離,沒有將輸入、輸出和用事件來跟蹤的狀態(tài)混雜在一個(gè)對(duì)象里更好更方便的寫法更加底層,提供的API豐富(request, response)脫離了XHR,是ES規(guī)范里新的實(shí)現(xiàn)方式fetch是一個(gè)低層次的API,你可以把它考慮成原生的XHR,所以使用起來并不是那么舒服, 需要進(jìn)行封裝,例如: 1)fetch只對(duì)網(wǎng)絡(luò)請(qǐng)求報(bào)錯(cuò),對(duì)400,500都當(dāng)做成功的請(qǐng)求,需要封裝去處理 2)fetch默認(rèn)不會(huì)帶cookie,需要添加配置項(xiàng) 3)fetch不支持abort,不支持超時(shí)控制,使用setTimeout及Promise.reject的實(shí)現(xiàn)的超時(shí)控制并不能阻止請(qǐng)求過程繼續(xù)在后臺(tái)運(yùn)行,造成了量的浪費(fèi) 4)fetch沒有辦法原生監(jiān)測請(qǐng)求的進(jìn)度,而XHR可以為什么要用axios? axios 是一個(gè)基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特征:從瀏覽器中創(chuàng)建 XMLHttpRequest從 node.js 發(fā)出 http 請(qǐng)求支持 Promise API攔截請(qǐng)求和響應(yīng)轉(zhuǎn)換請(qǐng)求和響應(yīng)數(shù)據(jù)取消請(qǐng)求自動(dòng)轉(zhuǎn)換JSON數(shù)據(jù)客戶端支持防止CSRF/XSRF回流/重繪 | 防抖/節(jié)流
回流: 當(dāng)渲染樹中的一部分或者全部因?yàn)樵氐某叽纭⒉季帧㈦[藏等改變而需要重新構(gòu)建的時(shí)候,這時(shí) 候就會(huì)發(fā)生回流。 每個(gè)?面都至少發(fā)生一次回流,也就是?面第一次加載的時(shí)候。 在回流的時(shí)候,瀏覽器會(huì)使渲染樹中受到影響的元素部分失效,并重新繪制這個(gè)部分的渲染樹, 完成回流以后,重繪: 當(dāng)渲染樹中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風(fēng)格,而不會(huì)影響布局的,比如background-color。則就叫稱為重繪。防抖: 短時(shí)間內(nèi)多次觸發(fā)同一事件,只執(zhí)行最后一次,或者只執(zhí)行最開始的一次,中間的不執(zhí)行。 在事件觸發(fā)時(shí),開始計(jì)時(shí),在規(guī)定的時(shí)間(delay)內(nèi),若再次觸發(fā)事件,將上一次計(jì)時(shí)(timer)清空,然后重新開始計(jì)時(shí)。保證只有在規(guī)定時(shí)間內(nèi)沒有再次觸發(fā)事件之后,再去執(zhí)行這個(gè)事件。 節(jié)流: 指定時(shí)間間隔內(nèi),若事件被多次觸發(fā),只會(huì)執(zhí)行一次 在事件觸發(fā)之后,開始計(jì)時(shí),在規(guī)定的時(shí)間(delay)內(nèi),若再次觸發(fā)事件,不對(duì)此事件做任何處理。保證在規(guī)定時(shí)間內(nèi)只執(zhí)行一次事件.減少重繪和回流的方式
CSS使用transform替代top使用visibility替換display:none避免使用table布局盡可能在DOM樹的最末端改變class避免設(shè)置多層內(nèi)聯(lián)樣式將動(dòng)畫效果應(yīng)用到position屬性為absoulte或fixed的元素上避免使用css表達(dá)式將頻繁重繪或者回流的節(jié)點(diǎn)設(shè)置為圖層css硬件加速JavaScript避免頻繁操作樣式避免頻繁操作DOM避免頻繁讀取會(huì)引發(fā)重繪/回流的屬性對(duì)具有復(fù)雜動(dòng)畫的元素使用絕對(duì)定位事件循環(huán)Event Loop
Event Loop 即事件循環(huán) 是指瀏覽器或者Node的一種解決JavaScript單線程運(yùn)行時(shí)不阻塞的一種機(jī)制,單線程的是所有任務(wù)都在主線程上完成,任務(wù)太多的時(shí)候,頁面卡死,eventLoop可以解決單線程阻塞問題,程序中會(huì)有兩個(gè)線程,一個(gè)主線程,一個(gè)eventLoop線程,負(fù)責(zé)主線程和其他進(jìn)程之間的通信,遇到I/O的時(shí)候,主線程會(huì)讓eventLoop線程通知對(duì)應(yīng)的程序,主線程的任務(wù)會(huì)繼續(xù)往后執(zhí)行,等I/O程序執(zhí)行完了,eventLoop線程會(huì)把結(jié)果返回給主線程,主線程利用回調(diào)函數(shù)調(diào)用結(jié)果,完成任務(wù) (1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)。 (2)主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件。 (3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列",看看里面有哪些事件。那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。 (4)主線程不斷重復(fù)上面的第三步。宏任務(wù)和微任務(wù)的執(zhí)行順序一次事件循環(huán)中,先執(zhí)行宏任務(wù)隊(duì)列里的一個(gè)任務(wù),再把微任務(wù)隊(duì)列里的所有任務(wù)執(zhí)行完畢,再去宏任務(wù)隊(duì)列取下一個(gè)宏任務(wù)執(zhí)行。同步異步的區(qū)別
在js中,所有任務(wù)都分為同步任務(wù)和異步任務(wù)兩大類。同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù);異步任務(wù)指的是,不進(jìn)入主線程、而進(jìn)入"任務(wù)隊(duì)列"(task queue)的任務(wù),只有"任務(wù)隊(duì)列"通知主線程,某個(gè)異步任務(wù)可以執(zhí)行了,該任務(wù)才會(huì)進(jìn)入主線程執(zhí)行。(1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)。 (2)主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件。 (3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列",看看里面有哪些事件。那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。 (4)主線程不斷重復(fù)上面的第三步。有時(shí)候 setTimeout明明寫的延時(shí)3秒,實(shí)際卻5,6秒才執(zhí)行函數(shù),這又是因?yàn)槭裁?#xff1f;答:setTimeout 并不能保證執(zhí)行的時(shí)間,是否及時(shí)執(zhí)行取決于 JavaScript 線程是擁擠還是空閑。 瀏覽器的JS引擎遇到setTimeout,拿走之后不會(huì)立即放入異步隊(duì)列,同步任務(wù)執(zhí)行之后,timer模塊會(huì)到設(shè)置時(shí)間之后放到異步隊(duì)列中。js引擎發(fā)現(xiàn)同步隊(duì)列中沒有要執(zhí)行的東西了,即運(yùn)行棧空了就從異步隊(duì)列中讀取,然后放到運(yùn)行棧中執(zhí)行。所以setTimeout可能會(huì)多了等待線程的時(shí)間。 這時(shí)setTimeout函數(shù)體就變成了運(yùn)行棧中的執(zhí)行任務(wù),運(yùn)行棧空了,再監(jiān)聽異步隊(duì)列中有沒有要執(zhí)行的任務(wù),如果有就繼續(xù)執(zhí)行,如此循環(huán),就叫Event Loop。數(shù)據(jù)請(qǐng)求設(shè)置請(qǐng)求數(shù)據(jù)格式Content-Type
1.瀏覽器默認(rèn)的 application/x-www-form-urlencoded(url因扣得的) 這應(yīng)該是最常見的 POST 提交數(shù)據(jù)的方式了。瀏覽器的原生 form 表單,如果不設(shè)置 enctype 屬性,那么最終就會(huì)以 application/x-www-form-urlencoded 方式提交數(shù)據(jù)。2.multipart(莫踢怕特)/form-data 這也是一個(gè)常見的 POST 數(shù)據(jù)提交的方式。我們使用表單上傳文件時(shí),就要讓 form 的 enctype 等于這個(gè)值3.application/json 除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify 4.text/xml 相比于JSON,不能更好的適用于數(shù)據(jù)交換,它包含了太多的包裝, 而且它跟大多數(shù)編程語言的數(shù)據(jù)模型不匹配,讓大多數(shù)程序員感到詫異,XML是面向數(shù)據(jù)的,JSON是面向?qū)ο蠛徒Y(jié)構(gòu)的,JSON會(huì)給程序員一種更加親切的感覺。數(shù)組扁平化
flat(infinite)
1. reduce遍歷數(shù)組每一項(xiàng),若值為數(shù)組則遞歸遍歷,否則concat。function flatten(arr) { return arr.reduce((result, item)=> {return result.concat(Array.isArray(item) ? flatten(item) : item);}, []); }reduce是數(shù)組的一種方法,它接收一個(gè)函數(shù)作為累加器,數(shù)組中的每個(gè)值(從左到右)開始縮減,最終計(jì)算為一個(gè)值。 reduce包含兩個(gè)參數(shù):回調(diào)函數(shù),傳給total的初始值// 求數(shù)組的各項(xiàng)值相加的和: arr.reduce((total, item)=> { // total為之前的計(jì)算結(jié)果,item為數(shù)組的各項(xiàng)值return total + item; }, 0);2. toString & split 調(diào)用數(shù)組的toString方法,將數(shù)組變?yōu)樽址缓笤儆胹plit分割還原為數(shù)組function flatten(arr) {return arr.toString().split(',').map(function(item) {return Number(item);}) } 因?yàn)閟plit分割后形成的數(shù)組的每一項(xiàng)值為字符串,所以需要用一個(gè)map方法遍歷數(shù)組將其每一項(xiàng)轉(zhuǎn)換為數(shù)值型3. join & split 和上面的toString一樣,join也可以將數(shù)組轉(zhuǎn)換為字符串function flatten(arr) {return arr.join(',').split(',').map(function(item) {return parseInt(item);}) }4. 遞歸遞歸的遍歷每一項(xiàng),若為數(shù)組則繼續(xù)遍歷,否則concatfunction flatten(arr) {var res = [];arr.map(item => {if(Array.isArray(item)) {res = res.concat(flatten(item));} else {res.push(item);}});return res; }5. 擴(kuò)展運(yùn)算符 es6的擴(kuò)展運(yùn)算符能將二維數(shù)組變?yōu)橐痪S[].concat(...[1, 2, 3, [4, 5]]); // [1, 2, 3, 4, 5]根據(jù)這個(gè)結(jié)果我們可以做一個(gè)遍歷,若arr中含有數(shù)組則使用一次擴(kuò)展運(yùn)算符,直至沒有為止。function flatten(arr) {while(arr.some(item=>Array.isArray(item))) {arr = [].concat(...arr);}return arr; }如何擴(kuò)展數(shù)組,讓他擁有新的方法
Array.prototype.push.apply(a,b)class中super作用是什么
es5 的繼承是先創(chuàng)建子類的this,然后將父類的方法添加到子類的this上去; es6 的繼承是創(chuàng)建父類的this對(duì)象,然后再對(duì)this對(duì)象添加方法/屬性。 而super方法就是用來創(chuàng)建父類this對(duì)象的。實(shí)際上執(zhí)行的是 super.sport.call(this);xss攻擊和csrf攻擊是什么
1、CSRF(Cross-site request forgery):跨站請(qǐng)求偽造。 (1)登錄受信任網(wǎng)站A,并在本地生成Cookie。(如果用戶沒有登錄網(wǎng)站A,那么網(wǎng)站B在誘導(dǎo)的時(shí)候,請(qǐng)求網(wǎng)站A的api 接口時(shí),會(huì)提示你登錄) (2)在不登出A的情況下,訪問危險(xiǎn)網(wǎng)站B(其實(shí)是利用了網(wǎng)站A的漏洞)CSRF如何防御 方法一: Token 驗(yàn)證:(用的最多)(1)服務(wù)器發(fā)送給客戶端一個(gè)token;(2)客戶端提交的表單中帶著這個(gè)token。(3)如果這個(gè) token 不合法,那么服務(wù)器拒絕這個(gè)請(qǐng)求。 方法二: 隱藏令牌:把 token 隱藏在 http 的 head頭中。方法二和方法一有點(diǎn)像,本質(zhì)上沒有太大區(qū)別,只是使用方式上有區(qū)別。 方法三: Referer(銳服爾) 驗(yàn)證:Referer 指的是頁面請(qǐng)求來源。意思是,只接受本站的請(qǐng)求,服務(wù)器才做響應(yīng);如果不是,就攔截。2、XSS(Cross Site Scripting):跨域腳本攻擊。 XSS攻擊的核心原理是:不需要你做任何的登錄認(rèn)證,它會(huì)通過合法的操作(比如在url中輸入、在評(píng)論框中輸入),向你的頁面注入腳本(可能是js、hmtl代碼塊等)。 最后導(dǎo)致的結(jié)果可能是:盜用Cookie破壞頁面的正常結(jié)構(gòu),插入廣告等惡意內(nèi)容D-doss攻擊 XSS的攻擊方式 1、反射型發(fā)出請(qǐng)求時(shí),XSS代碼出現(xiàn)在url中,作為輸入提交到服務(wù)器端,服務(wù)器端解析后響應(yīng),XSS代碼隨響應(yīng)內(nèi)容一起傳回給瀏覽器,最后瀏覽器解析執(zhí)行XSS代碼。這個(gè)過程像一次反射,所以叫反射型XSS。 2、存儲(chǔ)型存儲(chǔ)型XSS和反射型XSS的差別在于,提交的代碼會(huì)存儲(chǔ)在服務(wù)器端(數(shù)據(jù)庫、內(nèi)存、文件系統(tǒng)等),下次請(qǐng)求時(shí)目標(biāo)頁面時(shí)不用再提交XSS代碼。XSS的防范措施(encode + 過濾)主要有三個(gè): 1、編碼:對(duì)用戶輸入的數(shù)據(jù)進(jìn)行HTML Entity(安特踢) 編碼。 2、過濾:移除用戶輸入的和事件相關(guān)的屬性。如onerror可以自動(dòng)觸發(fā)攻擊,還有onclick等。(總而言是,過濾掉一些不安全的內(nèi)容)移除用戶輸入的Style節(jié)點(diǎn)、Script節(jié)點(diǎn)、Iframe節(jié)點(diǎn)。(尤其是Script節(jié)點(diǎn),它可是支持跨域的呀,一定要移除)。 3、校正避免直接對(duì)HTML Entity進(jìn)行解碼。使用DOM Parse轉(zhuǎn)換,校正不配對(duì)的DOM標(biāo)簽。這個(gè)概念,它的作用是把文本解析成DOM結(jié)構(gòu)。比較常用的做法是,通過第一步的編碼轉(zhuǎn)成文本,然后第三步轉(zhuǎn)成DOM對(duì)象,然后經(jīng)過第二步的過濾。還有一種簡潔的答案:首先是encode,如果是富文本,就白名單。3、CSRF 和 XSS 的區(qū)別: 區(qū)別一:CSRF:需要用戶先登錄網(wǎng)站A,獲取 cookie。XSS:不需要登錄。 區(qū)別二:(原理的區(qū)別)CSRF:是利用網(wǎng)站A本身的漏洞,去請(qǐng)求網(wǎng)站A的api。XSS:是向網(wǎng)站 A 注入 JS代碼,然后執(zhí)行 JS 里的代碼,篡改網(wǎng)站A的內(nèi)容。webapp和小程序有什么區(qū)別
首先,微信小程序已經(jīng)提供了一套 view, data, model, router 層的開發(fā)工具, 對(duì)于開發(fā)簡單應(yīng)用,小程序是可以比 webapp 更加快速的。但是實(shí)際上微信小程序提供的這一套開發(fā)框架,要開發(fā)一些復(fù)雜應(yīng)用,是很困難的, 因?yàn)?#xff1a;小程序不支持 npm 等 package manager(麥呢橘)無法復(fù)用社區(qū)中已經(jīng)很成熟的 web 框架和工具組件只能封裝 view 和 style,無法封裝行為(handler),行為只能定義在 page 上小程序有 1mb 的限制,所以我們只能將圖片之類的靜態(tài)資源事先放在服務(wù)器上其次,微信小程序是由微信自己來 host,開發(fā)者只需要上傳就好, 而微信 webapp 需要開發(fā)者自己 host,還需要注冊(cè)域名甚至備案才可以調(diào)用微信接口以及跟公眾號(hào)集成。 所以微信小程序降低了開發(fā)者的門檻。綜上,對(duì)于簡單的工具型應(yīng)用,微信小程序可以讓開發(fā)者加快開發(fā)速度,降低發(fā)布門檻, 這種類型的應(yīng)用比較適合微信小程序。對(duì)于復(fù)雜的應(yīng)用,webapp 是更適合的形式。react優(yōu)缺點(diǎn)
優(yōu)點(diǎn): 1、采用虛擬 DOM,它并不直接對(duì)DOM進(jìn)行操作,安插在javascript邏輯和實(shí)際的DOM之間,性能好 2、跨瀏覽器兼容:虛擬DOM幫助我們解決了跨瀏覽器問題,它為我們提供了標(biāo)準(zhǔn)化的API,甚至在IE8中都是沒問題的。 3、一切都是組件:代碼更加 模塊化 ,重用代碼更容易,可維護(hù)性高。 4、單向數(shù)據(jù)流:redux 實(shí)現(xiàn)是一個(gè)用于在JavaScript應(yīng)用中創(chuàng)建單向數(shù)據(jù)層的架構(gòu),它隨著React視圖庫的開發(fā)而被Facebook概念化。 5、同構(gòu)、純粹的javascript:因?yàn)樗阉饕娴呐老x程序依賴的是服務(wù)端響應(yīng)而不是JavaScript的執(zhí)行,預(yù)渲染你的應(yīng)用有助于搜索引擎優(yōu)化。 6、兼容性好:比如使用RequireJS來加載和打包,而Browserify(不弱瑟)和Webpack適用于構(gòu)建大型應(yīng)用。它們使得那些艱難的任務(wù)不再讓人望而生畏。 7、JSX語法:為了更加便利的模擬DOM結(jié)構(gòu),我們使用了JSX語法,可以讓我們?cè)贘S中編譯DOM結(jié)構(gòu) 8、函數(shù)式編程:JS的最大特點(diǎn)就是函數(shù)式編程,在React中,函數(shù)式編程可謂式無處不見缺點(diǎn): 不適合單獨(dú)做一個(gè)完整的框架:react是視圖層框架,大型項(xiàng)目想要一套完整的框架的話,也許還需要引入Flux和route相關(guān)的東西。react生命周期
16版本: 初始階段: constructor定義state componentWillMount(這個(gè)鉤子函數(shù)在將來會(huì)被棄用)為掛載做準(zhǔn)備工作 render 解析 this.state 和 this.props 將jsx型的虛擬dom渲染為對(duì)象類型的虛擬domrender 中不允許使用 this.setState() 如何你使用了,就會(huì)棧溢出 componentDidMount表示組件掛載結(jié)束虛擬dom -> Real dom可以獲取真實(shí)dom數(shù)據(jù)請(qǐng)求 -> 賦值給state第三方庫實(shí)例化/DOM操作更新階段: componentWillReceiveProps(在17版本中被棄用)這個(gè)鉤子實(shí)際作用是判斷組件身上的props是否發(fā)生改變 shouldComponentUpdate可以決組件是否要更新渲染 return true/false接收新舊狀態(tài),用于作對(duì)比(淺對(duì)比)一般需要我們手動(dòng)作深對(duì)比這個(gè)鉤子函數(shù)是React組件性能優(yōu)化的一種方式 componentWillUpdate表示組件更新前的準(zhǔn)備這個(gè)鉤子函數(shù)在未來版本被棄用 render和初始化階段的作用一致 componentDidUpdate對(duì)Real dom 作操作注意:父組件數(shù)據(jù)更新,子組件會(huì)重新運(yùn)行render,反之不行每次都要運(yùn)行子組件render,會(huì)造成react性能浪費(fèi) 粗略解決方案:在shouldComponentUpdate中,可判斷哪些數(shù)據(jù)改變從而來控制return true/false 繼而決定是否需要更新render渲染更好的解決方案:1.引用PureComponent,讓類組件繼承(extends)PureComponent 如:class App extends PureComponent{}2.引用memo,讓函數(shù)組件寫在memo()里 如:const memoApp =memo(function App() {})3.除了memo之外,更細(xì)致的是函數(shù)組件中還可以用useCallback(方法)和useMemo(對(duì)象和數(shù)組)兩個(gè)鉤子阻止組件render銷毀階段: componentWillUnmount銷毀組件清除無用實(shí)例和事件 錯(cuò)誤捕獲:componentDidCatch用戶捕獲子組件throw的錯(cuò)誤,然后顯示回退UI15版本: 相對(duì)于16版本,初始化階段(constructor鉤子變成下列兩個(gè)):定義于初始化props的 getDefalutProps 鉤子函數(shù)定義于初始化state的 getInitialState 鉤子函數(shù) 沒有錯(cuò)誤捕獲階段17版本: 相對(duì)于16版本 少3多2少了componentWillMount,componentWillReceiveProps,componentWillUpdate 3個(gè)鉤子函數(shù)(斯塔得可) (迪外的) 多了static getDerivedStateFromProps鉤子函數(shù) (破外服)一個(gè)靜態(tài)方法,所以不能在這個(gè)函數(shù)里面使用this,這個(gè)函數(shù)有兩個(gè)參數(shù)nextProps和prevState,這個(gè)函數(shù)會(huì)返回一個(gè)對(duì)象用來更新當(dāng)前的state對(duì)象,如果不需要更新可以返回null。簡單說就是,可以增加一次state狀態(tài)(斯那坡秀的) 多了getSnapshotBeforeUpdate鉤子函數(shù)快照這個(gè)函數(shù)有一個(gè)返回值,會(huì)作為第三個(gè)參數(shù)傳遞給componentDidUpdate鉤子redux流程 redux的原理
view用actionCreator(酷睿A特)創(chuàng)建一個(gè)action,里面可能包含一些數(shù)據(jù) 使用store的dispatch方法將action傳入store store將action與舊的state轉(zhuǎn)發(fā)給reducer reducer深拷貝state,并返回一個(gè)新的state給store store接收并更新state 使用store.subscribe(薩布斯快不)訂閱更新,重新render組件redux組成state :用來存儲(chǔ)數(shù)據(jù)和數(shù)據(jù)管理的、更新視圖reducer:是一個(gè)純函數(shù),接收舊 state 和 action,根據(jù)不同的 Action 做出不同的操作并返回新的 stateactions:發(fā)送動(dòng)作給reducer,reducer接收動(dòng)作,判斷動(dòng)作類型修改數(shù)據(jù),修改事件后,組件重新做redux事件的訂閱Redux三大原則 單一數(shù)據(jù)源:整個(gè)應(yīng)用的 state 被存儲(chǔ)在一個(gè) Object tree 中,且只存在于唯一的Store中state 是只讀的:唯一改變 state 的方法就是觸發(fā) action,action 是一個(gè)用于描述發(fā)生事件的普通對(duì)象,視圖部分只需要表達(dá)想要修改的意圖,所有修改都會(huì)被集中化處理。狀態(tài)的改變通過純函數(shù)來完成:Redux使用純函數(shù)方式來執(zhí)行狀態(tài)的修改,Action表明了修改狀態(tài)值的意圖,而真正執(zhí)行狀態(tài)修改的則是Reducer。且Reducer必須是一個(gè)純函數(shù),當(dāng)Reducer接收到Action時(shí),Action并不能直接修改State的值,而是通過創(chuàng)建一個(gè)新的狀態(tài)對(duì)象來返回修改的狀態(tài)。redux 中間件
在action 和 store 之間執(zhí)行中間件Redux中間件機(jī)制Redux本身就提供了非常強(qiáng)大的數(shù)據(jù)流管理功能,但這并不是它唯一的強(qiáng)大之處,它還提供了利用中間件來擴(kuò)展自身功能,以滿足用戶的開發(fā)需求(米的為爾) applyMiddlewares():它是 Redux 的原生方法,作用是將所有中間件組成一個(gè)數(shù)組,依次執(zhí)行。 applyMiddleware顧名思義,用于調(diào)用各種中間件; applyMiddleware執(zhí)行后,將所有入?yún)⒅虚g件存入一個(gè)數(shù)組,并且返回一個(gè)閉包(閉包的概念不做累述) 閉包接受一個(gè)createStore作為入?yún)⒉⑶覉?zhí)行后返回下一個(gè)閉包。redux-thunk|異步action
首先檢查參數(shù) action 的類型,如果是函數(shù)的話,就執(zhí)行這個(gè) action 函數(shù), 并把 dispatch, getState, extraArgument(哎克斯拽埃歌門特) 作為參數(shù)傳遞進(jìn)去, 否則就調(diào)用 next 讓下一個(gè)中間件繼續(xù)處理 action 好處可以進(jìn)行前后端數(shù)據(jù)交互 缺點(diǎn)將帶有數(shù)據(jù)請(qǐng)求的action和沒有帶有數(shù)據(jù)請(qǐng)求的action混在一起了缺點(diǎn)解決: 棄用redux-thunk,使用redux-sagaredux-saga可以將異步action和普通action區(qū)別開來redux-saga|集中處理異步action
redux-saga可以將異步action和普通action區(qū)別開來,控制器與更優(yōu)雅的異步處理 redux-saga就是用Generator(杰呢瑞特)來處理異步。redux-saga文檔并沒有說自己是處理異步的工具,而是說用來處理邊際效應(yīng)(side effects),這里的邊際效應(yīng)你可以理解為程序?qū)ν獠康牟僮?#xff0c;比如請(qǐng)求后端,比如操作文件。redux-saga相當(dāng)于在Redux原有數(shù)據(jù)流中多了一層,通過對(duì)Action進(jìn)行監(jiān)聽,從而捕獲到監(jiān)聽的Action,然后可以派生一個(gè)新的任務(wù)對(duì)state進(jìn)行維護(hù)(這個(gè)看項(xiàng)目本身的需求),通過更改的state驅(qū)動(dòng)View的變更。redux-saga同樣是一個(gè)redux中間件,它的定位就是通過集中控制action,起到一個(gè)類似于MVC中控制器的效果。 同時(shí)它的語法使得復(fù)雜異步操作不會(huì)像promise那樣出現(xiàn)很多then的情況,更容易進(jìn)行各類測試。redux與react-redux的關(guān)系
redux是獨(dú)立的應(yīng)用狀態(tài)管理工具。它是可以獨(dú)立于react之外的。如果我們需要在react當(dāng)中運(yùn)用它,那么我們需要手動(dòng)訂閱store的狀態(tài)變化,來對(duì)我們的react組件進(jìn)行更新。react-reudx這個(gè)工具,就幫我們實(shí)現(xiàn)了這個(gè)功能,我們只需對(duì)store進(jìn)行處理,react組件就會(huì)有相應(yīng)的變化。Redux的核心由三部分組成:Store, Action, Reducer。 Store: 是個(gè)對(duì)象,貫穿你整個(gè)應(yīng)用的數(shù)據(jù)都應(yīng)該存儲(chǔ)在這里。 Action: 是個(gè)對(duì)象,必須包含type這個(gè)屬性,reducer將根據(jù)這個(gè)屬性值來對(duì)store進(jìn)行相應(yīng)的處理。除此之外的屬性,就是進(jìn)行這個(gè)操作需要的數(shù)據(jù)。 Reducer: 是個(gè)函數(shù)。接受兩個(gè)參數(shù):要修改的數(shù)據(jù)(state) 和 action對(duì)象。根據(jù)action.type來決定采用的操作,對(duì)state進(jìn)行修改,最后返回新的state。總結(jié) Redux: store, action, reducer store: getState, dispatch, subscribe combineReducers (克木拜恩) createStore store ? dispatch ? action ? reducerreact-redux: connect : 將store作為props注入 provider(破外的): 使store在子孫組件的connect中能夠獲取到react-reudx
1. UI組件|顯示頁面?? (破森特遜弄)React-Redux 將所有組件分成兩大類:UI 組件(presentational component)和容器組件 2. 容器組件|負(fù)責(zé)管理數(shù)據(jù)/復(fù)雜邏輯?UI 組件負(fù)責(zé) UI 的呈現(xiàn),容器組件負(fù)責(zé)管理數(shù)據(jù)和邏輯。 3. Provider組件|容器組件獲取state??所有的 UI 組件都由用戶提供,容器組件則是由 React-Redux 自動(dòng)生成。也就是說,用戶負(fù)責(zé)視覺層,狀態(tài)管理則是全部交給它。 4. connect()|UI組件+容器組件React-Redux 提供connect方法,用于從 UI 組件生成容器組件。connect的意思,就是將這兩種組件連起來。DVA與CRA相比的優(yōu)點(diǎn)
dva:dva 首先是一個(gè)基于 redux 和 redux-saga 的數(shù)據(jù)流方案,然后為了簡化開發(fā)體驗(yàn),dva 還額外內(nèi)置了 react-router 和 fetch,所以也可以理解為一個(gè)輕量級(jí)的應(yīng)用框架。--- 來自官方。相比于cra只是多了內(nèi)置的redux和redux-saga,幫我們處理了數(shù)據(jù)流這方面的需求而已。如果只是想要達(dá)到這個(gè)效果的話,直接在cra中增加dva-core的依賴也是可以做到的。umi:是一個(gè)可插拔的企業(yè)級(jí) react 應(yīng)用框架。umi和cra都是應(yīng)用框架,可能相比cra來說umi的功能點(diǎn)更多一些,只能說是功能性的話umi要相對(duì)來說更勝一籌flux
flux 是 react 中的類似于 vuex 的公共狀態(tài)管理方案,它是 Facebook 官方給出的應(yīng)用架構(gòu),利用數(shù)據(jù)的單向流動(dòng)的形式對(duì)公共狀態(tài)進(jìn)行管理。現(xiàn)已不推薦使用。flux的組成View:視圖層Action:視圖發(fā)出的消息Dispatcher:派發(fā)者,用來接收Action,執(zhí)行回調(diào)函數(shù)Store:數(shù)據(jù)層,存放狀態(tài),一旦發(fā)生改動(dòng)flux 在進(jìn)行數(shù)據(jù)更新時(shí),會(huì)經(jīng)歷以下幾步:用戶與 View 層交互,觸發(fā) ActionAction 使用 dispatcher.dispatch 將Action自己的狀態(tài)發(fā)送給dispatcherdispatcher 通過register注冊(cè)事件,再通過Action傳入的類型來觸發(fā)對(duì)應(yīng)的 Store 回調(diào)進(jìn)行更新Store 里進(jìn)行相應(yīng)的數(shù)據(jù)更新,并觸發(fā) View 層事件使試圖也同步更新View層 收到信號(hào)進(jìn)行更新redux和flux的區(qū)別1)redux是flux中的一個(gè)實(shí)現(xiàn)Flux的核心思想就是數(shù)據(jù)和邏輯永遠(yuǎn)單向流動(dòng)2)在redux中我們只能定義一個(gè)store,在flux中我們可以定義多個(gè)3)在redux中,store和dispatch都放到了store,結(jié)構(gòu)更加清晰4)在redux中本身就內(nèi)置State對(duì)象,對(duì)倉庫的管理更加明確React 中 keys 的作用
key是react用于追蹤哪些列表被修改、被添加或者被移出的輔助標(biāo)識(shí)。在開發(fā)過程中,我們需要保證某些元素在同級(jí)的元素中key是具有唯一性的特性,在react Diff算法中React會(huì)借助元素的key值來判斷該元素是新創(chuàng)建的還是移動(dòng)而來的元素,從而減少元素的不必要的重復(fù)渲染。此外,我們還需要借助key值來判斷元素與本地狀態(tài)的關(guān)聯(lián)關(guān)系,因此我們絕不可忽視轉(zhuǎn)換函數(shù)中 Key 的重要性。react根據(jù)key來決定是銷毀重新創(chuàng)建組件還是更新組件,原則是:key相同,組件有所變化,react會(huì)只更新組件對(duì)應(yīng)變化的屬性。 key不同,組件會(huì)銷毀之前的組件,將整個(gè)組件重新渲染。react新特性和diff算法
render 支持返回這五類: React elements, 數(shù)組, Fragments, Portal, String/numbers, boolean/null, 基礎(chǔ)數(shù)據(jù)類型Fiber React Fiber的方法其實(shí)很簡單——分片。把一個(gè)耗時(shí)長的任務(wù)分成很多小片,每一個(gè)小片的運(yùn)行時(shí)間很短,雖然總時(shí)間依然很長,但是在每個(gè)小片執(zhí)行完之后,都給其他任務(wù)一個(gè)執(zhí)行的機(jī)會(huì),這樣唯一的線程就不會(huì)被獨(dú)占,其他任務(wù)依然有運(yùn)行的機(jī)會(huì)。新的生命周期函數(shù) 由于異步渲染的改動(dòng),componentWillMount, componentWillReceiveProps,componentWillUpdate 三個(gè)函數(shù)將被廢棄。 由于這是一個(gè)很大的改變會(huì)影響很多現(xiàn)有的組件,所以需要慢慢的去改。 目前react 16 只是會(huì)報(bào)warning,在react 17就只能在前面加UNSAFE_的前綴來使用diff算法 作用: 計(jì)算出Virtual DOM中真 正變化的部分,并只針對(duì)該部分進(jìn)行原生DOM操作,而非重新渲染整個(gè)頁面getDerivedStateFromProps static getDerivedStateFromProps(props, state)在調(diào)用render方法之前調(diào)用, 無論是在初始安裝還是后續(xù)更新。它應(yīng)返回一個(gè)對(duì)象來更新狀態(tài),或者返回null以不更新任何內(nèi)容。根據(jù)props更新state 這個(gè)生命周期可用于替代componentWillReceivePropsgetSnapshotBeforeUpdate() getSnapshotBeforeUpdate(prevProps, prevState)在最近呈現(xiàn)的輸出被提交到例如DOM之前調(diào)用。它使組件可以在可能更改之前從DOM捕獲一些信息(例如滾動(dòng)位置)。此生命周期返回的任何值都將作為參數(shù)傳遞給componentDidUpdate()。hookslazy、suspense lazy需要跟Suspence配合使用。 lazy實(shí)際上是幫助我們實(shí)現(xiàn)代碼分割的功能。由于有些內(nèi)容,并不一定要在首屏展示,所以這些資源沒有必要一開始就要去獲取,那么這些資源就可以動(dòng)態(tài)獲取。 這樣的話,相當(dāng)于把不需要首屏展示的代碼分割出來,減少首屏代碼的體積,提升性能。Suspence 很像Error Boundary,不同的是Error Boundary是用來捕獲錯(cuò)誤,顯示相應(yīng)的callback組件。而Suspence是用來捕獲還沒有加載好的組件,并暫停渲染,顯示相應(yīng)的callback。setState概述,同步異步
1. 兩個(gè)參數(shù)及用法第一個(gè)參數(shù)可以是對(duì)象或者函數(shù),是更新state 第二個(gè)參數(shù)獲取最新的state,副作用操作,dom操作事件觸發(fā)聲明,數(shù)據(jù)獲取,第三方庫實(shí)例化2. 同步/異步原理setState在合成事件和鉤子函數(shù)中是異步的 在原生事件和setTimeout中是同步的setState的“異步”并不是說內(nèi)部由異步代碼實(shí)現(xiàn),其實(shí)本身執(zhí)行的過程和代碼都是同步的,只是合成事件和鉤子函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和鉤子函數(shù)中沒法立馬拿到更新后的值,形式了所謂的“異步”,當(dāng)然可以通過第二個(gè)參數(shù) setState(partialState, callback) 中的callback拿到更新后的結(jié)果。setState 的批量更新優(yōu)化也是建立在“異步”(合成事件、鉤子函數(shù))之上的,在原生事件和setTimeout 中不會(huì)批量更新,在“異步”中如果對(duì)同一個(gè)值進(jìn)行多次 setState , setState 的批量更新策略會(huì)對(duì)其進(jìn)行覆蓋,取最后一次的執(zhí)行,如果是同時(shí) setState 多個(gè)不同的值,在更新時(shí)會(huì)對(duì)其進(jìn)行合并批量更新。react合成事件
1. 合成事件原理如果DOM上綁定了過多的事件處理函數(shù),整個(gè)頁面響應(yīng)以及內(nèi)存占用可能都會(huì)受到影響。React為了避免這類DOM事件濫用,同時(shí)屏蔽底層不同瀏覽器之間的事件系統(tǒng)差異,實(shí)現(xiàn)了一個(gè)中間層——SyntheticEvent。當(dāng)用戶在為onClick添加函數(shù)時(shí),React并沒有將Click時(shí)間綁定在DOM上面。 而是在document處監(jiān)聽所有支持的事件,當(dāng)事件發(fā)生并冒泡至document處時(shí),React將事件內(nèi)容封裝交給中間層SyntheticEvent(負(fù)責(zé)所有事件合成) 所以當(dāng)事件觸發(fā)的時(shí)候,對(duì)使用統(tǒng)一的分發(fā)函數(shù)dispatchEvent將指定函數(shù)執(zhí)行。2. 與原生事件的區(qū)別React合成事件一套機(jī)制:React并不是將click事件直接綁定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React將事件封裝給正式的函數(shù)處理運(yùn)行和處理。react路由傳參和讀參
1.params <Route path='/path/:name' component={Path}/> <link to="/path/2">xxx</Link> this.props.history.push({pathname:"/path/" + name}); 讀取參數(shù)用:this.props.match.params.name 優(yōu)勢(shì):刷新地址欄,參數(shù)依然存在 缺點(diǎn):只能傳字符串,并且,如果傳的值太多的話,url會(huì)變得長而丑陋。2.query <Route path='/query' component={Query}/> <Link to={{ path : ' /query' , query : { name : 'sunny' }}}> this.props.history.push({pathname:"/query",query: { name : 'sunny' }}); 讀取參數(shù)用: this.props.location.query.name 優(yōu)勢(shì): 傳參優(yōu)雅,傳遞參數(shù)可傳對(duì)象; 缺點(diǎn): 刷新地址欄,參數(shù)丟失3.state <Route path='/sort ' component={Sort}/> <Link to={{ path : ' /sort ' , state : { name : 'sunny' }}}> this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }}); 讀取參數(shù)用: this.props.location.query.state 優(yōu)缺點(diǎn)同query4.search <Route path='/web/departManange ' component={DepartManange}/> <link to="web/departManange?tenantId=12121212">xxx</Link> this.props.history.push({pathname:"/web/departManange?tenantId" + row.tenantId}); 讀取參數(shù)用: this.props.location.search 優(yōu)缺點(diǎn)同paramsredux和mobx(類似雙向數(shù)據(jù)綁定)區(qū)別
1. 組成部分actions->state->computed values->Reactions 2. 工作流在mobx中, 數(shù)據(jù)是通過加 @observable 作為可監(jiān)測的被觀察者, 在view層中, 你可以通過添加@observer 將view作為觀察者,對(duì)數(shù)據(jù)進(jìn)行監(jiān)測, 如果要觸發(fā)改變數(shù)據(jù),則使用@action, 事實(shí)上,你可以直接在view層改變數(shù)據(jù), 但這種方式不便監(jiān)控?cái)?shù)據(jù),因此不推薦直接改變數(shù)據(jù)。 而@computed可以用來計(jì)算數(shù)據(jù), 也可以是計(jì)算多個(gè)數(shù)據(jù)之后返回新的數(shù)據(jù), 如果其中數(shù)據(jù)改變, @computed也會(huì)觸發(fā)改變 3. 優(yōu)點(diǎn)不同于redux的單一數(shù)據(jù)流, mobx中,你可以同時(shí)在各個(gè)地方使用同一份state, 也可以在一個(gè)頁面中使用多個(gè)store文件react組件通信5種
1.父組件向子組件通信 React數(shù)據(jù)流動(dòng)是單向的,父組件向子組件通信也是最常見的;父組件通過props向子組件傳遞需要的信息2.子組件向父組件通信 利用回調(diào)函數(shù),可以實(shí)現(xiàn)子組件向父組件通信:父組件將一個(gè)函數(shù)作為 props 傳遞給子組件,子組件調(diào)用該回調(diào)函數(shù),便可以向父組件通信。3.非嵌套組件間通信 非嵌套組件,就是沒有任何包含關(guān)系的組件,包括兄弟組件以及不在同一個(gè)父級(jí)中的非兄弟組件。對(duì)于非嵌套組件,可以采用下面兩種方式:利用二者共同父組件的 context 對(duì)象進(jìn)行通信使用自定義事件的方式 如果采用組件間共同的父級(jí)來進(jìn)行中轉(zhuǎn),會(huì)增加子組件和父組件之間的耦合度,如果組件層次較深的話,找到二者公共的父組件不是一件容易的事,當(dāng)然還是那句話,也不是不可以。4.跨組件通信 所謂跨級(jí)組件通信,就是父組件向子組件的子組件通信,向更深層的子組件通信。跨級(jí)組件通信可以采用下面兩種方式:中間組件層層傳遞 props使用 context 對(duì)象 中間組件層層傳遞 props:如果父組件結(jié)構(gòu)較深,那么中間的每一層組件都要去傳遞 props,增加了復(fù)雜度,并且這些 props 并不是這些中間組件自己所需要的。不過這種方式也是可行的,當(dāng)組件層次在三層以內(nèi)可以采用這種方式,當(dāng)組件嵌套過深時(shí),采用這種方式就需要斟酌了。使用 context 對(duì)象:context 相當(dāng)于一個(gè)全局變量,是一個(gè)大容器,我們可以把要通信的內(nèi)容放在這個(gè)容器中,這樣一來,不管嵌套有多深,都可以隨意取用。 使用 context 也很簡單,需要滿足兩個(gè)條件:上級(jí)組件要聲明自己支持 context,并提供一個(gè)函數(shù)來返回相應(yīng)的 context 對(duì)象子組件要聲明自己需要使用 context5.redux 首先由view dispatch攔截action,然后執(zhí)行對(duì)應(yīng)reducer并更新到store中,最終views會(huì)根據(jù)store數(shù)據(jù)的改變執(zhí)行界面的刷新渲染操作。1)首先先把redux相關(guān)工具安裝好 2)通過創(chuàng)建一個(gè)store實(shí)例createStore,接收一個(gè)rootReducer和中間件執(zhí)行函數(shù)3)創(chuàng)建分塊的數(shù)據(jù)rootReducer,通過combineReducers打造rootReducer,里面放分塊的數(shù)據(jù)4)在組件中通過高階組件connect函數(shù),接收store里的數(shù)據(jù),把ActionCreators里的方法綁定到組件身上,并且可以發(fā)送動(dòng)作action給reducer5)在reductor中根據(jù)action中的type動(dòng)作類型,判斷動(dòng)作修改數(shù)據(jù)組件按需加載
(實(shí)現(xiàn)方式,需要的依賴)懶加載1、vue異步組件技術(shù)vue-router配置路由,使用vue的異步組件技術(shù),可以實(shí)現(xiàn)按需加載。但是,這種情況下一個(gè)組件生成一個(gè)js文件。2.import()3.webpack提供的require.ensure()4.第三方庫比如react-loadable 5.lazyload-loader組件銷毀
componentWillUnmount定義state flag:false 作為開關(guān) 定義方法if判斷是否為1,改變state flag:true將方法綁定組件上 可以用三目或者短路原則&&控制組件的顯示隱藏Ant D中input輸入框三個(gè)屬性怎么實(shí)現(xiàn)
onChange輸入框內(nèi)容改變時(shí)候回調(diào) value輸入的內(nèi)容 defaultValue輸入框默認(rèn)值input默認(rèn)值在input中綁定value 定義一個(gè)state 和input雙向數(shù)據(jù)綁定 做成受控組件 定義一個(gè)事件 改變的時(shí)候獲取e.target.valueHooks
為什么使用hook不必寫class組件就可以用state和其他的React特性;自定義hook 實(shí)現(xiàn)組件的復(fù)用 用useEffects代替生命周期方法 代碼更加簡潔出現(xiàn)原因3點(diǎn)為了讓函數(shù)組件擁有類組件的功能。原因比如useState、useReducer 狀態(tài)定義比如useEffect、useLayoutEffect 生命周期功能比如useRef useImperativeHandle 替代了類組件的 Ref為了優(yōu)化函數(shù)組件,比如useMemo、useCallback函數(shù)組件添加新的方法,如useDebugValue顯示自定義hook,自己添加hook類名自定義hooks來復(fù)用狀態(tài)優(yōu)點(diǎn)4點(diǎn) 1.讓函數(shù)組件可以定義狀態(tài) 讓函數(shù)組件可以使用生命周期、監(jiān)聽數(shù)據(jù)讓函數(shù)組件可以有Ref的功能(父組件獲取子組件)優(yōu)化函數(shù)組件 useMemo、useCallback自定義hooks來復(fù)用狀態(tài),代碼量比類組件更少,更清爽。 2.使用規(guī)則2點(diǎn)不要在循環(huán),條件或嵌套函數(shù)中調(diào)用 Hook只在函數(shù)組件中使用 Hooks 3.常用HookuseState:定義狀態(tài) 修改狀態(tài)返回一個(gè)數(shù)組,其中第一項(xiàng)是狀態(tài)值,第二項(xiàng)是一個(gè)更新狀態(tài)的函數(shù)。狀態(tài)一旦改變,React 就會(huì)重新渲染組件,變量獲取新的狀態(tài)值。useEffect:相當(dāng)于componentDidMount,componentDidUpdate,componentWillUnmount三個(gè)鉤子的組合參數(shù)一:執(zhí)行的回調(diào)函數(shù);參數(shù)二:該useEffect在哪些state發(fā)生變化時(shí),才重新執(zhí)行;第二個(gè)參數(shù)是空數(shù)組的時(shí)候執(zhí)行一次,相當(dāng)于componentDidMount,不加的時(shí)候執(zhí)行多次第二個(gè)參數(shù)的作用就是 僅在更改時(shí)更新,實(shí)現(xiàn)性能的優(yōu)化DOM操作 第三方實(shí)例化可以做 清除無用實(shí)例和事件useEffect傳入的回調(diào)函數(shù)本身可以有一個(gè)返回值,這個(gè)返回值是另外一個(gè)回調(diào)函數(shù),來模擬componentWillUnmountuseLayoutEffect:布局副作用useEffect 在瀏覽器渲染完成后執(zhí)行useLayoutEffect 在瀏覽器渲染前執(zhí)行,在render過程中,會(huì)阻塞Dom渲染useLayoutEffect 里的任務(wù)最好影響了 Layout為了用戶體驗(yàn),優(yōu)先使用 useEffect (優(yōu)先渲染)useContext:跨組件通信 createContext創(chuàng)建一個(gè)組件 <numContext.Provider value={num}>useDebugValue:自定義 hook 的標(biāo)簽 方便調(diào)試臺(tái)查看useMemo:記憶組件 動(dòng)態(tài)緩存 新值和舊值一樣,不重新渲染頁面,優(yōu)化作用,類似于shouldComponentUpdate useCallBack:作用和 useMemo 一樣useMemo和useCallback都會(huì)在組件第一次渲染的時(shí)候執(zhí)行,之后會(huì)在其依賴的變量發(fā)生改變時(shí)再次執(zhí)行并且這兩個(gè)hooks都返回緩存的值,useMemo返回緩存的變量,useCallback返回緩存的函數(shù)。useCallback(x => console.log(x), [m]) 等價(jià)于useMemo( () => x => console.log(x), [m])useRef:返回一個(gè)可變的ref對(duì)象useImperativeHandle:將組件中的方法放到外面使用搭配React.forwardRef5.自定義hook類似于高階組件 高階組件返回的一個(gè)類組件,而自定義Hook可以返回任何東西高階組件必須傳遞一個(gè)組件作為參數(shù),而自定義Hook不需要function useFriendStatus(friendID) {const [isOnline, setIsOnline] = useState(null);// 在開發(fā)者工具中的這個(gè) Hook 旁邊顯示標(biāo)簽// e.g. "FriendStatus: Online"useDebugValue(isOnline ? 'Online' : 'Offline');return isOnline;} 可以理解為數(shù)據(jù)的操作都在hook里進(jìn)行,而外部只關(guān)心自己想要的。我只要數(shù)據(jù)列表,獲取產(chǎn)品鉤子(可能并不需要,可通過參數(shù)變更從而觸發(fā)重新獲取數(shù)據(jù))、刪除產(chǎn)品鉤子 為了封裝方法:節(jié)流;react useState() Hook
1.使用 useState() 進(jìn)行狀態(tài)管理調(diào)用useState() Hook 來啟用函數(shù)組件中的狀態(tài)。useState(initialValue)的第一個(gè)參數(shù)initialValue是狀態(tài)的初始值。[state, setState] = useState(initialValue)返回一個(gè)包含2個(gè)元素的數(shù)組:狀態(tài)值和狀態(tài)更新函數(shù)。使用新值調(diào)用狀態(tài)更新器函數(shù)setState(newState)更新狀態(tài)。或者,可以使用一個(gè)回調(diào)setState(prev => next)來調(diào)用狀態(tài)更新器,該回調(diào)將返回基于先前狀態(tài)的新狀態(tài)。調(diào)用狀態(tài)更新器后,React 確保重新渲染組件,以使新狀態(tài)變?yōu)楫?dāng)前狀態(tài)。 2.多種狀態(tài)通過多次調(diào)用useState(),一個(gè)函數(shù)組件可以擁有多個(gè)狀態(tài)。需要注意的,要確保對(duì)useState()的多次調(diào)用在渲染之間始終保持相同的順序。 3.狀態(tài)的延遲初始化每當(dāng) React 重新渲染組件時(shí),都會(huì)執(zhí)行useState(initialState)。如果初始狀態(tài)是原始值(數(shù)字,布爾值等),則不會(huì)有性能問題。當(dāng)初始狀態(tài)需要昂貴的性能方面的操作時(shí),可以通過為useState(computeInitialState)提供一個(gè)函數(shù)來使用狀態(tài)的延遲初始化,該函數(shù)僅在初始渲染時(shí)執(zhí)行一次,以獲得初始狀態(tài)。在以后的組件渲染中,不會(huì)再調(diào)用該函數(shù),從而跳過昂貴的操作。 4.調(diào)用 useState() 在使用useState() Hook 時(shí),必須遵循 Hook 的規(guī)則: 1.僅頂層調(diào)用Hook:不能在循環(huán),條件,嵌套函數(shù)等中調(diào)用useState()。在多個(gè)useState()調(diào)用中,渲染之間的調(diào)用順序必須相同。 2.僅從React 函數(shù)調(diào)用 Hook:必須僅在函數(shù)組件或自定義鉤子內(nèi)部調(diào)用useState()。高階組件HOC
1.名詞解釋/作用使函數(shù)復(fù)用,可以通過給組件傳遞方法來復(fù)用高階組件中的函數(shù)方法。高階組件特點(diǎn)高階組件是一個(gè)函數(shù)高階組件接收一個(gè)組件作為參數(shù)進(jìn)行使用,且需要在render函數(shù)中return返回這個(gè)組件高階組件的目的是為了: 復(fù)用組件,將多個(gè)組件都要使用的類似邏輯放在同一個(gè)地方進(jìn)行處理,類似于在Vue中封裝cookie以供重復(fù)使用2.常用高階組件4個(gè)React.memo()connect()provider() withRouter() // 可以使用 3.有自己封裝過嗎 拖拽封裝,給組件里面的標(biāo)簽添加方法就可以實(shí)現(xiàn)拖拽,并返回標(biāo)簽的x與y坐標(biāo)。深對(duì)比,深復(fù)制封裝、正則封裝、頁面路由跳轉(zhuǎn)、路由數(shù)據(jù)接收解析。拖拽封裝思路
重點(diǎn): 1、一定要絕對(duì)定位,脫離文檔流才可以移動(dòng)。 2、綁定拖拽的元素,移動(dòng)和鼠標(biāo)松開后是對(duì)document的綁定,因?yàn)橐苿?dòng)的是整個(gè)div。 3、點(diǎn)擊:a= 獲取當(dāng)前鼠標(biāo)坐標(biāo)、b =div距瀏覽器距離、c = 鼠標(biāo)在div內(nèi)部距離=a-b。移動(dòng):通過 a - c 建立鼠標(biāo)與div的關(guān)系,防止鼠標(biāo)超出div。拖拽狀態(tài) = 0鼠標(biāo)在元素上按下的時(shí)候{ 拖拽狀態(tài) = 1 記錄下鼠標(biāo)的x和y坐標(biāo) 記錄下元素的x和y坐標(biāo) } 鼠標(biāo)在元素上移動(dòng)的時(shí)候{ 如果拖拽狀態(tài)是0就什么也不做。 如果拖拽狀態(tài)是1,那么 元素y = 現(xiàn)在鼠標(biāo)y - 原來鼠標(biāo)y + 原來元素y 元素x = 現(xiàn)在鼠標(biāo)x - 原來鼠標(biāo)x + 原來元素x } 鼠標(biāo)在任何時(shí)候放開的時(shí)候{ 拖拽狀態(tài) = 0 }數(shù)據(jù)請(qǐng)求封裝思路
自定義hook封裝過組件嗎
1.將Hello組件和App組件中共用的邏輯放在統(tǒng)一的自定義hook中寫 2.自定義hook,hook名以u(píng)se開頭 3.其他組件通過import引入自定義hook,就可以使用了react和vue的區(qū)別
相同點(diǎn): 1.都使用了虛擬dom,如果需要改變?nèi)魏卧氐臓顟B(tài),先改虛擬dom,當(dāng)有變化產(chǎn)生時(shí),會(huì)創(chuàng)建新的虛擬dom,通過diff算法對(duì)比新舊虛擬dom的差異,只需要渲染差異部分就行 2.都使用組件化不同點(diǎn): 1.react中有新語法jsx,vue用普通的html 2.vue中父組件和子組件有通信的時(shí)候,父組件數(shù)據(jù)改變引起子組件改變,子組件會(huì)重新渲染,如果父子組件沒有通信,父組件改變子組件不會(huì)渲染,react中不管是否有數(shù)據(jù)通信,父組件改變子組件都會(huì)渲染 3.react:create-react-appvue :vue-cli 4.react中用redux管理狀態(tài),state通過setState更新vue中數(shù)據(jù)由vuex管理react的class組件,沒有class的時(shí)候怎么寫
React.createClass 我們最早使用這個(gè)方法來構(gòu)建一個(gè)組件“類”,它接受一個(gè)對(duì)象為參數(shù), 對(duì)象中必須聲明一個(gè)render方法,render返回一個(gè)組件實(shí)例生命周期 鉤子函數(shù)用es5怎么定義
protoType.componentDidMount虛擬dom和diff算法
虛擬 dom 相當(dāng)于在 js 和真實(shí) dom 中間加了一個(gè)緩存,利用 dom diff 算法 避免了沒有必要的 dom 操作,從而提高性能 具體實(shí)現(xiàn)步驟如下 用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個(gè)樹構(gòu)建一個(gè)真正的 DOM 樹, 插到文檔當(dāng)中 當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹。然后用新的樹和舊的樹進(jìn)行比較,記錄兩 棵樹差異把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的 DOM 樹上,視圖就更新1.虛擬dom是什么所謂的虛擬 dom,也就是虛擬節(jié)點(diǎn)。它通過JS的Object對(duì)象模擬DOM中的節(jié)點(diǎn),然后再通過特定的render方法將其渲染成真實(shí)的DOM節(jié)點(diǎn)用js模擬一顆dom樹,放在瀏覽器內(nèi)存中。當(dāng)你要變更時(shí),虛擬dom使用diff算法進(jìn)行新舊虛擬dom的比較,將變更放到變更隊(duì)列中,反應(yīng)到實(shí)際的dom樹,減少了dom操作。2.虛擬dom的使用基本流程(前四步驟)1.獲取數(shù)據(jù)2.創(chuàng)建虛擬dom3.通過render函數(shù)解析jsx,將其轉(zhuǎn)換成虛擬dom結(jié)構(gòu)4.將虛擬dom渲染成真實(shí)dom5.數(shù)據(jù)更改了6.使用diff算法比對(duì)兩次虛擬dom,生成patch對(duì)象7.根據(jù)key將patch對(duì)象渲染到頁面中改變的結(jié)構(gòu)上,而其他沒有改變的地方是不做任何修改的(虛擬dom的惰性原則)優(yōu)點(diǎn): 保證性能下限: 框架的虛擬 DOM 需要適配任何上層 API 可能產(chǎn)生的操作,它的一些 DOM 操作的實(shí)現(xiàn)必須是普適的,所以它的性能并不是最優(yōu)的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虛擬 DOM 至少可以保證在你不需要手動(dòng)優(yōu)化的情況下,依然可以提供還不錯(cuò)的性能,即保證性能的下限; 無需手動(dòng)操作 DOM: 我們不再需要手動(dòng)去操作 DOM,只需要寫好 View-Model 的代碼邏輯,框架會(huì)根據(jù)虛擬 DOM 和 數(shù)據(jù)雙向綁定,幫我們以可預(yù)期的方式更新視圖,極大提高我們的開發(fā)效率; 跨平臺(tái): 虛擬 DOM 本質(zhì)上是 JavaScript 對(duì)象,而 DOM 與平臺(tái)強(qiáng)相關(guān),相比之下虛擬 DOM 可以進(jìn)行更方便地跨平臺(tái)操作,例如服務(wù)器渲染、weex 開發(fā)等等。缺點(diǎn): 無法進(jìn)行極致優(yōu)化: 雖然虛擬 DOM + 合理的優(yōu)化,足以應(yīng)對(duì)絕大部分應(yīng)用的性能需求,但在一些性能要求極高的應(yīng)用中虛擬 DOM 無法進(jìn)行針對(duì)性的極致優(yōu)化。首次渲染大量DOM時(shí),由于多了一層虛擬DOM的計(jì)算,會(huì)比innerHTML插入慢。1.diff算法是什么Diff算法是用于比較兩個(gè)新舊虛擬dom樹的差異的,比較完之后會(huì)得到一個(gè)差異對(duì)象,我們稱之為patch補(bǔ)丁對(duì)象比較后會(huì)出現(xiàn)四種情況:1、此節(jié)點(diǎn)是否被移除 -> 添加新的節(jié)點(diǎn)2、屬性是否被改變 -> 舊屬性改為新屬性3、文本內(nèi)容被改變 -> 舊內(nèi)容改為新內(nèi)容4、節(jié)點(diǎn)要被整個(gè)替換 -> 結(jié)構(gòu)完全不相同 移除整個(gè)替換2.diff算法運(yùn)行結(jié)束后,返回是什么返回一個(gè)keyreact Native
React Native(內(nèi)特服)能在手機(jī)上創(chuàng)建原生應(yīng)用,React在這方面處于領(lǐng)先位置。使用JavaScript, CSS和HTML創(chuàng)建原生移動(dòng)應(yīng)用,這是一個(gè)重要的革新。Vue社區(qū)與阿里合作開發(fā)Vue版的React Native——Weex也很不錯(cuò),但仍處于開發(fā)狀態(tài)且并沒經(jīng)過實(shí)際項(xiàng)目的驗(yàn)證。既擁有Native的用戶體驗(yàn)、又保留React的開發(fā)效率React Native與React.js的主要區(qū)別還是JSX,它使用XML標(biāo)記的方式去直接聲明界面,將HTML直接嵌入到JavaScript代碼中react-router(路由)原理
react-router依賴基礎(chǔ) - history history是一個(gè)獨(dú)立的第三方j(luò)s庫,可以用來兼容在不同瀏覽器、不同環(huán)境下對(duì)歷史記錄的管理老瀏覽器的history: 主要通過hash來實(shí)現(xiàn),對(duì)應(yīng)createHashHistory 高版本瀏覽器: 通過html5里面的history,對(duì)應(yīng)createBrowserHistory node環(huán)境下: (不弱惹)主要存儲(chǔ)在歷史記錄memeory里面,對(duì)應(yīng)createMemoryHistory 抽象了一個(gè)公共的文件createHistory:此時(shí)的location跟瀏覽器原生的location是不相同的,最大的區(qū)別就在于里面多了key字段,history內(nèi)部通過key來進(jìn)行l(wèi)ocation的操作原理: 1.執(zhí)行URL前進(jìn)createBrowserHistory: pushState、replaceStatecreateHashHistory: location.hash=*** location.replace()createMemoryHistory: 在內(nèi)存中進(jìn)行歷史記錄的存儲(chǔ) 1.檢測URL回退createBrowserHistory: popstatecreateHashHistory: hashchangecreateMemoryHistory: 因?yàn)槭窃趦?nèi)存中操作,跟瀏覽器沒有關(guān)系,不涉及UI層面的事情,所以可以直接進(jìn)行歷史信息的回退 1.state的存儲(chǔ)為了維護(hù)state的狀態(tài),將其存儲(chǔ)在sessionStorage里面:基本原理:實(shí)現(xiàn)URL與UI可視化界面的同步。其中在react-router中,URL對(duì)應(yīng)Location對(duì)象,而UI是由react components來決定的,這樣就轉(zhuǎn)變成location與components之間的同步問題。在react-router中最主要的component是Router、RouterContext、Link,history庫起到了中間橋梁的作用安裝react-router-dom Link組件用于點(diǎn)擊鏈接跳轉(zhuǎn)其他頁面,沒有路由激活NavLink 用于有路由激活效果的react-router-dom和react-router的區(qū)別
寫法上的區(qū)別: import {Swtich, Route, Router, HashHistory, Link} from 'react-router-dom';import {Switch, Route, Router} from 'react-router'; import {HashHistory, Link} from 'react-router-dom';react-router-dom: 加入了在瀏覽器運(yùn)行環(huán)境下的一些功能:BrowserRouter和HashRouter組件,前者使用pushState和popState事件構(gòu)建路由,后者使用window.location.hash和hashchange事件構(gòu)建路由。react-router-dom是依賴于react-router的,其中Switch、Route、Router、Redirect等組件是直接引入react-router中的react-router-dom還另外新增了Link、BrowserRouter、HashRouter組件。在引入react-router-dom后不需要顯性引入react-router, react-router-dom依賴react-router,npm都會(huì)將他們安裝。react-router3.x與react-router-dom區(qū)別react-router3.x版本下路由采用集中式配置,UI組件和路由是分開的。react-router4.x版本下路由路由采用分散式配置,路由嵌套在UI組件當(dāng)中,更加契合組件化思想(組件中的路由也應(yīng)該包含在組件之中)。react路由模式
我們一直在使用的路由方式是BrowserRouter,也就是瀏覽器的路由方式,其實(shí)React還有幾種路由方式:(不弱惹) 1、BrowserRouter:瀏覽器的路由方式,也就是在開發(fā)中最常使用的路由方式 2、HashRouter:在路徑前加入#號(hào)成為一個(gè)哈希值,Hash模式的好處是,再也不會(huì)因?yàn)槲覀兯⑿露也坏轿覀兊膶?duì)應(yīng)路徑 3、MemoryRouter:不存儲(chǔ)history,所有路由過程保存在內(nèi)存里,不能進(jìn)行前進(jìn)后退,因?yàn)榈刂窓跊]有發(fā)生任何變化 4、NativeRouter:經(jīng)常配合ReactNative使用,多用于移動(dòng)端 5、StaticRouter:設(shè)置靜態(tài)路由,需要和后臺(tái)服務(wù)器配合設(shè)置,比如設(shè)置服務(wù)端渲染時(shí)使用(斯大推克)react路由配置
1、引入路由包npm install --save react-routernpm install --save react-router-domreact-router:是基本的router包,里邊函的內(nèi)容較多,但是在網(wǎng)頁開發(fā)中有很多用不到,現(xiàn)在的市面上的課程講的基本都是這個(gè)包的教程。react-router-dom:隨著react生態(tài)環(huán)境的壯大,后出現(xiàn)的包,這個(gè)包比react-router包輕巧了很多。 2、設(shè)置路由配置文件在src目錄下新建一個(gè)Router/index.js文件用于管理路由,這里需要引入一些對(duì)應(yīng)的組件和路由包文件。Router的history是必需的propsSwitch表示只渲染第一個(gè)與當(dāng)前地址匹配的<Route>Route的props path為路徑,component為路徑對(duì)應(yīng)的頁面exact屬性表示精確匹配,比如我們有多層路由進(jìn)行嵌套時(shí),exact可以幫助我們精確匹配到你想跳轉(zhuǎn)的路由。 exact的值為bool型,為true是表示嚴(yán)格匹配,為false時(shí)為正常匹配3、在入口文件引入路由配置文件import RouterConfig from './router/index.js';ReactDOM.render(<RouterConfig/>, document.getElementById('root'));4、在各組件中使用路由<ul className="menu"><li><NavLink to='/Page1'>第一個(gè)頁面</NavLink></li><li><NavLink to='/Page2'>第二個(gè)頁面</NavLink></li></ul>1.Switch:表示一次只渲染一個(gè)組件 2.Route:路由組件,用于展示一個(gè)組件 同router-view 3.Redirect:重定向(銳得埃克特) 4.lazy + Suspense(色斯盤絲):實(shí)現(xiàn)路由懶加載 5.exact:路徑完全匹配 6.fallback:組件切換時(shí)候的轉(zhuǎn)場組件react路由(router)實(shí)現(xiàn)異步加載
react-router,官網(wǎng)文檔給出的是用webpack的bundle-loaderrequire.ensure。這是webpack的舊式寫法,現(xiàn)在已不推薦import()符合ECMAScript提議的import()語法,該提案與普通 import 語句或 require 函數(shù)的類似,但返回一個(gè) Promise 對(duì)象。這意味著模塊時(shí)異步加載的react原理
1. setState setState在合成事件和鉤子函數(shù)中是異步的 在原生事件和setTimeout中是同步的setState的“異步”并不是說內(nèi)部由異步代碼實(shí)現(xiàn),其實(shí)本身執(zhí)行的過程和代碼都是同步的,只是合成事件和鉤子函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和鉤子函數(shù)中沒法立馬拿到更新后的值,形式了所謂的“異步”,第一個(gè)參數(shù)可以是對(duì)象或者函數(shù) 是更新state 第二個(gè)參數(shù)獲取最新的state,副作用操作 dom操作事件觸發(fā)聲明 數(shù)據(jù)獲取2. JSX語法的轉(zhuǎn)化JSX 僅僅是 createElement() 方法的語法糖(簡化語法)JSX 語法被 @babel/preset-react 插件編譯為 createElement() 方法react.createElement()React 元素:是一個(gè)對(duì)象,用來描述你希望在屏幕上看到的內(nèi)容3. 組件更新機(jī)制setState() 的兩個(gè)作用: 1. 修改 state 2. 更新組件(UI)過程:父組件重新渲染時(shí),也會(huì)重新渲染子組件。但只會(huì)渲染當(dāng)前組件子樹(當(dāng)前組件及其所有子組件) 4. 組件性能優(yōu)化減輕 state:只存儲(chǔ)跟組件渲染相關(guān)的數(shù)據(jù)避免不必要的重新渲染 : shouldComponentUpdate(nextProps, nextState) 通過返回值決定該組件是否重新渲染,返回 true 表示重新渲染,false 表示不重新渲染 起到優(yōu)化作用5. 純組件 PureComponentPureComponent 內(nèi)部自動(dòng)實(shí)現(xiàn)了 shouldComponentUpdate 鉤子,不需要手動(dòng)比較 純組件內(nèi)部通過分別 對(duì)比 前后兩次 props 和 state 的值,來決定是否重新渲染組件 純組件內(nèi)部的對(duì)比是 shallow compare(淺層對(duì)比)6. 虛擬 DOM 和 Diff 算法數(shù)據(jù)改變視圖更新初次渲染時(shí),React 會(huì)根據(jù)初始state(Model),創(chuàng)建一個(gè)虛擬 DOM 對(duì)象(樹)。根據(jù)虛擬 DOM 生成真正的 DOM,渲染到頁面中。當(dāng)數(shù)據(jù)變化后(setState(),重新根據(jù)新的數(shù)據(jù),創(chuàng)建新的虛擬DOM對(duì)象(樹)。與上一次得到的虛擬 DOM 對(duì)象,使用 Diff 算法 對(duì)比(找不同),生成patch補(bǔ)丁對(duì)象,得到需要更新的內(nèi)容。最終,React 只將變化的內(nèi)容更新(patch)到 DOM 中,重新渲染到頁面。react的connect高階組件實(shí)現(xiàn), 如何在全局中取得store
連接React組件與 Redux store。 connect:connect函數(shù)的返回值是一個(gè)高階組件,通過高階組件來獲取store中的數(shù)據(jù) connect底層原理:是閉包mapStateFromProps:從countReducer中解構(gòu)出num數(shù)據(jù),用來獲取數(shù)據(jù) mapDispatchFromProps:將ActionCreators中的方法綁定到組件上,并且發(fā)送actionconnect調(diào)用的結(jié)果是返回一個(gè)高階組件 connect方法利用了合并分發(fā)的原理來幫助我們完成store內(nèi)容的獲取合并: 將store中的所有數(shù)據(jù)拿到手 分發(fā): 將我們UI需要的數(shù)據(jù)派發(fā)出去原理 合并分發(fā) :合并的意思是:(我們項(xiàng)目中)redux的數(shù)據(jù)是集中在一處的 分發(fā)的意思是:給的是所有數(shù)據(jù)中的分塊的數(shù)據(jù)react的connect實(shí)現(xiàn)原理
首先connect之所以會(huì)成功,是因?yàn)镻rovider組件: 在原應(yīng)用組件上包裹一層,使原來整個(gè)應(yīng)用成為Provider的子組件 接收Redux的store作為props,通過context對(duì)象傳遞給子孫組件上的connect那connect做了些什么呢? 它真正連接 Redux 和 React,它包在我們的容器組件的外一層, 它接收上面 Provider 提供的 store 里面的 state 和 dispatch, 傳給一個(gè)構(gòu)造函數(shù),返回一個(gè)對(duì)象,以屬性形式傳給我們的容器組件。關(guān)于它的源碼 connect是一個(gè)高階函數(shù),首先傳入mapStateFromProps、mapDispatchFromProps, 然后返回一個(gè)生產(chǎn)Component的函數(shù)(wrapWithConnect), 然后再將真正的Component作為參數(shù)傳入wrapWithConnect, 這樣就生產(chǎn)出一個(gè)經(jīng)過包裹的Connect組件,該組件具有如下特點(diǎn):通過props.store獲取祖先Component的store props包括stateProps、dispatchProps、parentProps,合并在一起得到nextState,作為props傳給真正的Component componentDidMount時(shí),添加事件this.store.subscribe(this.handleChange),實(shí)現(xiàn)頁面交互 shouldComponentUpdate時(shí)判斷是否有避免進(jìn)行渲染,提升頁面性能,并得到nextState componentWillUnmount時(shí)移除注冊(cè)的事件this.handleChangereact-router3和react-router4 的區(qū)別
一、V3或者說V早期版本是把router 和 layout components 分開在V4中是:集中式 router通過 <Route> 嵌套,實(shí)現(xiàn) Layout 和 page 嵌套Layout 和 page 組件 是作為 router 的一部分 二、在V3中,我們是將整個(gè)龐大的router直接丟給Dom在V4中,除了BrowserRouter,我們丟給DOM的我們的程序本身另外,V4 中,我們不再使用 {props.children} 來嵌套組件了,替代的 <Route>,當(dāng) route 匹配時(shí),子組件會(huì)被渲染到 <Route> 書寫的地方三、在V3 中的 routing 規(guī)則是 exclusive,意思就是最終只獲取一個(gè) route而 V4 中的 routes 默認(rèn)是 inclusive 的,這就意味著多個(gè) <Route>可以同時(shí)匹配和呈現(xiàn)如果只想匹配一個(gè)路由,可以使用Switch,在 <Switch> 中只有一個(gè) <Route> 會(huì)被渲染,同時(shí)可以再在每個(gè)路由添加exact,做到精準(zhǔn)匹配Redirect,瀏覽器重定向,當(dāng)多有都不匹配的時(shí)候,進(jìn)行匹配react中獲取真實(shí)的dom節(jié)點(diǎn)
使用ref屬性獲取Dom元素后,再使用原生javascript獲取內(nèi)容react是什么層面上的框架
React框架本身和我們常用的JavaScript MVC框架,如:AngularJS,Backbone,Ember等,沒有直接的可比性。 React的官方博客中明確闡述了React不是一個(gè)MVC框架, 而是一個(gè)用于構(gòu)建組件化UI的庫,是一個(gè)前端界面開發(fā)工具。所以頂多算是MVC中的V(view)。react數(shù)據(jù)流
React遵循從上到下的數(shù)據(jù)流向,即單向數(shù)據(jù)流。單向數(shù)據(jù)流并非‘單向綁定’,甚至單向數(shù)據(jù)流與綁定沒有‘任何關(guān)系’。 對(duì)于React來說,單向數(shù)據(jù)流(從上到下)與單一數(shù)據(jù)源這兩個(gè)原則,限定了React中要想在一個(gè)組件中更新另一個(gè)組件的狀態(tài)(類似于Vue的平行組件傳參,或者是子組件向父組件傳遞參數(shù)) ,需要進(jìn)行狀態(tài)提升。即將狀態(tài)提升到他們最近的祖先組件中。子組件中Change了狀態(tài),觸發(fā)父組件狀態(tài)的變更,父組件狀態(tài)的變更, 影響到了另一個(gè)組件的顯示(因?yàn)閭鬟f給另一個(gè)組件的狀態(tài)變化了,這一點(diǎn)與Vue子組件的$emit()方法很相似)。react數(shù)據(jù)一定要在DidMount里獲取更新的原因
componentDidMount方法中的代碼,是在組件已經(jīng)完全掛載到網(wǎng)頁上才會(huì)調(diào)用被執(zhí)行,所以可以保證數(shù)據(jù)的加載。 在這方法中調(diào)用setState方法,會(huì)觸發(fā)重渲染。這個(gè)方法就是用來加載外部數(shù)據(jù)用的,或處理其他的副作用代碼。constructor()constructor()中獲取數(shù)據(jù)的話,如果時(shí)間太長,或者出錯(cuò),組件就渲染不出來,整個(gè)頁面都沒法渲染了。constructor是作組件state初紿化工作,并不是設(shè)計(jì)來作加載數(shù)據(jù)的。componentWillMount()如果使用SSR(服務(wù)端渲染),componentWillMount會(huì)執(zhí)行2次,一次在服務(wù)端,一次在客戶端。而componentDidMount不會(huì)。constructor可以完成state初始化,componentWillMount使用的很少,目前16版本加入了UNSAFE來標(biāo)識(shí) componentWillMount,新的生命周期static getDerivedStateFromProps() 也會(huì)替代這個(gè)。React16之后采用了Fiber架構(gòu),只有componentDidMount聲明周期函數(shù)是確定被執(zhí)行一次的,類似ComponentWillMount的生命周期鉤子都有可能執(zhí)行多次,所以不加以在這些生命周期中做有副作用的操作,比如請(qǐng)求數(shù)據(jù)之類。render()無限r(nóng)endercomponentDidMount()確保已經(jīng)render過一次。提醒我們正確地設(shè)置初始狀態(tài),這樣就不會(huì)得到導(dǎo)致錯(cuò)誤的"undefined"狀態(tài)。react中的受控組件和非受控組件
受控組件HTML中的表單元素是可輸入的,也就是有自己的可變狀態(tài)而React中可變狀態(tài)通常保存在state中,并且只能通過setState()方法來修改React講state與表單元素值value綁定在一起,有state的值來控制表單元素的值簡單來說,值受到react控制的表單元素非受控組件調(diào)用 React.createRef() 方法創(chuàng)建ref對(duì)象將創(chuàng)建好的 ref 對(duì)象添加到文本框中通過ref對(duì)象獲取到文本框的值簡單來說,表單組件沒有value prop就可以稱為非受控組件react中的ref的3種方式
方式1: string類型綁定 類似于vue中的ref綁定方式,可以通過this.refs.綁定的ref的名字獲取到節(jié)點(diǎn)dom 注意的是 這種方式已經(jīng)不被最新版的react推薦使用,有可能會(huì)在未來版本中遺棄方式2: react.CreateRef() 通過在class中使用React.createRef()方法創(chuàng)建一些變量,可以將這些變量綁定到標(biāo)簽的ref中 那么該變量的current則指向綁定的標(biāo)簽dom方式3: 函數(shù)形式 在class中聲明函數(shù),在函數(shù)中綁定ref 使用這種方法可以將子組件暴露給父組件以使得父組件能夠調(diào)用子組件的方法 通過函數(shù)的方法綁定ref可以將整個(gè)子組件暴露給父組件當(dāng)在子組件中調(diào)用onRef函數(shù)時(shí),正在調(diào)用從父組件傳遞的函數(shù)。this.props.onRef(this)這里的參數(shù)指向子組件本身,父組件接收該引用作為第一個(gè)參數(shù):onRef = {ref =>(this.child = ref)}然后它使用this.child保存引用。之后,可以在父組件內(nèi)訪問整個(gè)子組件實(shí)例,并且可以調(diào)用子組件函數(shù)。react中的static(靜態(tài)方法)
靜態(tài)方法和 React 沒有直接關(guān)系,React 的組件都是繼承自 React.Component 這個(gè)類,靜態(tài)方法屬于類本身。static并不是react定義的,而加上static關(guān)鍵字,就表示該方法不會(huì)被實(shí)例繼承,而是直接通過類來調(diào)用。這里涉及到了ES6的class,我們定義一個(gè)組件的時(shí)候通常是定義了一個(gè)類, 而static則是創(chuàng)建了一個(gè)屬于這個(gè)類的屬性或者方法。 組件則是這個(gè)類的一個(gè)實(shí)例,component的props和state是屬于這個(gè)實(shí)例的,react的props與state的區(qū)別
props: 一般用于父組件向子組件通信,在組件之間通信使用。 state: 一般用于組件內(nèi)部的狀態(tài)維護(hù),更新組建內(nèi)部的數(shù)據(jù),狀態(tài),更新子組件的props等。混合開發(fā)
1. 混合開發(fā)是介于webapp和原生app之間的一種應(yīng)用,它同時(shí)具有webapp可以跨平臺(tái)的特性,也具備原生app可以進(jìn)行安裝使用的特性 2. webApp 1. 優(yōu)點(diǎn): 跨平臺(tái) 、 維護(hù)更新、項(xiàng)目迭代快2. 缺點(diǎn): 交互體驗(yàn)不好 、進(jìn)入應(yīng)用的方式麻煩 3. 原生app1.案例: 美團(tuán)、餓了嗎、微信、QQ 2.安裝在手機(jī)中使用的 3.優(yōu)點(diǎn): 手機(jī)安裝、交互體驗(yàn)好 4.缺點(diǎn): 維護(hù)更新、項(xiàng)目迭代很慢、成本太高了 4. 混合開發(fā): 擇中方案跨平臺(tái)維護(hù)更新快 成本低手機(jī)安裝,交互體驗(yàn)好為什么混合開發(fā)會(huì)興起呢? 1. 混合開發(fā)的興起是偶然的混合開發(fā)方式 1. h5 主導(dǎo)- 開發(fā)思維: H5【 vue/ react/ angular 】 + 第三方可以訪問原生設(shè)備的庫- 微信公眾號(hào): h5網(wǎng)頁 + 微信JSSDK - 歷史1. PhoneGap + cordva.js 淘汰2. vue/react/angular + ioinc.js 3. vue - uni-app 4. h5 + h5plus.js h5 + h5+5. 微信公眾號(hào): webapp + js-jdk 6. vue/react + weex.js[ 阿里內(nèi)部 ] 2. React Native1. facebook 團(tuán)隊(duì)項(xiàng)目 16 - 18年很熱火,18年后半年開始熱度下降,facebook覺得這個(gè)框架對(duì)于開發(fā)者而言開發(fā)難度太大,維護(hù)成本也高,Facebook決定不再更新它了、2. 典型應(yīng)用: 餓了嗎3. React Native開發(fā)出來項(xiàng)目 - 原生app 4. React Native = React + 原生js5. 構(gòu)建React Native項(xiàng)目 - 腳手架 1. 構(gòu)建項(xiàng)目環(huán)境: create-react-native-app 2. 手機(jī)調(diào)試:expo expo-cli3. 目錄解釋1. __test__ expo手機(jī)調(diào)試的測試文件夾,不用管2. .expo 臨時(shí)文件,運(yùn)行項(xiàng)目3. .expo-shared 分享4. assets 靜態(tài)資源5. components 公共組件6. constants 項(xiàng)目公用的常量7. navigation 底部tabbar欄組件8. node_modules 依賴包9. screens 頁面小程序
對(duì)于路由的觸發(fā)方式以及頁面生命周期函數(shù)如下:
| 初始化 | 小程序打開的第一個(gè)頁面 | onLoad, onSHow | |
| 打開新頁面 | 調(diào)用 API wx.navigateTo 或使用組件 | onHide | onLoad, onShow |
| 頁面重定向 | 調(diào)用 API wx.redirectTo 或使用組件 | onUnload | onLoad, onShow |
| 頁面返回 | 調(diào)用 API wx.navigateBack 或使用組件或用戶按左上角返回按鈕 | onUnload | onShow |
| Tab 切換 | 調(diào)用 API wx.navigateBack 或使用組件或用戶按調(diào)用 API wx.switchTab 或使用組件 或用戶切換 Tab | 各種情況請(qǐng)參考下表 | |
| 重啟動(dòng) | 調(diào)用 API wx.reLaunch 或使用組件 | onUnload | onLoad, onShow |
頁面跳轉(zhuǎn)觸發(fā)的生命周期,其實(shí)還是存在問題的,并非官方所說的那樣。
SwitchTab的跳轉(zhuǎn)BUG 首頁跳轉(zhuǎn)到子頁面后,在子頁面上使用: <navigator type='switchTab' url="/pages/index/index" ><view>跳轉(zhuǎn)首頁</button> </navigator> 這種方式有問題,解決的辦法是通過JS來實(shí)現(xiàn)跳轉(zhuǎn),代碼如下: <view class="weui-btn-area"><button class="weui-btn" bindtap="backIndex" type="default">返回主頁</button> </view> 跳轉(zhuǎn)成功后,重新調(diào)用onload方法,JS代碼如下: backIndex:function(){wx.switchTab({url: '/pages/index/index',success: function (e) {var page = getCurrentPages().pop();if (page == undefined || page == null) return;page.onLoad();}})}get與post的區(qū)別
1.提交方式 get: get會(huì)將接收到的數(shù)據(jù)拼接到url地址中,以"?"問號(hào)劃分,問號(hào)后面是接收到的數(shù)據(jù),多個(gè)數(shù)據(jù)之間用&連接。用戶可以很直觀的看見。 post: post會(huì)將接收到的數(shù)據(jù)放置在html header中一起發(fā)送到指定的url地址內(nèi)。用戶看不到這個(gè)過程。2.傳遞數(shù)據(jù)大小 get: get傳遞數(shù)據(jù)的大小因?yàn)槭艿綖g覽器地址欄的限制,所以一般在2k-8k,這要據(jù)瀏覽器而定,比如谷歌瀏覽器就是8k。 post: post傳遞數(shù)據(jù)的大小最小是2M,但理論上是無上限的。3.應(yīng)用范圍 get: get一般用于獲取/查詢資源信息.多用于a標(biāo)簽的href屬性中,也常用于location.href屬性中。 post: post一般是用于更新數(shù)據(jù)信息.多用于表單提交。4.安全性 get的安全性比post較差。react父組件通過ref獲取不到子組件的解決方案
在子組件中 this.customfunction = this.customfunction.bind(this); 即可React PureComponent 和 Component 區(qū)別
React.PureComponent 與 React.Component 幾乎完全相同,但 React.PureComponent 通過prop和state的淺對(duì)比來實(shí)現(xiàn) shouldComponentUpate()。如果React組件的 render() 函數(shù)在給定相同的props和state下渲染為相同的結(jié)果,在某些場景下你可以使用 React.PureComponent 來提升性能。React.PureComponent 的 shouldComponentUpdate() 只會(huì)對(duì)對(duì)象進(jìn)行淺對(duì)比。如果對(duì)象包含復(fù)雜的數(shù)據(jù)結(jié)構(gòu),它可能會(huì)因深層的數(shù)據(jù)不一致而產(chǎn)生錯(cuò)誤的否定判斷(表現(xiàn)為對(duì)象深層的數(shù)據(jù)已改變視圖卻沒有更新, 原文:false-negatives)。當(dāng)你期望只擁有簡單的props和state時(shí),才去繼承 PureComponent ,或者在你知道深層的數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生改變時(shí)使用 forceUpate() 。或者,考慮使用 不可變對(duì)象 來促進(jìn)嵌套數(shù)據(jù)的快速比較。此外,React.PureComponent 的 shouldComponentUpate() 會(huì)忽略整個(gè)組件的子級(jí)。請(qǐng)確保所有的子級(jí)組件也是”Pure”的。PureComponent的作用:PureComponent 其實(shí)是在內(nèi)部幫我們簡單實(shí)現(xiàn)了一下shouldComponentUpdate的功能,以便提供組件的性能;這里的簡單指是:對(duì)prop和state做淺比較,若淺比較結(jié)果相同,則該組件以及其子組件不做render;否則,render。使用PureComponent注意事項(xiàng):PureComponent主要針對(duì)prop和state為基本數(shù)據(jù)類型,如bool、string、number;對(duì)于數(shù)組和對(duì)象等引用類型,則要引用不同,才會(huì)渲染;如果引用相同,則PureComponent淺比較返回結(jié)果相同,不做render;PureComponent 中不建議再另外重寫shouldComponentUpdate方法,否則會(huì)報(bào)warning信息:PureComponent的最好作為展示組件,如果prop和state每次都會(huì)變,PureComponent做淺比較也會(huì)影響性能,可以考慮直接用Component;對(duì)于prop和state數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜的情況,可以考慮自己重寫shouldComponentUpdate方法來做優(yōu)化;react中調(diào)用setState之后發(fā)生
React會(huì)將當(dāng)前傳入的參數(shù)對(duì)象與組件當(dāng)前的狀態(tài)合并,然后觸發(fā)調(diào)和過程,在調(diào)和的過程中,React會(huì)以相對(duì)高效的方式根據(jù)新的狀態(tài)構(gòu)建React元素樹并且重新渲染整個(gè)UI界面.React得到的元素樹之后,React會(huì)自動(dòng)計(jì)算出新的樹與老的樹的節(jié)點(diǎn)的差異,然后根據(jù)差異對(duì)界面進(jìn)行最小化的渲染,在React的差異算法中,React能夠精確的知道在哪些位置發(fā)生看改變以及應(yīng)該如何去改變,這樣就保證了UI是按需更新的而不是重新渲染整個(gè)界面SPA和MPA的異同
單頁應(yīng)用(SinglePage Application,SPA)指只有一個(gè)主頁面的應(yīng)用,一開始只需加載一次 js,css 等相關(guān)資源。所有的內(nèi)容都包含在主頁面,對(duì)每一個(gè)功能模塊組件化。單頁應(yīng)用跳轉(zhuǎn),就是切換相關(guān)組件,僅刷新局部資源。多頁應(yīng)用(MultiPage Application,MPA)指有多個(gè)獨(dú)立的頁面的應(yīng)用,每個(gè)頁面必須重復(fù)加載 js,css 等相關(guān)資源。多頁應(yīng)用跳轉(zhuǎn),需要整頁資源刷新。兩者對(duì)比表格:SPA ||| MPA 結(jié)構(gòu):一個(gè)主頁面 + 許多模塊的組件 ||| 許多完整的頁面 體驗(yàn):頁面切換快,體驗(yàn)佳;當(dāng)初次加載文件過多時(shí),需要做相關(guān)的調(diào)優(yōu)。 ||| 頁面切換慢,網(wǎng)速慢的時(shí)候,體驗(yàn)尤其不好 資源文件:組件公用的資源只需要加載一次 ||| 每個(gè)頁面都要自己加載公用的資源 適用場景:對(duì)體驗(yàn)度和流暢度有較高要求的應(yīng)用,不利于 SEO(可借助 SSR 優(yōu)化 SEO) ||| 適用于對(duì) SEO 要求較高的應(yīng)用 過渡動(dòng)畫:Vue 提供了 transition 的封裝組件,容易實(shí)現(xiàn) ||| 很難實(shí)現(xiàn) 內(nèi)容更新:相關(guān)組件的切換,即局部更新 ||| 整體 HTML 的切換,費(fèi)錢(重復(fù) HTTP 請(qǐng)求) 路由模式:可以使用 hash ,也可以使用 history ||| 普通鏈接跳轉(zhuǎn) 數(shù)據(jù)傳遞:因?yàn)閱雾撁?#xff0c;使用全局變量就好(Vuex) ||| cookie 、localStorage 等緩存方案,URL 參數(shù),調(diào)用接口保存等 相關(guān)成本:前期開發(fā)成本較高,后期維護(hù)較為容易 ||| 前期開發(fā)成本低,后期維護(hù)就比較麻煩,因?yàn)榭赡芤粋€(gè)功能需要改很多地方單頁應(yīng)用實(shí)現(xiàn)核心:前端路由 前端路由的核心:改變視圖的同時(shí)不會(huì)向后端發(fā)出請(qǐng)求。TS
TS好處: 1、強(qiáng)類型 2、不需要去瀏覽器中瀏覽效果,就能知道編譯錯(cuò)誤靜態(tài)類型檢查可以做到early fail,即你編寫的代碼即使沒有被執(zhí)行到,一旦你編寫代碼時(shí)發(fā)生類型不匹配,語言在編譯階段(解釋執(zhí)行也一樣,可以在運(yùn)行前)即可發(fā)現(xiàn) 4、類型就是最好的注釋,看類型我們就知道這個(gè)是什么 3、即使ts中有編譯報(bào)錯(cuò),tsc依舊可以將其編譯成js學(xué)習(xí)TS的基本數(shù)據(jù)類型 定類型是為了安全,規(guī)矩多就安全 1、基礎(chǔ)數(shù)據(jù)類型 :number \string\boolean\null\undefinedany 表示任意類型 void 表示空類型,空類型是針對(duì)函數(shù)的,表示函數(shù)沒有返回值。返回空 2、內(nèi)置對(duì)象類型 : Array \ Boolean \ HTMLElement 3、自定義類型 : 接口 類 泛型 枚舉類型TS 中 interface 和 type 的區(qū)別
在ts中,定義類型由兩種方式:接口(interface)和類型別名(type alias) interface只能定義對(duì)象類型, type聲明的方式可以定義組合類型,交叉類型和原始類型如果用type alias 聲明的方式,會(huì)導(dǎo)致一些功能的缺失1.interface方式可以實(shí)現(xiàn)接口的extends/implements,而type 不行2.interface可以實(shí)現(xiàn)接口的merge,但是type不行Webpack
webpack打包react vue,與自己的源代碼分離使用splitchunks webpack熱更新:不用刷新瀏覽器而將新變更的模塊替換掉舊的模塊。webpack會(huì)分析每個(gè)入口文件,解析包依賴關(guān)系的各個(gè)文件,每個(gè)模塊都打包到bundle.js。webpack給每個(gè)模塊分配一個(gè)唯一的ID并通過這個(gè)ID索引和訪問模塊。頁面運(yùn)行時(shí),先啟動(dòng)entry.js,其他模塊會(huì)在運(yùn)行require時(shí)候執(zhí)行。1.Webpack Loader Plugin(loader ,plugin分別什么作用,哪個(gè)配置可以把依賴包抽離出來,不打包進(jìn)去) 【Loader】:用于對(duì)模塊源碼的轉(zhuǎn)換,loader描述了webpack如何處理非javascript模塊,并且在buld中引入這些依賴。loader可以將文件從不同的語言(如TypeScript)轉(zhuǎn)換為JavaScript,或者將內(nèi)聯(lián)圖像轉(zhuǎn)換為data URL。比如說:CSS-Loader,Style-Loader等。babel-loader優(yōu)雅降級(jí)配置ES高版本轉(zhuǎn)成低版本【Plugin】:是用于在webpack打包編譯過程里,在對(duì)應(yīng)的事件節(jié)點(diǎn)里執(zhí)行自定義操作,比如資源管理、bundle文件優(yōu)化等操作,依賴包抽離 const ExtractTextWebapckPlugin= require("extract-text-webpack-plugin") module exclude node_modules排除excloude排除node_modulesloader的使用很簡單:在webpack.config.js中指定loader。module.rules可以指定多個(gè)loader,對(duì)項(xiàng)目中的各個(gè)loader有個(gè)全局概覽。loader是運(yùn)行在NodeJS中,可以用options對(duì)象進(jìn)行配置。plugin可以為loader帶來更多特性。loader可以進(jìn)行壓縮,打包,語言翻譯等等。loader從模板路徑解析,npm install node_modules。也可以自定義loader,命名XXX-loader。語言類的處理器loader:CoffeeScript,TypeScript,ESNext(Bable),Sass,Less,Stylus。任何開發(fā)技術(shù)棧都可以使用webpack。webpack常用的loader樣式:style-loader、css-loader、less-loader、sass-loader等 文件:raw-loader、file-loader 、url-loader等 編譯:babel-loader、coffee-loader 、ts-loader等 校驗(yàn)測試:mocha-loader、jshint-loader 、eslint-loader等目的在于解決loader無法實(shí)現(xiàn)的其他事,從打包優(yōu)化和壓縮,到重新定義環(huán)境變量,功能強(qiáng)大到可以用來處理各種各樣的任務(wù)。webpack提供了很多開箱即用的插件:CommonChunkPlugin主要用于提取第三方庫和公共模塊,避免首屏加載的bundle文件,或者按需加載的bundle文件體積過大,導(dǎo)致加載時(shí)間過長,是一把優(yōu)化的利器。而在多頁面應(yīng)用中,更是能夠?yàn)槊總€(gè)頁面間的應(yīng)用程序共享代碼創(chuàng)建bundle。webpack功能強(qiáng)大,難點(diǎn)在于它的配置文件,webpack4默認(rèn)不需要配置文件,可以通過mode選項(xiàng)為webpack指定了一些默認(rèn)的配置,mode分為:development/production,默認(rèn)是production。插件可以攜帶參數(shù),所以在plugins屬性傳入new實(shí)例。webpack常用的plugin webpack內(nèi)置UglifyJsPlugin,壓縮和混淆代碼。 webpack內(nèi)置CommonsChunkPlugin,提高打包效率,將第三方庫和業(yè)務(wù)代碼分開打包。 ProvidePlugin:自動(dòng)加載模塊,代替require和importhtml-webpack-plugin可以根據(jù)模板自動(dòng)生成html代碼,并自動(dòng)引用css和js文件extract-text-webpack-plugin 將js文件中引用的樣式單獨(dú)抽離成css文件DefinePlugin 編譯時(shí)配置全局變量,這對(duì)開發(fā)模式和發(fā)布模式的構(gòu)建允許不同的行為非常有用。【Mode】可以在config文件里面配置,也可以在CLI參數(shù)中配置:webpack--mode=production(一般會(huì)選擇在CLI,也就是npm scripts里面進(jìn)行配置)。在webpack4以下版本,webpack3.XX,通過plugins進(jìn)行環(huán)境變量的配置。【resolve】模塊,resolver是個(gè)庫,幫助webpack找到bundle需要引入的模塊代碼,打包時(shí),webpack使用enhanced-resolve來解析路徑。 2.webpack優(yōu)化 多進(jìn)程打包 安裝插件thread-loader parallel-webpack HappyPack多進(jìn)程壓縮 parallel-uglify-plugin terser-webpack-plugin 資源CDN 公用代碼提取,使用 CDN 加載 動(dòng)態(tài)polyfill 動(dòng)態(tài) polyfill 指的是根據(jù)不同的瀏覽器,動(dòng)態(tài)載入需要的 polyfillflex布局
flex是由 flex-grow:1父容器在主軸上還有多少剩余空間,flex-shrink當(dāng)父元素的寬度大于所有子元素的寬度的和時(shí)(即父元素會(huì)有剩余空間), 子元素如何分配父元素的剩余空間flex-basis基準(zhǔn)值組成flex 怎么實(shí)現(xiàn)1個(gè)盒子垂直居中 如何實(shí)現(xiàn)四個(gè)盒子水平均勻分布父容器 display:flex; justify-content: center; align-items: center;display: flex; justify-content:space-evenly; align-items: center;實(shí)現(xiàn)導(dǎo)航的吸頂效果
設(shè)置css:fixed固定定位 判斷滾動(dòng)條滾動(dòng)的距離大于導(dǎo)航條距頂部的距離,來判斷是否實(shí)現(xiàn)吸頂,然后addClass添加樣式less的hover簡寫
a{&:hover {} //這里&代表它的上一級(jí)就是a }CSS偽類 ::after,before的應(yīng)用場景
::before和::after必須配合content屬性來使用, content用來定義插入的內(nèi)容,content必須有值,至少是空。 默認(rèn)情況下,偽類元素的display是默認(rèn)值inline,可以通過設(shè)置display:block來改變其顯示。1.清除浮動(dòng): 在浮動(dòng)元素后面添加一個(gè)空的Div標(biāo)簽,然后在設(shè)置它的清除浮動(dòng)要是,使用after偽元素2.常見消息框 : 偽類content:' ' 偽類4條邊必須寬度相同,而且其他三條邊為transparent 可以通過設(shè)置定位元素left,top值為50%,translate(-50%,-50%) 來使任意寬高的元素居中。div::before{content:' ';3.陰影 : 通過設(shè)置before,after不同位置,不同旋轉(zhuǎn)角度,要保證偽類的顏色及z-indexdiv.outer::before,div.outer::after{content:'';z-index:1;width:50%;height:3px;position:absolute;left:10px;bottom:7px;background-color:transparent;box-shadow:5px 5px 10px rgba(0,0,0,0.5);-webkit-transform:rotate(-3deg);4.做出各種圖形效果#star-five:before {border-bottom: 80px solid red;border-left: 30px solid transparent;border-right: 30px solid transparent;position: absolute;height: 0;width: 0;top: -45px;left: -65px;content: '';transform: rotate(-35deg);}#star-five:after {width: 0;height: 0;border-left: 100px solid transparent;border-right: 100px solid transparent;border-bottom: 70px solid yellow;top: 7px;left: -110px;position: absolute;display: block;content: '';transform: rotate(-70deg);}CSS權(quán)重的計(jì)算
權(quán)重疊加 0,0,0,5 + 0,0,0,5 =0,0,0,10 而不是 0,0,1,0,所以不會(huì)存在10個(gè)div能趕上一個(gè)類選擇器的情況繼承的權(quán)重是0 1)如果選中了,那么以上面的公式來計(jì)權(quán)重。誰大聽誰的。 2)如果沒有選中,那么權(quán)重是0,因?yàn)槔^承的權(quán)重為0當(dāng)選擇器沖突時(shí),權(quán)重高的生效;當(dāng)權(quán)重相同時(shí),寫在后頭的會(huì)把前面的覆蓋。http
http2.0,https連接,http概述:超文本傳輸協(xié)議,是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議http的缺點(diǎn) 1.通信使用明文可能會(huì)被竊聽。 2.不驗(yàn)證通信方的身份可能遭遇偽裝。 3.無法證明報(bào)文的完整性,可能已遭篡改。https就是在安全的傳輸層上發(fā)送的http。它在將http報(bào)文發(fā)送給TCP之前,先將其發(fā)送給了一個(gè)安全層 ,對(duì)其進(jìn)行加密。http安全層是通過ssl及其現(xiàn)代替代協(xié)議TSL來實(shí)現(xiàn)的。https的優(yōu)點(diǎn) (1)使用HTTPS協(xié)議可認(rèn)證用戶和服務(wù)器,確保數(shù)據(jù)發(fā)送到正確的客戶機(jī)和服務(wù)器; (2)HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,要比http協(xié)議安全,可防止數(shù)據(jù)在傳輸過程中不被竊取、改變,確保數(shù)據(jù)的完整性。https的缺點(diǎn) 但是https因?yàn)榧恿藢觭sl,所以在效率方面比較低,會(huì)使頁面加載的時(shí)長延長近50%,也會(huì)增加10-20%的耗電。 需要安裝證書,在一定基礎(chǔ)上增加部署費(fèi)用,并且報(bào)文加密解密對(duì)數(shù)據(jù)傳遞有一點(diǎn)的效率影響。http/2.0的目標(biāo)是改善用戶加載頁面的時(shí)候更快 HTTP/2采用二進(jìn)制格式而非文本格式 HTTP/2是完全多路復(fù)用的,而非有序并阻塞的——只需一個(gè)連接即可實(shí)現(xiàn)并行http對(duì)稱加密非對(duì)稱加密
對(duì)稱密鑰加密是指加密和解密使用同一個(gè)密鑰的方式,一方通過密鑰將信息加密后,把密文傳給另一方,另一方通過這個(gè)相同的密鑰將密文解密,轉(zhuǎn)換成可以理解的明文非對(duì)稱加密是加密和解密使用的是兩個(gè)不同的密鑰,所以這種算法叫作非對(duì)稱加密算法。指使用一對(duì)非對(duì)稱密鑰,即公鑰和私鑰,公鑰可以隨意發(fā)布,但私鑰只有自己知道。發(fā)送密文的一方使用對(duì)方的公鑰進(jìn)行加密處理,對(duì)方接收到加密信息后,使用自己的私鑰進(jìn)行解密。WebSocket和http有什么區(qū)別
socket是傳輸控制層協(xié)議,webSocket是應(yīng)用層協(xié)議WebSocket protocol 是HTML5一種新的協(xié)議。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信(full-duplex)。 一開始的握手需要借助HTTP請(qǐng)求完成。HTTP請(qǐng)求缺點(diǎn): 會(huì)導(dǎo)致過多不必要的請(qǐng)求,浪費(fèi)流量和服務(wù)器資源,每一次請(qǐng)求、應(yīng)答,都浪費(fèi)了一定流量在相同的頭部信息上然而WebSocket的出現(xiàn)可以彌補(bǔ)這一缺點(diǎn)。 在WebSocket中,只需要服務(wù)器和瀏覽器通過HTTP協(xié)議進(jìn)行一個(gè)握 手的動(dòng)作,然后單獨(dú)建立一條TCP的通信通道進(jìn)行數(shù)據(jù)的傳送。原理:(webSocket) WebSocket同HTTP一樣也是應(yīng)用層的協(xié)議,但是它是一種雙向通信協(xié)議,是建立在TCP之上的。1. 瀏覽器、服務(wù)器建立TCP連接,三次握手。這是通信的基礎(chǔ),傳輸控制層,若失敗后續(xù)都不執(zhí)行。 2. TCP連接成功后,瀏覽器通過HTTP協(xié)議向服務(wù)器傳送WebSocket支持的版本號(hào)等信息。(開始前的HTTP握手) 3. 服務(wù)器收到客戶端的握手請(qǐng)求后,同樣采用HTTP協(xié)議回饋數(shù)據(jù)。 4. 當(dāng)收到了連接成功的消息后,通過TCP通道進(jìn)行傳輸通信。WebSocket與HTTP的關(guān)系 相同點(diǎn): 都是一樣基于TCP的,都是可靠性傳輸協(xié)議。 都是應(yīng)用層協(xié)議不同點(diǎn): WebSocket是雙向通信協(xié)議,模擬Socket協(xié)議,可以雙向發(fā)送或接受信息。HTTP是單向的。 WebSocket是需要握手進(jìn)行建立連接的。錯(cuò)誤調(diào)試工具
F12 斷點(diǎn) 錯(cuò)誤附近輸出打印 火狐中的firebug IE開發(fā)者工具 Emmethttp狀態(tài)碼
200 OK 請(qǐng)求成功。一般用于GET與POST請(qǐng)求 3開頭 重定向 300 多種選擇。請(qǐng)求的資源可包括多個(gè)位置,相應(yīng)可返回一個(gè)資源特征與地址的列表用于用戶終端(例如:瀏覽器)選擇 301 永久移動(dòng)。請(qǐng)求的資源已被永久的移動(dòng)到新URI,返回信息會(huì)包括新的URI,瀏覽器會(huì)自動(dòng)定向到新URI。今后任何新的請(qǐng)求都應(yīng)使用新的URI代替 302 臨時(shí)移動(dòng)。與301類似。但資源只是臨時(shí)被移動(dòng)。客戶端應(yīng)繼續(xù)使用原有URI 303 查看其它地址。與301類似。使用GET和POST請(qǐng)求查看 304 未修改。所請(qǐng)求的資源未修改,服務(wù)器返回此狀態(tài)碼時(shí),不會(huì)返回任何資源。客戶端通常會(huì)緩存訪問過的資源,通過提供一個(gè)頭信息指出客戶端希望只返回在指定日期之后修改的資源 305 使用代理。所請(qǐng)求的資源必須通過代理訪問 306 已經(jīng)被廢棄的HTTP狀態(tài)碼 307 臨時(shí)重定向。與302類似。使用GET請(qǐng)求重定向 400 客戶端請(qǐng)求的語法錯(cuò)誤,服務(wù)器無法理解 401 請(qǐng)求要求用戶的身份認(rèn)證 402 保留,將來使用 403 服務(wù)器理解請(qǐng)求客戶端的請(qǐng)求,但是拒絕執(zhí)行此請(qǐng)求 404 服務(wù)器無法根據(jù)客戶端的請(qǐng)求找到資源(網(wǎng)頁)。通過此代碼,網(wǎng)站設(shè)計(jì)人員可設(shè)置"您所請(qǐng)求的資源無法找到"的個(gè)性頁面 405 客戶端請(qǐng)求中的方法被禁止 406 N服務(wù)器無法根據(jù)客戶端請(qǐng)求的內(nèi)容特性完成請(qǐng)求 407 請(qǐng)求要求代理的身份認(rèn)證,與401類似,但請(qǐng)求者應(yīng)當(dāng)使用代理進(jìn)行授權(quán) 408 服務(wù)器等待客戶端發(fā)送的請(qǐng)求時(shí)間過長,超時(shí) 409 服務(wù)器完成客戶端的 PUT 請(qǐng)求時(shí)可能返回此代碼,服務(wù)器處理請(qǐng)求時(shí)發(fā)生了沖突 410 客戶端請(qǐng)求的資源已經(jīng)不存在。410不同于404,如果資源以前有現(xiàn)在被永久刪除了可使用410代碼,網(wǎng)站設(shè)計(jì)人員可通過301代碼指定資源的新位置 411 服務(wù)器無法處理客戶端發(fā)送的不帶Content-Length的請(qǐng)求信息 412 客戶端請(qǐng)求信息的先決條件錯(cuò)誤 413 由于請(qǐng)求的實(shí)體過大,服務(wù)器無法處理,因此拒絕請(qǐng)求。為防止客戶端的連續(xù)請(qǐng)求,服務(wù)器可能會(huì)關(guān)閉連接。如果只是服務(wù)器暫時(shí)無法處理,則會(huì)包含一個(gè)Retry-After的響應(yīng)信息 414 請(qǐng)求的URI過長(URI通常為網(wǎng)址),服務(wù)器無法處理 415 服務(wù)器無法處理請(qǐng)求附帶的媒體格式 416 客戶端請(qǐng)求的范圍無效 417 服務(wù)器無法滿足Expect的請(qǐng)求頭信息 500 服務(wù)器內(nèi)部錯(cuò)誤,無法完成請(qǐng)求 501 服務(wù)器不支持請(qǐng)求的功能,無法完成請(qǐng)求 502 作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請(qǐng)求時(shí),從遠(yuǎn)程服務(wù)器接收到了一個(gè)無效的響應(yīng) 503 由于超載或系統(tǒng)維護(hù),服務(wù)器暫時(shí)的無法處理客戶端的請(qǐng)求。延時(shí)的長度可包含在服務(wù)器的Retry-After頭信息中 504 充當(dāng)網(wǎng)關(guān)或代理的服務(wù)器,未及時(shí)從遠(yuǎn)端服務(wù)器獲取請(qǐng)求 505 服務(wù)器不支持請(qǐng)求的HTTP協(xié)議的版本,無法完成處理HTTP和HTTPS的區(qū)別
HTTP是超文本傳輸協(xié)議,信息是明文傳輸?shù)?#xff0c;HTTPS是具有ssl/tls加密傳輸協(xié)議。默認(rèn)端口不同,前者是80,后者是443。HTTPS比HTTP安全HTTPS協(xié)議需要到CA申請(qǐng)證書,需要一定費(fèi)用瀏覽器的緩存機(jī)制
什么是瀏覽器緩存 Web緩存是指一個(gè)Web資源(如html頁面,圖片,js,數(shù)據(jù)等)存在于Web服務(wù)器和客戶端(瀏覽器)之間的副本。緩存會(huì)根據(jù)進(jìn)來的請(qǐng)求保存輸出內(nèi)容的副本;當(dāng)下一個(gè)請(qǐng)求來到的時(shí)候,如果是相同的URL,緩存會(huì)根據(jù)緩存機(jī)制決定是直接使用副本響應(yīng)訪問請(qǐng)求,還是向源服務(wù)器再次發(fā)送請(qǐng)求。比較常見的就是瀏覽器會(huì)緩存訪問過網(wǎng)站的網(wǎng)頁,當(dāng)再次訪問這個(gè)URL地址的時(shí)候,如果網(wǎng)頁沒有更新,就不會(huì)再次下載網(wǎng)頁,而是直接使用本地緩存的網(wǎng)頁。只有當(dāng)網(wǎng)站明確標(biāo)識(shí)資源已經(jīng)更新,瀏覽器才會(huì)再次下載網(wǎng)頁。瀏覽器和網(wǎng)站服務(wù)器是根據(jù)緩存機(jī)制進(jìn)行緩存的非HTTP協(xié)議定義的緩存機(jī)制瀏覽器緩存機(jī)制,其實(shí)主要就是HTTP協(xié)議定義的緩存機(jī)制(如: Expires; Cache-control等)。但是也有非HTTP協(xié)議定義的緩存機(jī)制,如使用HTML Meta 標(biāo)簽,Web開發(fā)者可以在HTML頁面的<head>節(jié)點(diǎn)中加入<meta>標(biāo)簽<meta http-equiv="Pragma" content="no-cache">上述代碼的作用是告訴瀏覽器當(dāng)前頁面不被緩存,每次訪問都需要去服務(wù)器拉取。使用上很簡單,但只有部分瀏覽器可以支持,而且所有緩存代理服務(wù)器都不支持,因?yàn)榇聿唤馕鯤TML內(nèi)容本身。瀏覽器在第一次請(qǐng)求發(fā)生后,再次請(qǐng)求時(shí):瀏覽器會(huì)先獲取該資源緩存的header信息,根據(jù)其中的expires和cache-control判斷是否命中強(qiáng)緩存),若命中則直接從緩存中獲取資源,包括緩存的header信息,本次請(qǐng)求不會(huì)與服務(wù)器進(jìn)行通信; 如果沒有命中強(qiáng)緩存,瀏覽器會(huì)發(fā)送請(qǐng)求到服務(wù)器,該請(qǐng)求會(huì)攜帶第一次請(qǐng)求返回的有關(guān)緩存的header字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服務(wù)器根據(jù)請(qǐng)求中的相關(guān)header信息來對(duì)比結(jié)果是否命中協(xié)商緩存,若命中,則服務(wù)器返回新的響應(yīng)header信息更新緩存中的對(duì)應(yīng)header信息,但是并不返回資源內(nèi)容,它會(huì)告知瀏覽器可以直接從緩存獲取;否則返回最新的資源內(nèi)容瀏覽器的強(qiáng)緩存和協(xié)商緩存
這里說的緩存是指瀏覽器(客戶端)在本地磁盤中對(duì)訪問過的資源保存的副本文件。瀏覽器緩存主要有以下幾個(gè)優(yōu)點(diǎn): 1. 減少重復(fù)數(shù)據(jù)請(qǐng)求,避免通過網(wǎng)絡(luò)再次加載資源,節(jié)省流量。 2. 降低服務(wù)器的壓力,提升網(wǎng)站性能。 3. 加快客戶端加載網(wǎng)頁的速度,提升用戶體驗(yàn)。瀏覽器緩存分為強(qiáng)緩存和協(xié)商緩存,兩者有兩個(gè)比較明顯的區(qū)別: 1. 如果瀏覽器命中強(qiáng)緩存,則不需要給服務(wù)器發(fā)請(qǐng)求;而協(xié)商緩存最終由服務(wù)器來決定是否使用緩存,即客戶端與服務(wù)器之間存在一次通信。 2. 在chrome中強(qiáng)緩存(雖然沒有發(fā)出真實(shí)的http請(qǐng)求)的請(qǐng)求狀態(tài)碼返回是200(from cache);而協(xié)商緩存如果命中走緩存的話,請(qǐng)求的狀態(tài)碼是304(not modified)。不同瀏覽器的策略不同,在Fire Fox中,from cache狀態(tài)碼是304.強(qiáng)緩存 強(qiáng)緩存是利用http的返回頭中的Expires或者Cache-Control兩個(gè)字段來控制的,用來表示資源的緩存時(shí)間。 Expires:該字段是http1.0時(shí)的規(guī)范,它的值為一個(gè)絕對(duì)時(shí)間的GMT格式的時(shí)間字符串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT。這個(gè)時(shí)間代表著這個(gè)資源的失效時(shí)間,在此時(shí)間之前,即命中緩存。這種方式有一個(gè)明顯的缺點(diǎn),由于失效時(shí)間是一個(gè)絕對(duì)時(shí)間,所以當(dāng)服務(wù)器與客戶端時(shí)間偏差較大時(shí),就會(huì)導(dǎo)致緩存混亂。 Cache-Control:Cache-Control是http1.1時(shí)出現(xiàn)的header信息,主要是利用該字段的max-age值來進(jìn)行判斷,它是一個(gè)相對(duì)時(shí)間,例如Cache-Control:max-age=3600,代表著資源的有效期是3600秒。cache-control除了該字段外,還有下面幾個(gè)比較常用的設(shè)置值:no-cache:不使用本地緩存。需要使用緩存協(xié)商,先與服務(wù)器確認(rèn)返回的響應(yīng)是否被更改,如果之前的響應(yīng)中存ETag,那么請(qǐng)求的時(shí)候會(huì)與服務(wù)端驗(yàn)證,如果資源未被更改,則可以避免重新下載。 no-store:直接禁止游覽器緩存數(shù)據(jù),每次用戶請(qǐng)求該資源,都會(huì)向服務(wù)器發(fā)送一個(gè)請(qǐng)求,每次都會(huì)下載完整的資源。 public:可以被所有的用戶緩存,包括終端用戶和CDN等中間代理服務(wù)器。 private:只能被終端用戶的瀏覽器緩存,不允許CDN等中繼緩存服務(wù)器對(duì)其緩存。Cache-Control與Expires可以在服務(wù)端配置同時(shí)啟用,同時(shí)啟用的時(shí)候Cache-Control優(yōu)先級(jí)高。為什么要有Etag HTTP1.1中Etag的出現(xiàn)主要是為了解決幾個(gè)Last-Modified比較難解決的問題:1.一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間)這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET 2.某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級(jí)的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒); 3.某些服務(wù)器不能精確的得到文件的最后修改時(shí)間。Last-Modified與ETag是可以一起使用的,服務(wù)器會(huì)優(yōu)先驗(yàn)證ETag,一致的情況下,才會(huì)繼續(xù)比對(duì)Last-Modified,最后才決定是否返回304。200 OK(from cache)與304 Not Modified的區(qū)別200 OK( from cache )不向服務(wù)器發(fā)送請(qǐng)求,直接使用本地緩存文件。304 Not Modified則向服務(wù)器詢問,若服務(wù)器認(rèn)為瀏覽器的緩存版本還可用,那么便會(huì)返回304。緩存類型 獲取資源形式 狀態(tài)碼 發(fā)送請(qǐng)求到服務(wù)器 強(qiáng)緩存 從緩存取 200(from cache) 否,直接從緩存取 協(xié)商緩存 從緩存取 304(Not Modified) 否,通過服務(wù)器來告知緩存是否可用用戶行為對(duì)緩存的影響 用戶操作 Expires/Cache-Control Last-Modied/Etag 地址欄回車 有效 有效 頁面鏈接跳轉(zhuǎn) 有效 有效 新開窗口 有效 有效 前進(jìn)回退 有效 有效 F5刷新 無效 有效 Ctrl+F5強(qiáng)制刷新 無效 無效不能被緩存的請(qǐng)求
1. HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請(qǐng)求 2. 需要根據(jù)Cookie,認(rèn)證信息等決定輸入內(nèi)容的動(dòng)態(tài)請(qǐng)求是不能被緩存的 3. 經(jīng)過HTTPS安全加密的請(qǐng)求 4. POST請(qǐng)求無法被緩存 5. HTTP響應(yīng)頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請(qǐng)求無法被緩存用戶行為對(duì)緩存的影響
qq、fire fox 、safari 、chrome 這幾個(gè)瀏覽器的訪問同一個(gè)頁面,不同的瀏覽器在 F5 刷新的時(shí)候 ,同一個(gè)文件 qq 、fire fox 瀏覽器會(huì)返回 `304 Not Nodified`,在請(qǐng)求頭中不攜帶 `Expires/Cache-Control`; 而 chrome 和 safari 刷新的時(shí)候,會(huì)返回 `200 from cache`, 沒有真正發(fā)起請(qǐng)求,走強(qiáng)緩存。可見不同的瀏覽器反饋是不一致的,所以下面表格中"F5刷新"時(shí) `Expires/Cache-Control` 會(huì)無效我認(rèn)為是存在一定爭議的。而 Ctrl + F5 強(qiáng)制刷新的時(shí)候,會(huì)暫時(shí)禁用強(qiáng)緩存和協(xié)商緩存。eslint規(guī)則
Eslint 是一個(gè)JavaScript驗(yàn)證工具,有了它可以讓你的編輯器像ide一樣進(jìn)行一些靜態(tài)的錯(cuò)誤提示功能.npm install eslint -g某些文件關(guān)閉eslint檢測 在文件的最頂端加上注釋 /*eslint-disable*/關(guān)閉某一行代碼的eslint檢查 // eslint-disable-next-line.eslintrc.json配置rules選項(xiàng)git
(版本回退是什么命令,哪個(gè)命令查看已刪除的提交commitId)git-reset 版本回退git reset --hard xxx 回到上一個(gè)版本git reset --soft xxx 該命令將最近一次提交節(jié)點(diǎn)的提交記錄回退到暫存區(qū)git reset --mixed xxx 是將最近一次提交節(jié)點(diǎn)記錄回退到工作區(qū)git log 與 git reflog 查看歷史記錄(被刪除的歷史commit ID)git場景問題 提交暫存區(qū)git add 出錯(cuò) git reset HEAD <文件名> 回退提交本地倉庫 git commit出錯(cuò): 1.更改 commit 信息:git commit --amend -m“新提交消息” 2.漏提交:git add missed-file // missed-file 為遺漏提交文件git commit --amend --no-edit //--no-edit提交消息不會(huì)更改 3.git reset --hard commit_id git log查看提交的版本git revert 是提交一個(gè)新的版本 git fetch 將遠(yuǎn)程主機(jī)的更新全部放到本地中g(shù)it revert 和 git reset 的區(qū)別:(1)git revert是用一次新的commit來回滾之前的commit,git reset是直接刪除指定的commit。 (2)git revert是用一次逆向的commit“中和”之前的提交 ,合并的時(shí)候回滾的變化不會(huì)出現(xiàn)git reset是之間把某些commit在某個(gè)branch上刪除,合并時(shí)候回滾的commit會(huì)被引入node.js
1.Node不是一個(gè)后端語言,但是它可以做類似后端語言的功能 2.Node是使用谷歌V8引擎 3.Node是js的一個(gè)運(yùn)行環(huán)境 4.Node具有非阻塞I/O 特點(diǎn) 5.Node采用了Common.js規(guī)范 node+koa2 node+express用于快速構(gòu)建Node.js項(xiàng)目node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScirpt 運(yùn)行環(huán)境。Node.js使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式I/O的模型,使其輕量又高效**Node.js基于commonjs規(guī)范事件驅(qū)動(dòng): 任務(wù)執(zhí)行,發(fā)布者,訂閱者,事件驅(qū)動(dòng) . 異步(非阻塞): 執(zhí)行某一個(gè)任務(wù)的同時(shí)也可以執(zhí)行其他任務(wù) 同步(阻塞): 執(zhí)行某一個(gè)任務(wù),這個(gè)任務(wù)如果沒有執(zhí)行完成,其他任務(wù)必須等待 I/O: 輸入/輸出( 數(shù)據(jù)庫操作,文件系統(tǒng)操作等 ) - 服務(wù)器的環(huán)境 非阻塞I/O模型: 當(dāng)使用Node.js來實(shí)現(xiàn)數(shù)據(jù)庫操作、文件系統(tǒng)等操作時(shí),要進(jìn)行的異步操作,異步操作的核心傳統(tǒng)實(shí)現(xiàn)方式就是回調(diào)函數(shù)和事件。Node.js的包管理工具npm優(yōu)點(diǎn):Node.js 使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式 I/O 的模型,異步編程,使其輕量又高效。 缺點(diǎn):單進(jìn)程,單線程,只支持單核cpu,不能充分的利用多核cpu服務(wù)器。一旦這個(gè)進(jìn)程崩掉,那么整個(gè)web服務(wù)就崩掉了。內(nèi)置模塊 http 是用于創(chuàng)建一個(gè)能夠處理和響應(yīng) http 響應(yīng)的服務(wù)fs 用于對(duì)系統(tǒng)文件及目錄進(jìn)行讀寫操作。 path 提供了一些用于處理文件路徑的小工具 Url:幫助我們對(duì)提交上來的url進(jìn)行解析處理 querystring 提供用于解析和格式化 URL 查詢字符串的工具。qs.parse() qs.stringify()TS語法
TypeScript具有類型系統(tǒng),且是JavaScript的超集。它可以編譯成普通的JavaScript代碼。 TypeScript支持任意瀏覽器,任意環(huán)境,任意系統(tǒng)并且是開源的。npm install -g typescripttsc --init 生成tsconfig.json配置文件基礎(chǔ)數(shù)據(jù)類型 number、string、boolean、null 、undefined any 表示任意類型 void 表示空類型 內(nèi)置對(duì)象類型Array BooleanHTMLElementHTMLDivElement 自定義類型 接口 interface 類 泛型 未來的類型定義的時(shí)候不知道是什么類型,調(diào)用的時(shí)候才知道元組 1、數(shù)組中的數(shù)據(jù)類型必須和規(guī)定的類型順序?qū)?yīng)起來 2、當(dāng)使用越界索引給數(shù)組賦值的時(shí)候,會(huì)使用聯(lián)合類型(只要值是規(guī)定類型的某一種即可)。枚舉 enum類型是對(duì)JavaScript標(biāo)準(zhǔn)數(shù)據(jù)類型的一個(gè)補(bǔ)充never類型表示的是那些永不存在的值的類型。readonly:只讀屬性,不可修改sex? :表示sex是一個(gè)可傳屬性,可以有也可以沒有[propName: string]: any;表示新增的屬性可以是任意類型arr3: Array<number> 數(shù)組類型定義arr2: (number | string)[]fn (a: number, b: number) : number 函數(shù)類型定義linux命令
pwd:輸入pwd命令,Linux會(huì)輸出當(dāng)前目錄。ls命令用來查看目錄的內(nèi)容。cd命令用來改變所在目錄。cat命令可以用來合并文件,也可以用來在屏幕上顯示整個(gè)文件的內(nèi)容。grep命令的最大功能是在一堆文件中查找一個(gè)特定的字符串。touch命令用來創(chuàng)建新文件cp命令用來拷貝文件mv命令用來移動(dòng)文件rm命令用來刪除文件。 mkdir 創(chuàng)建文件夾創(chuàng)建目錄CSS3新特性
1 圓角邊框:border-radius 2 多背景圖:background 3 顏色和透明度:background: rgba(0,0,0,.5) 4 多列布局和彈性盒:display: flex 5 盒子的變幻(2D、3D)transform: translate(50px,100px);//移動(dòng) transform: rotate(); //旋轉(zhuǎn) transform: scale(); //縮放transform: skew(); //傾斜 6 過渡 transition: width 1s linear 2s; 動(dòng)畫:animation: myfirst 5s; @keyframes myfirst { 0% {background: block;} 25% {background: red;} 50% {background: yellow;} 100% {background: green;} } 7 引入web字體(在服務(wù)器端存儲(chǔ)) 8 媒體查詢 9 陰影 h 10 文字陰影 text-shadow div 11 盒子陰影 box-shadowHTML5 h5新特性
1 語義化標(biāo)簽 section aside header nav 2 表單新特性:autofocus 自動(dòng)獲取焦點(diǎn)placeholder 占位multipleautocomplete 自動(dòng)補(bǔ)全,是否自動(dòng)記錄之前提交的數(shù)據(jù),以用于下一次輸入建議required 在表單提交時(shí)會(huì)驗(yàn)證是否有輸入,沒有則彈出提示消息。min:限定輸入數(shù)字的最小值。max:限定輸入數(shù)字的最大值 3 video(視頻)和audio(音頻) 4 canvas畫布 5 webworker 就是為 JavaScript 創(chuàng)造多線程環(huán)境,允許主線程創(chuàng)建 Worker 線程,將一些任務(wù)分配給后者運(yùn)行。 6 webscoket 服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話,屬于服務(wù)器推送技術(shù)的一種。 7 拖拽apidragstart:源對(duì)象開始拖放。 drag:源對(duì)象拖放過程中。 dragend:源對(duì)象拖放結(jié)束。 過程對(duì)象: dragenter:源對(duì)象開始進(jìn)入過程對(duì)象范圍內(nèi)。 dragover:源對(duì)象在過程對(duì)象范圍內(nèi)移動(dòng)。 dragleave:源對(duì)象離開過程對(duì)象標(biāo)準(zhǔn)盒模型與怪異盒模型區(qū)別
標(biāo)準(zhǔn)盒模型一個(gè)塊的總寬度= width + margin(左右) + padding(左右) + border(左右) 怪異盒模型一個(gè)塊的總寬度= width + margin(左右)(即width已經(jīng)包含了padding和 border值)CSS3彈性盒
彈性盒 display:flex(父元素添加) 彈性盒:控制子元素按主軸方向排列 彈性盒可以設(shè)置單獨(dú)內(nèi)容水平垂直居中 父元素:display:flex 子元素:margin:auto 靈活元素:靈活元素即使是內(nèi)聯(lián)元素也能設(shè)置寬高加父元素身上 1.flex-direction 屬性指定了彈性子元素在父容器中的位置。 row:橫向從左到右排列(左對(duì)齊),默認(rèn)的排列方式。row-reverse:反轉(zhuǎn)橫向排列(右對(duì)齊,從后往前排,最后一項(xiàng)排在最前面。column:縱向排列。olumn-reverse:反轉(zhuǎn)縱向排列,從后往前排,最后一項(xiàng)排在最上面。 2.justify-content:flex-start/flex-end/space-between/space-around 3.align-items: 設(shè)置或檢索彈性盒子元素在側(cè)軸(縱軸)方向上的對(duì)齊方式。 center/flex-start/flex-end/baseline/stretch 4.flex-wrap:屬性用于指定彈性盒子的子元素?fù)Q行方式。nowrap/wrap/wrap-reverse 5.align-content:設(shè)置各個(gè)行的對(duì)齊: stretch - 默認(rèn)。各行將會(huì)伸展以占用剩余的空間。flex-start - 各行向彈性盒容器的起始位置堆疊。flex-end - 各行向彈性盒容器的結(jié)束位置堆疊。center -各行向彈性盒容器的中間位置堆疊。space-between -各行在彈性盒容器中平均分布。space-around 加子元素身 1、align-self:屬性用于設(shè)置彈性元素自身在側(cè)軸(縱軸)方向上的對(duì)齊方式。align-self: auto | flex-start | flex-end | center | baseline | stretchflex 屬性用于指定彈性子元素如何分配空間。1: 計(jì)算值為 1 1 autoinitial: 計(jì)算值為 0 1 autonone:計(jì)算值為 0 0 auto inherit:從父元素繼承 2、第一個(gè)參數(shù)表示: flex-grow 定義項(xiàng)目的放大比例,默認(rèn)為0,即如果存在剩余空間,也不放大 3、第二個(gè)參數(shù)表示: flex-shrink 定義了項(xiàng)目的縮小比例,默認(rèn)為1,即如果空間不足,該項(xiàng)目將縮小 4、第三個(gè)參數(shù)表示: flex-basis給上面兩個(gè)屬性分配多余空間之前, 計(jì)算項(xiàng)目是否有多余空間, 默認(rèn)值為 auto, 即項(xiàng)目本身的大小CSS元素居中
1.使用margin進(jìn)行固定長度的偏移 2.使用絕對(duì)定位并進(jìn)行偏移(已知寬高) #father{ position:relative; } #son{ position: absolute; left:50%; top:50%; margin-left: -子元素的寬/2; margin-top: -子元素的高/2; } 3.使用絕對(duì)定位并margin自適應(yīng)進(jìn)行居中 #father{ position:relative;} #son{position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin:auto; }(啊不斯陸特) 4.使用彈性盒子來實(shí)現(xiàn)居中 #father{ display: flex; justify-content: center; align-items: center; }(加斯特佛) (額來) (哎特木) 5.使用定位 + transform #father{ position:relative;} #son{ position: absolute; left: 50%; top: 50%; transform:translate(-50% -50%) }6.table-cell布局 因?yàn)閠able-cell相當(dāng)與表格的td,td為行內(nèi)元素,無法設(shè)置寬和高,所以嵌套一層,嵌套一層必須設(shè)置display: inline-block;CSS幾種定位的區(qū)別 relative, absolute, fixed
1、相對(duì)定位position:relative;參考物是自己,不脫離文檔流(初始位置仍然占據(jù)空 間),top:100px; 給正值是向該容器的中心點(diǎn)移動(dòng);2、絕對(duì)定位position:absolute; 參考物是外層具有position屬性的元素, 如果向外 都么有找到最后會(huì)參考body/html做定位3、固定定位position:fixed; 參考物是可視窗口 4、粘性定位(了解)position:sticky; 是絕對(duì)定位+固定定位div外邊距重疊的原因及解決辦法
情況一:兩個(gè)div垂直邊界相鄰,margin會(huì)等于二者中margin較大的值 解決方案: 1.position:absolute 2.float:left 情況二:子元素在父元素內(nèi),子元素的margin-top會(huì)與父元素的margin-top重疊,值等于二者中較大的,如果只有子元素設(shè)置了margin-top,則顯示為父元素的margin-top 解決方案: 1.給父元素設(shè)置border(給子元素設(shè)置邊框沒有用) 2.給父元素設(shè)置padding值 3.給父元素或子元素添加float:left 4.給父元素或子元素添加position:absolute 5.給父元素添加overflow:hidden 6.給子元素添加display:inline-block 情況三:一個(gè)空白元素自身的margin-top和margin-bottom會(huì)重疊,值為而這種較大的 解決方案: 1.設(shè)置透明borderpx,em,rem,pt的區(qū)別
1、px實(shí)際上就是像素,用px設(shè)置字體大小時(shí),比較穩(wěn)定和精確 2、em就是根據(jù)基準(zhǔn)來縮放字體的大小 3、rem是相對(duì)于根元素字體大小來顯示的 4、pt的大小等于1英寸的1/72 瀏覽器的兼容性除了IE6-IE8,其他的瀏覽器都支持em和rem,px所有瀏覽器都支持CSS的BFC
1、什么是BFC BFC(Block formatting context)直譯為“塊級(jí)格式化上下文”。 他是一個(gè)獨(dú)立的渲染區(qū)域,也可以理解成一個(gè)獨(dú)立的容器,并且這個(gè)容器里box的布局,與這個(gè)容器外的毫不相干。 2、BFC渲染規(guī)則 a.內(nèi)部的box會(huì)在垂直方向,一個(gè)接一個(gè)的放置 b.box垂直方向的距離由margin決定。屬于同一個(gè)BFC的兩個(gè)相鄰box的margin會(huì)發(fā)生重 疊 c.每個(gè)元素的margin box的左邊,與包含塊border box的左邊相接觸(對(duì)于從左往右的格 式化,否則相反)。 即使存在浮動(dòng)也是如此 d.BFC的區(qū)域不會(huì)與float box重疊 e.BFC就是頁面上的一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會(huì)影響到外面的元素。反之 也如此 f.計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算 3、如何產(chǎn)生BFC a.根元素 b.float屬性不為none c.position為absolute或fixed d.display為inline-block, table-cell,table-caption,flex,inline-flex e.overflow不為visible 4、BFC的作用 a.自適應(yīng)兩欄布局 b.清除內(nèi)部浮動(dòng) c.防止垂直margin重疊(放在兩個(gè)BFC里)兼容問題
1)css瀏覽器兼容問題(比如設(shè)置元素透明度,ie瀏覽器使用濾鏡實(shí)現(xiàn),filter :progid:DXlmage Transform.Microsoft.Alpha(style=0,opacity=50);非IE瀏覽器 opacity:0.5) 解決方法:現(xiàn)在前端開發(fā)已經(jīng)出現(xiàn)了非常多的框架和類庫用于瀏覽器的兼容問題,比如jq類 庫,解決獲取元素中包含的所有文本內(nèi)容兼容性問題,$(“element”).text(“element text”) 2)css3瀏覽器前綴問題 -ms-:ie瀏覽器 -o-:opera歐朋瀏覽器 -webkit-:谷歌瀏覽器 -moz-:火狐瀏覽器工作中遇到的困難 1)IE6中高度不對(duì)問題 在div中給定了高度為1px,其它瀏覽器顯示正常,可是ie6中顯示的高度就不對(duì)了,這時(shí)我 給樣式表中加 了個(gè)font-size:0px;line-height:0px;就好了 2)把border設(shè)為“0”像素雖然在頁面上看不見,但按border默認(rèn)值理解,瀏覽器依然對(duì) border- width/border-color進(jìn)行了渲染,即已經(jīng)占用了內(nèi)存值把border設(shè)為“none”即沒有,瀏覽器解析“none”時(shí)將不作出渲染動(dòng)作,即不會(huì)消耗內(nèi)存移動(dòng)端適配
1.Media Queries 通過查詢?cè)O(shè)備的寬度來執(zhí)行不同的 css 代碼,最終達(dá)到界面 的配置 2.Flex彈性布局 3.rem + viewport 縮放 實(shí)現(xiàn)原理 根據(jù)rem將頁面放大dpr倍, 然后viewport設(shè)置為1/dpr. 4、rem實(shí)現(xiàn) 移動(dòng)端適配方案: 1)viewport(scale=1/dpr) dpr:備像素比 2)rem 3)flex 4)vm/vh以iphone8為例,iphone8的CSS像素為375px*677px,DPR是2,所以其設(shè)備像素為750px*1354px750(px) / 375(px) = 2什么是CSS預(yù)處理器?優(yōu)點(diǎn)是什么
css預(yù)處理器用一種專門的編程語言,進(jìn)行web頁面樣式設(shè)計(jì),然后在編譯成正常的css文件, 以供項(xiàng)目使用 在css中使用變量、簡單的邏輯程序、函數(shù)。可以讓你的css更加簡潔、適應(yīng)性更強(qiáng)、可讀性更佳、更易于代碼的維護(hù)0.5px線怎么實(shí)現(xiàn)(單邊框0.5px)
方式一:border + border - img + 線性漸變linear-gradient 方式二:定位 + 偽元素 + background + 線性漸變linear-gradient 方式三:定位 + 偽元素 + transform縮放(scale)CSS布局 - 左側(cè)寬度固定,右側(cè)自適應(yīng)
方法一: 設(shè)置絕對(duì)定位寬度固定區(qū)域設(shè)置 position:absolute+ left/right+ top + width自適應(yīng)區(qū)域設(shè)置 margin-left/margin-right: 固定寬度區(qū)域的寬度。注意:(1)若左側(cè)固定的高度大于右側(cè)自適應(yīng)區(qū)域高度頁面布局就變成這樣了:(測試布局區(qū)域緊挨著自適應(yīng)區(qū)域的下方,蓋住了部分固定區(qū)域)簡單粗暴的就是測試布局區(qū)域定位的top值直接設(shè)置為兩個(gè)區(qū)域最高的高度值(2)若左側(cè)固定的高度大于右側(cè)自適應(yīng)區(qū)域高度,且測試區(qū)域不進(jìn)行定位 方法二:浮動(dòng)布局左側(cè)固定區(qū)域浮動(dòng)+寬度,右側(cè)自適應(yīng)區(qū)域 設(shè)置margin-left :左側(cè)寬度值。 方法三:BFC規(guī)則左側(cè)固定區(qū)域浮動(dòng)+寬度,右側(cè)自適應(yīng)區(qū)域(非浮動(dòng)元素)設(shè)置overflow:hidden。CSS布局 - 左右側(cè)寬度固定,中間自適應(yīng)
1、絕對(duì)定位布局:position + margin 缺點(diǎn): 如果中間欄含有最小寬度限制,或是含有寬度的內(nèi)部元素,當(dāng)瀏覽器寬度小到一定程度,會(huì)發(fā)生層重疊的情況。 2、浮動(dòng)布局: float + margin 3、flex布局高度由內(nèi)容決定。 4、table布局高度由內(nèi)容決定。 5、Grid網(wǎng)格布局 6、圣杯布局 7、雙飛翼布局 8、對(duì)比圣杯布局和雙飛翼布局 (1)都是左右欄定寬,中間欄自適應(yīng)的三欄布局,中間欄都放到文檔流前面,保證先行渲染。 (2)解決方案基本相似:都是三欄全部設(shè)置左浮動(dòng)float:left,然后分別結(jié)局中間欄內(nèi)容被覆蓋的問題。 (3)解決中間欄內(nèi)容被覆蓋問題時(shí),圣杯布局設(shè)置父元素的padding,雙飛翼布局在中間欄嵌套一個(gè)div,內(nèi)容放到新的 div中,并設(shè)置margin,實(shí)際上,雙飛翼布局就是圣杯布局的改進(jìn)方案。webpack 打包優(yōu)化 怎么減少打包時(shí)間
多進(jìn)程打包 - 速度分析 多進(jìn)程壓縮 - 體積分析 資源CDN 動(dòng)態(tài)polyfill - 根據(jù)不同瀏覽器,動(dòng)態(tài)載入需要的polyfill,大幅度減少構(gòu)建體積split-thunk 前端構(gòu)建項(xiàng)目中,為了提高打包效率,往往將第三庫與業(yè)務(wù)邏輯代碼分開打包,因?yàn)榈谌綆焱恍枰?jīng)常打包更新。webpack建議使用CommonsChunk 來單獨(dú)打包第三方庫webpack loader(轉(zhuǎn)換器)和plugin(插件)有什么區(qū)別:loader它是一個(gè)轉(zhuǎn)換器,將A文件進(jìn)行編譯形成B文件,這里操作的是文件,比如將A.scss轉(zhuǎn)換為A.css,單純的文件轉(zhuǎn)換過程plugin是一個(gè)擴(kuò)展器,它豐富了webpack本身,針對(duì)是loader結(jié)束后,webpack打包的整個(gè)過程,它并不直接操作文件,而是基于事件機(jī)制工作,會(huì)監(jiān)聽webpack打包過程中的某些節(jié)點(diǎn),執(zhí)行廣泛的任務(wù)loader:優(yōu)雅降級(jí),圖片打包 plugin:html產(chǎn)出:把public下面的html文件打包到build里面的index.html并自動(dòng)引入app.jscss抽離靜態(tài)資源拷貝繼承的6種方式
1.原型鏈繼承重點(diǎn):讓新實(shí)例的原型等于父類的實(shí)例。特點(diǎn):1、實(shí)例可繼承的屬性有:實(shí)例的構(gòu)造函數(shù)的屬性,父類構(gòu)造函數(shù)屬性,父類原型的屬性。(新實(shí)例不會(huì)繼承父類實(shí)例的屬性!)缺點(diǎn):1、新實(shí)例無法向父類構(gòu)造函數(shù)傳參。2、繼承單一。3、所有新實(shí)例都會(huì)共享父類實(shí)例的屬性。(原型上的屬性是共享的,一個(gè)實(shí)例修改了原型屬性,另一個(gè)實(shí)例的原型屬性也會(huì)被修改!) 2.借用構(gòu)造函數(shù)繼承重點(diǎn):用.call()和.apply()將父類構(gòu)造函數(shù)引入子類函數(shù)(在子類函數(shù)中做了父類函數(shù)的自執(zhí)行(復(fù)制))特點(diǎn):1、只繼承了父類構(gòu)造函數(shù)的屬性,沒有繼承父類原型的屬性。2、解決了原型鏈繼承缺點(diǎn)1、2、3。3、可以繼承多個(gè)構(gòu)造函數(shù)屬性(call多個(gè))。4、在子實(shí)例中可向父實(shí)例傳參。缺點(diǎn):1、只能繼承父類構(gòu)造函數(shù)的屬性。2、無法實(shí)現(xiàn)構(gòu)造函數(shù)的復(fù)用。(每次用每次都要重新調(diào)用)3、每個(gè)新實(shí)例都有父類構(gòu)造函數(shù)的副本,臃腫。 3.組合繼承(組合原型鏈繼承和借用構(gòu)造函數(shù)繼承) 重點(diǎn):結(jié)合了兩種模式的優(yōu)點(diǎn),傳參和復(fù)用特點(diǎn):1、可以繼承父類原型上的屬性,可以傳參,可復(fù)用。2、每個(gè)新實(shí)例引入的構(gòu)造函數(shù)屬性是私有的。缺點(diǎn):調(diào)用了兩次父類構(gòu)造函數(shù)(耗內(nèi)存),子類的構(gòu)造函數(shù)會(huì)代替原型上的那個(gè)父類構(gòu)造函數(shù)。 4.原型式繼承重點(diǎn):用一個(gè)函數(shù)包裝一個(gè)對(duì)象,然后返回這個(gè)函數(shù)的調(diào)用,這個(gè)函數(shù)就變成了個(gè)可以隨意增添屬性的實(shí)例或?qū)ο蟆? object.create()就是這個(gè)原理。特點(diǎn):類似于復(fù)制一個(gè)對(duì)象,用函數(shù)來包裝。缺點(diǎn):1、所有實(shí)例都會(huì)繼承原型上的屬性。2、無法實(shí)現(xiàn)復(fù)用。(新實(shí)例屬性都是后面添加的) 5.寄生式繼承重點(diǎn):就是給原型式繼承外面套了個(gè)殼子。優(yōu)點(diǎn):沒有創(chuàng)建自定義類型,因?yàn)橹皇翘琢藗€(gè)殼子返回對(duì)象(這個(gè)),這個(gè)函數(shù)順理成章就成了創(chuàng)建的新對(duì)象。缺點(diǎn):沒用到原型,無法復(fù)用。 6.寄生組合式繼承(常用)重點(diǎn):修復(fù)了組合繼承的問題寄生:在函數(shù)內(nèi)返回對(duì)象然后調(diào)用組合:1、函數(shù)的原型等于另一個(gè)實(shí)例。2、在函數(shù)中用apply或者call引入另一個(gè)構(gòu)造函數(shù),可傳參阻止冒泡和取消默認(rèn)事件(默認(rèn)行為)
防止事件捕獲和冒泡: w3c的方法是e.stopPropagation() IE則是使用e.cancelBubble = true取消默認(rèn)事件 w3c的方法是e.preventDefault() IE則是使用e.returnValue = falsejQuery用法 阻止默認(rèn)事件 return false (不停止冒泡)作用域和作用域鏈
變量的作用域無非就是兩種: 全局變量和局部變量。javascript的作用域是相對(duì)函數(shù)而言的,可以稱為函數(shù)作用域全局作用域: 最外層函數(shù)定義的變量擁有全局作用域,即對(duì)任何內(nèi)部函數(shù)來說,都是可以訪問的局部作用域: 局部作用域一般只在固定的代碼片段內(nèi)可訪問到,而對(duì)于函數(shù)外部是無法訪問的作用域鏈: 根據(jù)在內(nèi)部函數(shù)可以訪問外部函數(shù)變量的這種機(jī)制,用鏈?zhǔn)讲檎覜Q定哪些數(shù)據(jù)能被內(nèi)部函數(shù)訪問。作用域鏈的前端,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象作用域鏈中的下一個(gè)對(duì)象來自于外部環(huán)境,而在下一個(gè)變量對(duì)象則來自下一個(gè)外部環(huán)境,一直到全局執(zhí)行環(huán)境全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈上的最后一個(gè)對(duì)象遍歷數(shù)組的方式
1.for循環(huán) 使用臨時(shí)變量,將長度緩存起來,避免重復(fù)獲取數(shù)組長度,當(dāng)數(shù)組較大時(shí)優(yōu)化效果才會(huì)比較明顯。2.foreach循環(huán) 遍歷數(shù)組中的每一項(xiàng),沒有返回值,對(duì)原數(shù)組沒有影響,不支持IE。 有一些局限,不能continue跳過或者break終止循環(huán)3.map循環(huán) 有返回值,可以return出來 map的回調(diào)函數(shù)中支持return返回值 并不影響原來的數(shù)組,return的是新數(shù)組4.for of遍歷 可以正確響應(yīng)break、continue和return語句5.filter遍歷 不會(huì)改變?cè)紨?shù)組,返回新數(shù)組6.every遍歷 every()是對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)每一項(xiàng)返回true,則返回true。7.some遍歷 some()是對(duì)數(shù)組中每一項(xiàng)運(yùn)行指定函數(shù),如果該函數(shù)對(duì)任一項(xiàng)返回true,則返回true。8.reduce reduce()方法接收一個(gè)函數(shù)作為累加器(accumulator),數(shù)組中的每個(gè)值(從左到右)開始縮減,最終為一個(gè)值。9.reduceRight reduceRight()方法的功能和reduce()功能是一樣的, 不同的是reduceRight()從數(shù)組的末尾向前將數(shù)組中的數(shù)組項(xiàng)做累加。10.find find()方法返回?cái)?shù)組中符合測試函數(shù)條件的第一個(gè)元素。否則返回undefined 11.findIndex 對(duì)于數(shù)組中的每個(gè)元素,findIndex方法都會(huì)調(diào)用一次回調(diào)函數(shù)(采用升序索引順序),直到有元素返回 true。 只要有一個(gè)元素返回 true,findIndex立即返回該返回 true 的元素的索引值。 如果數(shù)組中沒有任何元素返回 true,則 findIndex 返回 -1。 findIndex 不會(huì)改變數(shù)組對(duì)象。12.keys,values,entries ES6 提供三個(gè)新的方法 —— entries(),keys()和values() —— 用于遍歷數(shù)組。 它們都返回一個(gè)遍歷器對(duì)象,可以用for...of循環(huán)進(jìn)行遍歷, 唯一的區(qū)別是keys()是對(duì)鍵名的遍歷、values()是對(duì)鍵值的遍歷,entries()是對(duì)鍵值對(duì)的遍歷數(shù)據(jù)分頁
前端的話,定義一個(gè)新的數(shù)組for循環(huán)判斷,有個(gè)公式,計(jì)算起始頁和終止頁的。 符合條件push僅數(shù)組中,后端就是用limt判斷數(shù)組排序
1. 普通數(shù)組排序 js中用方法sort()為數(shù)組排序。sort()方法有一個(gè)可選參數(shù),是用來確定元素順序的函數(shù)。如果這個(gè)參數(shù)被省略,那么數(shù)組中的元素將按照ASCII字符順序進(jìn)行排序。 2. 冒泡排序 (1)比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換他們兩個(gè)位置。 (2)對(duì)每一對(duì)相鄰元素作同樣的工作,從開始第一對(duì)到結(jié)尾的最后一對(duì)。在這一點(diǎn),最后的元素應(yīng)該會(huì)是最大的數(shù)。 (3)針對(duì)所有的元素重復(fù)以上的步驟,除了最后一個(gè)。 (4)持續(xù)每次對(duì)越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對(duì)數(shù)字需要比較。 3. 快速排序:遞歸思想,兩邊快速的排序,冒泡排序的改進(jìn) (1)選擇數(shù)組中間數(shù)作為基數(shù),并從數(shù)組中取出此基數(shù); (2)準(zhǔn)備兩個(gè)數(shù)組容器,遍歷數(shù)組,逐個(gè)與基數(shù)比對(duì),較小的放左邊容器,較大的放右邊容器; (3)進(jìn)行相同的操作,直到數(shù)組中只有一個(gè)元素時(shí),返回該數(shù)組。 4. 插入排序 (1)從第一個(gè)元素開始,該元素可以認(rèn)為已經(jīng)被排序 (2)取出下一個(gè)元素,在已經(jīng)排序的元素序列中掃描 (3)如果該元素(已排序)大于新元素,將該元素移到下一位置 (4)重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置 (5)將新元素插入到下一位置中 (6)重復(fù)步驟2 5. 選擇排序 (1)在未排序序列中找到最小(大)元素 (2)并存放到排序序列的起始位置 (3)然后,再從剩余未排序元素中繼續(xù)尋找最小(大)元素 (4)然后放到已排序序列的末尾。 (5)以此類推數(shù)組合并
1、concatjs的Array對(duì)象提供了一個(gè)叫concat()方法,連接兩個(gè)或更多的數(shù)組,并返回結(jié)果。var c = a.concat(b); //c=[1,2,3,4,5,6];這里有一個(gè)問題,concat方法連接a、b兩個(gè)數(shù)組后,a、b兩個(gè)數(shù)組的數(shù)據(jù)不變,同時(shí)會(huì)返回一個(gè)新的數(shù)組。這樣當(dāng)我們需要進(jìn)行多次的數(shù)組合并時(shí),會(huì)造成很大的內(nèi)存浪費(fèi),如果是數(shù)據(jù)量比較小的時(shí)候,還可以勉強(qiáng)用,如果數(shù)據(jù)量大的時(shí)候,這個(gè)就不妥了,所以這個(gè)方法肯定不是最好的。2、for循環(huán) 大概的思路是:遍歷其中一個(gè)數(shù)組,把該數(shù)組中的所有元素依次添加到另外一個(gè)數(shù)組中。直接上代碼:for(var i in b) { a.push ( b[i] );}3、apply函數(shù)的apply方法有一個(gè)特性,那就是func.apply(obj,argv),argv是一個(gè)數(shù)組。a.push.apply(a,b);調(diào)用a.push這個(gè)函數(shù)實(shí)例的apply方法,同時(shí)把,b當(dāng)作參數(shù)傳入,這樣a.push這個(gè)方法就會(huì)遍歷b數(shù)組的所有元素,達(dá)到合并的效果。這里可能有點(diǎn)繞,我們可以把b看成[4,5,6],變成這樣:a.push.apply(a,[4,5,6]);然后上面的操作就等同于:a.push(4,5,6);這樣就很清楚了!數(shù)組方法
push,在數(shù)組末尾添加一位或多位元素 pop,刪除數(shù)組最后一位元素 unshift,在數(shù)組的開頭添加一位或多位元素 shift,刪除數(shù)組的第一位元素 join,將數(shù)組轉(zhuǎn)換為字符串 reserve,反轉(zhuǎn)數(shù)組元素的順序 sort,對(duì)數(shù)組進(jìn)行排序 concat,連接兩個(gè)或多個(gè)數(shù)組 splice,添加或刪除數(shù)組中的元素 slice,從已有的數(shù)組中返回選定的元素 indexOf、lastIndexOf,查找數(shù)組中的元素 forEach,對(duì)數(shù)組進(jìn)行遍歷循環(huán),對(duì)數(shù)組中每一項(xiàng)運(yùn)行指定的函數(shù) map,迭代數(shù)組 filter,對(duì)數(shù)組中的元素進(jìn)行指定的檢查返回符合條件的元素放入一個(gè)新數(shù)組中 every,測試所有元素是否都符合指定條件 some,測試某些元素是否符合指定條件 reduce,接收一個(gè)函數(shù)作為累加器,數(shù)組中的每個(gè)值開始縮減,最終計(jì)算為一個(gè)值 toString,將數(shù)組轉(zhuǎn)換為字符串數(shù)組去重
使用ES6 Setvar arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];arr = Array.from(new Set(arr)); [...new Set(arr)]console.log(arr);//[1, 4, 2, 3, 6]使用indexOfvar arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];var newArr = [];arr.forEach((item) => {newArr.indexOf(item) === -1 ? newArr.push(item) : "";});console.log(newArr);//[1, 4, 2, 3, 6]使用lastIndexOfvar arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];var newArr = [];arr.forEach((item) => {newArr.lastIndexOf(item) === -1 ? newArr.push(item) : "";});console.log(newArr);//[1, 4, 2, 3, 6]使用雙重for循環(huán)加splice方法var arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];for (var i = 0; i < arr.length; i++) {for (var j = i + 1; j < arr.length; j++) {if (arr[i] == arr[j]) {arr.splice(j,1);j--;}}}console.log(arr);//[1, 4, 2, 3, 6]使用forEach和includes方法var arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];var newArr = [];arr.forEach((item) => {newArr.includes(item) ? "" : newArr.push(item);});console.log(newArr);//[1, 4, 2, 3, 6]使用fliter和includes方法var arr = [1, 1, 4, 2, 2, 3, 3, 3, 6, 6, 6];var newArr = [];arr.filter((item) => {newArr.includes(item) ? "" : newArr.push(item);});console.log(newArr);//[1, 4, 2, 3, 6]for…of 原理
for...of 是ES6引入用來遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一方法。這里的所有數(shù)據(jù)結(jié)構(gòu)只指具有iterator接口的數(shù)據(jù)。 一個(gè)數(shù)據(jù)只要部署了 Symbol.iterator,就具有了 iterator接口,就可以使用 for...of 循環(huán)遍歷它的成員。 也就是說,for...of循環(huán)內(nèi)部調(diào)用的數(shù)據(jù)結(jié)構(gòu)為Symbol.iterator方法。 部署在 Symbol.iterator 屬性,或者說,一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有 Symbol.iterator 屬性,就認(rèn)為是"可遍歷的"。Iterator(伊特瑞特):遍歷器(Iterator)就是這樣一種機(jī)制。它是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)。通俗點(diǎn)理解就是為了解決不同數(shù)據(jù)結(jié)構(gòu)遍歷的問題,引入了Iterator.Iterator的特點(diǎn):各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的、簡便的訪問接口使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi)原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下。ArrayMapSetString:字符串是一個(gè)類似數(shù)組的對(duì)象,也原生具有 Iterator 接口。TypedArray:通俗理解:ArrayBuffer是一片內(nèi)存空間,不能直接引用里面的數(shù)據(jù),可以通過TypedArray類型引用,用戶只能通過TypedArray使用這片內(nèi)存,不能直接通過ArrayBuffer使用這片內(nèi)存函數(shù)的 arguments 對(duì)象NodeList 對(duì)象除了原生具備Iterator 接口的數(shù)據(jù)之外,其他數(shù)據(jù)結(jié)構(gòu)(主要是對(duì)象)的 Iterator 接口, 都需要自己在Symbol.iterator屬性上面部署,這樣才會(huì)被for...of循環(huán)遍歷。對(duì)象(Object)之所以沒有默認(rèn)部署 Iterator 接口,是因?yàn)閷?duì)象的哪個(gè)屬性先遍歷,哪個(gè)屬性后遍歷是不確定的,需要開發(fā)者手動(dòng)指定。本質(zhì)上,遍歷器是一種線性處理,對(duì)于任何非線性的數(shù)據(jù)結(jié)構(gòu),部署遍歷器接口,就等于部署一種線性轉(zhuǎn)換。不過,嚴(yán)格地說,對(duì)象部署遍歷器接口并不是很必要,因?yàn)檫@時(shí)對(duì)象實(shí)際上被當(dāng)作 Map 結(jié)構(gòu)使用,ES5 沒有 Map 結(jié)構(gòu),而 ES6 原生提供了。一個(gè)對(duì)象如果要具備可被for...of循環(huán)調(diào)用的 Iterator 接口,就必須在Symbol.iterator的屬性上部署遍歷器生成方法(原型鏈上的對(duì)象具有該方法也可)。遍歷對(duì)象的方式
第一種: for...in第二種: 1)Object.keys(obj) 2)Object.values(obj) 參數(shù):obj:要返回其枚舉自身屬性的對(duì)象 返回值:一個(gè)表示給定對(duì)象的所有可枚舉屬性的字符串?dāng)?shù)組。第三種: 使用Object.getOwnPropertyNames(obj) 返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性(包含不可枚舉屬性) 遍歷可以獲取key和valuemap與filter和forEach的區(qū)別
map 與 filter 區(qū)別:相同點(diǎn):filter 和 map 都是對(duì)數(shù)組的操作,均返回一個(gè)新的數(shù)組不同點(diǎn):filter是滿足條件的留下,是對(duì)原數(shù)組的過濾;map則是對(duì)原數(shù)組的加工,映射成一對(duì)一映射的新數(shù)組map 與 forEach 區(qū)別:map()會(huì)分配內(nèi)存空間存儲(chǔ)新數(shù)組并返回,forEach()不會(huì)返回?cái)?shù)據(jù)(undefined)。forEach()允許callback更改原始數(shù)組的元素。map()返回新的數(shù)組。面向?qū)ο缶幊?/h1>
面向?qū)ο缶幊?
將所需要做的功能抽象成一個(gè)“對(duì)象”,然后一遍遍地調(diào)用這個(gè)對(duì)象來完成你想要的功能。面向?qū)ο蟮娜筇卣?
1.封裝
我們平時(shí)所用的方法和類都是一種封裝,當(dāng)我們?cè)陧?xiàng)目開發(fā)中,遇到一段功能的代碼在好多地方重復(fù)使用的時(shí)候,我們可以把他單獨(dú)封裝成一個(gè)功能的方法,這樣在我們需要使用的地方直接調(diào)用就可以了。2.繼承
繼承在我們的項(xiàng)目開發(fā)中主要使用為子類繼承父類,繼承會(huì)繼承父類的實(shí)例屬性和實(shí)例方法,并不會(huì)繼承靜態(tài)屬性和靜態(tài)方法,并且靜態(tài)方法只能通過類名去調(diào)用。3.多態(tài)
多態(tài)的具體表現(xiàn)為方法重載和方法重寫:
方法重載:
重載是指不同的函數(shù)使用相同的函數(shù)名,但是函數(shù)的參數(shù)個(gè)數(shù)或類型不同。調(diào)用的時(shí)候根據(jù)函數(shù)的參數(shù)來區(qū)別不同的函數(shù)
方法重寫:
重寫(也叫覆蓋)是指在派生類中重新對(duì)基類中的虛函數(shù)(注意是虛函數(shù))重新實(shí)現(xiàn)。即函數(shù)名和參數(shù)都一樣,只是函數(shù)的實(shí)現(xiàn)體不一樣三大特征的優(yōu)點(diǎn):
封裝:
封裝的優(yōu)勢(shì)在于定義只可以在類內(nèi)部進(jìn)行對(duì)屬性的操作,外部無法對(duì)這些屬性指手畫腳,要想修改,也只能通過你定義的封裝方法;繼承:
繼承減少了代碼的冗余,省略了很多重復(fù)代碼,開發(fā)者可以從父類底層定義所有子類必須有的屬性和方法,以達(dá)到耦合的目的;多態(tài):
多態(tài)實(shí)現(xiàn)了方法的個(gè)性化,不同的子類根據(jù)具體狀況可以實(shí)現(xiàn)不同的方法,光有父類定義的方法不夠靈活,遇見特殊狀況就捉襟見肘了
window.onload與document.ready的區(qū)別
1.執(zhí)行時(shí)間window.onload必須等到頁面內(nèi)包括圖片的所有元素加載完畢后才能執(zhí)行。 $(document).ready()是DOM結(jié)構(gòu)繪制完畢后就執(zhí)行,不必等到加載完畢。2.編寫個(gè)數(shù)不同window.onload不能同時(shí)編寫多個(gè),如果有多個(gè)window.onload方法,只會(huì)執(zhí)行一個(gè) $(document).ready()可以同時(shí)編寫多個(gè),并且都可以得到執(zhí)行3.簡化寫法window.onload沒有簡化寫法 $(document).ready(function(){})可以簡寫成$(function(){});
this
this代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,
隨著函數(shù)使用場合的不同,this的值會(huì)發(fā)生變化。指向:
1.在方法中,this 表示該方法所屬的對(duì)象。
2.如果單獨(dú)使用,this 表示全局對(duì)象。
3.函數(shù)中,this 表示全局對(duì)象。
4.嚴(yán)格模式下,this 是未定義的(undefined)。
5.在事件中,this 表示接收事件的元素。
6.類似 call() 和 apply() 方法可以將 this 引用到任何對(duì)象。
7.箭頭函數(shù)本身是沒有this和arguments的,引用的this實(shí)際上是調(diào)用的是定義時(shí)的上一層作用域的this。
<!DOCTYPE>
<!DOCTYPE> 聲明位于文檔中的最前面的位置,處于 <html> 標(biāo)簽之前。<!DOCTYPE> 聲明不是一個(gè) HTML 標(biāo)簽;它是用來告知 Web 瀏覽器頁面使用了哪種 HTML 版本。在 HTML 4.01 中,<!DOCTYPE> 聲明需引用 DTD (文檔類型聲明),
因?yàn)?HTML 4.01 是基于 SGML (Standard Generalized Markup Language 標(biāo)準(zhǔn)通用標(biāo)記語言)。
DTD 指定了標(biāo)記語言的規(guī)則,確保了瀏覽器能夠正確的渲染內(nèi)容。HTML5 不是基于 SGML,因此不要求引用 DTD。給您 HTML 文檔添加 <!DOCTYPE> 聲明,確保瀏覽器能夠預(yù)先知道文檔類型。
CSS position屬性
absolute:生成絕對(duì)定位的元素,相對(duì)于 static 定位以外的第一個(gè)父元素進(jìn)行定位。
fixed :生成固定定位的元素,相對(duì)于瀏覽器窗口進(jìn)行定位。
relative:生成相對(duì)定位的元素,相對(duì)于其正常位置進(jìn)行定位。
static :默認(rèn)值。沒有定位。
sticky :粘性定位,該定位基于用戶滾動(dòng)的位置。
inherit :規(guī)定應(yīng)該從父元素繼承 position 屬性的值。
js的解構(gòu)
解構(gòu)定義:允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值。
解構(gòu)必須滿足的條件:(模式匹配),只要等號(hào)兩邊的模式相同,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值。
主要介紹2種解構(gòu)常用的類型:數(shù)組解構(gòu)和對(duì)象解構(gòu)。數(shù)組解構(gòu):1.數(shù)組中的變量個(gè)數(shù)比賦值的數(shù)組中個(gè)數(shù)少的解構(gòu):2.數(shù)組中的變量個(gè)數(shù)比賦值的數(shù)組中個(gè)數(shù)多的解構(gòu):3.數(shù)組中的變量中有空字符的解構(gòu):上面的3種數(shù)組解構(gòu),賦值的數(shù)組的數(shù)值按位賦值給另外一方數(shù)組中的變量4.數(shù)組中的變量中有不定參數(shù)(有些時(shí)候也叫擴(kuò)展運(yùn)算符)的解構(gòu):需要注意的是不定參數(shù)必須放最后。5.數(shù)組中的變量中有默認(rèn)值的解構(gòu):如果賦值的數(shù)組個(gè)數(shù)沒有另外一方數(shù)組變量個(gè)數(shù)多,并且變量數(shù)組有默認(rèn),沒有進(jìn)行賦值用默認(rèn),進(jìn)行賦值用賦值的對(duì)象的解構(gòu):兩方也需要相同類型的括號(hào),對(duì)象結(jié)構(gòu)使用大括號(hào){}
普通對(duì)象解構(gòu):對(duì)象跟數(shù)值解構(gòu)不同的一點(diǎn),對(duì)象解構(gòu)不是按位去賦值,是根據(jù)鍵名(屬性名) 來進(jìn)行賦值
有默認(rèn)值的對(duì)象解構(gòu)跟數(shù)組的默認(rèn)值差不多,有賦值就用賦值的,沒有就用默認(rèn)值
有不定參數(shù)的對(duì)象解構(gòu)跟數(shù)組的不定參數(shù)差不多,不定參數(shù)放在最后,不定參數(shù)創(chuàng)建一個(gè)對(duì)象接受的剩下的鍵名鍵值(屬性名屬性值)
有嵌套的對(duì)象解構(gòu)主要注意嵌套層次是不是賦值一方對(duì)象的嵌套層次相同。
js實(shí)現(xiàn)輪播圖思路
1.圖片移動(dòng)實(shí)現(xiàn)原理:
利用浮動(dòng)將所有所有照片依次排成一行,給這一長串圖片添加一個(gè)父級(jí)的遮罩,每次只顯示一張圖,其余的都隱藏起來。對(duì)圖片添加絕對(duì)定位,通過控制left屬性,實(shí)現(xiàn)照片的移動(dòng)。2.圖片移動(dòng)動(dòng)畫原理:
從a位置移動(dòng)到b位置,需要先計(jì)算兩點(diǎn)之間的差值,通過差值和時(shí)間間隔,計(jì)算出每次移動(dòng)的步長,通過添加定時(shí)器,每次移動(dòng)相同的步長,實(shí)現(xiàn)動(dòng)畫效果。3.圖片定位停止原理:
每一張照片都有相同的寬度,每張照片都有一個(gè)絕對(duì)的定位數(shù)值,通過檢測定每次移動(dòng)后,照片當(dāng)前位置和需要到達(dá)位置之間的距離是否小于步長,如果小于,說明已經(jīng)移動(dòng)到位,可以將定時(shí)器清除,來停止動(dòng)畫。4圖片切換原理:
在全局設(shè)置一個(gè)變量,記錄當(dāng)前圖片的位置,每次切換或跳轉(zhuǎn)時(shí),只需要將數(shù)值修改,并調(diào)用圖片頁數(shù)轉(zhuǎn)像素位置函數(shù),再調(diào)用像素運(yùn)動(dòng)函數(shù)即可。5.自動(dòng)輪播原理:
設(shè)置定時(shí)器,一定時(shí)間間隔后,將照片標(biāo)記加1,然后開始切換。6.左右點(diǎn)擊切換原理:
修改當(dāng)前位置標(biāo)記,開始切換。這里需要注意與自動(dòng)輪播之間的沖突。當(dāng)點(diǎn)擊事件觸發(fā)之后,停止自動(dòng)輪播計(jì)時(shí)器,開始切換。當(dāng)動(dòng)畫結(jié)束后再次添加自動(dòng)輪播計(jì)時(shí)器。7.無縫銜接原理:
需要無縫銜接,難度在于最后一頁向后翻到第一頁,和第一頁向前翻到最后一頁。由于圖片的基本移動(dòng)原理。要想實(shí)現(xiàn)無縫銜接,兩張圖片就必須緊貼在一起。所以在第一張的前面需要添加最后一張,最后一張的后面需要添加第一張。首先判斷圖片的位置,是否移動(dòng)到位。當(dāng)滿足當(dāng)前位置,與預(yù)定位置之間的距離小于一步時(shí),認(rèn)定為移動(dòng)到位,并把圖片直接定位到預(yù)定位置。然后判斷,圖片的位置是否需要跳轉(zhuǎn)。
ps:這里一定要在圖片運(yùn)動(dòng)函數(shù)結(jié)束后,在進(jìn)行跳轉(zhuǎn)。8.預(yù)防鬼畜原理:
始終保證輪播圖的運(yùn)動(dòng)動(dòng)畫只有一個(gè),從底層杜絕鬼畜。需要在每次動(dòng)畫開始之前,嘗試停止動(dòng)畫定時(shí)器,然后開始為新的動(dòng)畫添加定時(shí)器。輪播圖鬼畜的本質(zhì)原因就是,同一時(shí)間多個(gè)定時(shí)器添加在圖片上,這些定時(shí)器直接相互沖突,造成圖片的抖動(dòng)。
解決方法:每次執(zhí)行運(yùn)動(dòng)函數(shù)之前,先嘗試清除一下,上一個(gè)輪播圖的定時(shí)器。確保同時(shí)觸發(fā)運(yùn)動(dòng)函數(shù)時(shí),只有一個(gè)定時(shí)器在工作。9.預(yù)防暴力點(diǎn)擊原理:
如果用戶快速點(diǎn)擊觸發(fā)事件,會(huì)在短時(shí)間內(nèi)多次調(diào)用切換函數(shù),雖然動(dòng)畫函數(shù)可以保證,不會(huì)發(fā)生鬼畜,但在照片從最后一張到第一張的切換過程,不會(huì)按照正常的輪播,而是實(shí)現(xiàn)了跳轉(zhuǎn)。所以需要通過添加口令的方式來,限制用戶的點(diǎn)擊。當(dāng)用戶點(diǎn)擊完成后,口令銷毀,動(dòng)畫結(jié)束后恢復(fù)口令。10.小圓點(diǎn)的位置顯示原理:
每次觸發(fā)動(dòng)畫時(shí),通過全局變量標(biāo)記,獲取當(dāng)前頁數(shù),操作清除所有小圓點(diǎn),然后指定一頁添加樣式。11.點(diǎn)擊觸發(fā)跳轉(zhuǎn)的原理:
類似于左右點(diǎn)擊觸發(fā),只是這是將全局頁面標(biāo)記,直接修改,后執(zhí)行動(dòng)畫。需要避免與自動(dòng)輪播定時(shí)器的沖突。
js數(shù)組和對(duì)象的擴(kuò)展
1.Array.from()方法用于將對(duì)象轉(zhuǎn)為真正的數(shù)組(類數(shù)組轉(zhuǎn)數(shù)組)
2.Array.of()方法用于將一組值,轉(zhuǎn)換為數(shù)組。console.log(Array.of(1,2,3,4,4,50));//[1, 2, 3, 4, 4, 50]
3.Object.assign(目標(biāo)對(duì)象,對(duì)象1,對(duì)象2)用于對(duì)象的合并,將源對(duì)象的所有可枚舉屬性,復(fù)制到目標(biāo)對(duì)象。(淺拷貝)
js提升
一、提升(Hosting)
簡單說就是在js代碼執(zhí)行前引擎會(huì)先進(jìn)行預(yù)編譯,預(yù)編譯期間會(huì)將變量聲明與函數(shù)聲明提升至其對(duì)應(yīng)作用域的最頂端。二、變量提升
在ES6之前,JavaScript沒有塊級(jí)作用域(一對(duì)花括號(hào){}即為一個(gè)塊級(jí)作用域),只有全局作用域和函數(shù)作用域。
變量提升即將變量聲明提升到它所在作用域的最開始的部分。
變量聲明的提升是以變量所處的第一層詞法作用域?yàn)椤皢挝弧钡?#xff0c;即全局作用域中聲明的變量會(huì)提升至全局最頂層,函數(shù)內(nèi)聲明的三、函數(shù)提升
即函數(shù)提升只會(huì)提升函數(shù)聲明,而不會(huì)提升函數(shù)表達(dá)式。四、為什么會(huì)有提升?
函數(shù)提升就是為了解決相互遞歸的問題,大體上可以解決像ML語言這樣自下而上的順序問題。
大概是說,變量提升是人為實(shí)現(xiàn)的問題,而函數(shù)提升在當(dāng)初設(shè)計(jì)時(shí)是有目的的。
比較redux和vuex的區(qū)別
redux和vuex的區(qū)別1)vuex是redux的基礎(chǔ)上進(jìn)行改變,對(duì)倉庫的管理更加明確2)使用mutation來替換redux中的reducer3)vuex有自動(dòng)渲染的功能,所以不需要更新redux和flux的區(qū)別1)redux是flux中的一個(gè)實(shí)現(xiàn)2))在redux中我們只能定義一個(gè)store,在flux中我們可以定義多個(gè)3)在redux中,store和dispatch都放到了store,結(jié)構(gòu)更加清晰4)在redux中本身就內(nèi)置State對(duì)象,對(duì)倉庫的管理更加明確
CSS display 屬性
| block | 此元素將顯示為塊級(jí)元素,此元素前后會(huì)帶有換行符。 | |
| inline | 默認(rèn)。此元素會(huì)被顯示為內(nèi)聯(lián)元素,元素前后沒有換行符。 | |
| inline-block | 行內(nèi)塊元素。(CSS2.1 新增的值) | |
| list-item | 此元素會(huì)作為列表顯示。 | |
| run-in | 此元素會(huì)根據(jù)上下文作為塊級(jí)元素或內(nèi)聯(lián)元素顯示。 | |
| compact | CSS 中有值 compact,不過由于缺乏廣泛支持,已經(jīng)從 CSS2.1 中刪除。 | |
| marker | CSS 中有值 marker,不過由于缺乏廣泛支持,已經(jīng)從 CSS2.1 中刪除。 | |
| table | 此元素會(huì)作為塊級(jí)表格來顯示(類似 ),表格前后帶有換行符。 | |
| inline-table | 此元素會(huì)作為內(nèi)聯(lián)表格來顯示(類似 ),表格前后沒有換行符。 | |
| table-row-group | 此元素會(huì)作為一個(gè)或多個(gè)行的分組來顯示(類似 | |
| table-header-group | 此元素會(huì)作為一個(gè)或多個(gè)行的分組來顯示(類似 | |
| table-footer-group | 此元素會(huì)作為一個(gè)或多個(gè)行的分組來顯示(類似 | |
| table-row | 此元素會(huì)作為一個(gè)表格行顯示(類似 | |
| table-column-group | 此元素會(huì)作為一個(gè)或多個(gè)列的分組來顯示(類似 | |
| table-column | 此元素會(huì)作為一個(gè)單元格列顯示(類似 | |
| table-cell | 此元素會(huì)作為一個(gè)表格單元格顯示(類似 | 和 | )
| table-caption | 此元素會(huì)作為一個(gè)表格標(biāo)題顯示(類似 | |
| inherit | 規(guī)定應(yīng)該從父元素繼承 display 屬性的值。 |
CSS選擇符
CSS選擇符id選擇器(#myid)類選擇器(.myclassname)標(biāo)簽選擇器(div)相鄰選擇器(h1+p)子選擇器(ul>li)后代選擇器(li a)群組選擇器(div,p{})通配符選擇器(*)屬性選擇器(a[title=""])偽類選擇器(a:hover{}或者li:nth-child{})CSS中l(wèi)ink和@import的區(qū)別
link屬于HTML標(biāo)簽,@import是CSS提供的頁面被加載時(shí),link引用的css文件會(huì)同時(shí)被加載,而@import引用的css文件要等到頁面被加載完畢再加載import只在IE5以上才能識(shí)別,link是HTML標(biāo)簽,無兼容問題link 引入樣式的權(quán)重大于@import 的引用CSS中display:none、visibility:hidden和opacity:0;的區(qū)別
display:none;隱藏對(duì)應(yīng)的元素,在文檔布局中不再給它分配空間,它各邊的元素會(huì)合攏。visibility:hidden;隱藏對(duì)應(yīng)的元素,但在文檔布局中仍保留原來的空間。opacity:0;內(nèi)容不可見,占據(jù)空間。CSS中rgba()和opacity的透明效果區(qū)別
rgba()和 opacity 都能實(shí)現(xiàn)透明效果,但最大的不同是 opacity 作用于元素,以及元素內(nèi)的所有內(nèi)容的透明度;rgba()只作用于元素的顏色或其背景色(設(shè)置 rgba 透明的元素的子元素不會(huì)繼承透明效果)。CSS的外邊距重疊
在 CSS 當(dāng)中,相鄰的兩個(gè)盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個(gè)單獨(dú)的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距。折疊結(jié)果遵循下列計(jì)算規(guī)則如下兩個(gè)相鄰的外邊距都是正數(shù)時(shí),折疊結(jié)果是它們兩者之間較大的值。兩個(gè)相鄰的外邊距都是負(fù)數(shù)時(shí),折疊結(jié)果是兩者絕對(duì)值的較大值。兩個(gè)外邊距一正一負(fù)時(shí),折疊結(jié)果是兩者之和。CSS清除浮動(dòng)
清除浮動(dòng)主要是為了解決父元素因?yàn)樽釉馗?dòng)引起的內(nèi)部高度為0的問題。 常見清除浮動(dòng)的方法額外標(biāo)簽法。在最后浮動(dòng)元素后加一個(gè)標(biāo)簽,設(shè)置clear:both;給父級(jí)元素設(shè)置高度給父級(jí)元素添加浮動(dòng)給父級(jí)元素設(shè)置overflow屬性為hidden或者auto使用after偽元素清除.clearfix:after {/*偽元素是行內(nèi)元素 正常瀏覽器清除浮動(dòng)方法*/content: "";display: block;height: 0;clear: both;visibility: hidden;}/*ie6清除浮動(dòng)的方式 *號(hào)只有IE6-IE7執(zhí)行,其他瀏覽器不執(zhí)行*/.clearfix {*zoom: 1;}使用after和before雙偽元素清除.clearfix:before,.clearfix:after {content: "";display: block;clear: both;}.clearfix {zoom: 1;}CSS3transition過渡和animation動(dòng)畫的區(qū)別
animation屬性類似于transition,他們都是隨著時(shí)間改變?cè)氐膶傩灾?#xff0c;其主要區(qū)別在于: transition需要觸發(fā)一個(gè)事件才會(huì)隨著時(shí)間改變其CSS屬性; animation在不需要觸發(fā)任何事件的情況下,也可以顯式的隨時(shí)間變化來改變?cè)谻SS屬性,達(dá)到一種動(dòng)畫的效果1)動(dòng)畫不需要事件觸發(fā),過渡需要。 2)過渡只有一組(兩個(gè):開始-結(jié)束) 關(guān)鍵幀,動(dòng)畫可以設(shè)置多個(gè)。前后端開發(fā)中數(shù)據(jù)是怎么交互的
web后端和前端是怎么連接的?網(wǎng)站數(shù)據(jù)處理主要分為三層。 第一層,表示層,這部分可以用HTML代碼,CSS/Javascript代碼來實(shí)現(xiàn)等。通過前端代碼可以實(shí)現(xiàn)網(wǎng)頁的布局和設(shè)計(jì)。這層又可以稱為顯示層。也就是你用瀏覽器打開能看到的網(wǎng)頁。 第二層,是業(yè)務(wù)層,這層是負(fù)責(zé)處理數(shù)據(jù)的。常用的代碼語言有PHP,JSP,Java等。通過這些后臺(tái)處理語言的算法來處理前臺(tái)傳回的數(shù)據(jù)。必要的時(shí)候進(jìn)行操作數(shù)據(jù)庫,然后把結(jié)果返回給前端網(wǎng)頁。 第三層,是數(shù)據(jù)層,這個(gè)就是數(shù)據(jù)庫,用來存儲(chǔ)數(shù)據(jù)的。通過業(yè)務(wù)層的操作可以實(shí)現(xiàn)增刪改數(shù)據(jù)庫的操作。在網(wǎng)頁上填一個(gè)表格然后提交會(huì)有以下幾種數(shù)據(jù)傳輸經(jīng)過: ①你接觸到的是這個(gè)網(wǎng)頁是屬于表示層,這個(gè)網(wǎng)頁一般由HTML標(biāo)簽結(jié)合CSS/JAVASCRIPT來實(shí)現(xiàn)的。這時(shí)候你要先填入數(shù)據(jù)。 ②然后你按提交觸發(fā)后臺(tái)處理機(jī)制,這時(shí)候數(shù)據(jù)會(huì)傳到后臺(tái)的代碼進(jìn)行處理。這部分代碼根據(jù)不同網(wǎng)站可以使PHP,JSP,JAVA等。代碼根據(jù)程序員預(yù)設(shè)的算法將收到的數(shù)據(jù)進(jìn)行處理之后會(huì)相應(yīng)的對(duì)數(shù)據(jù)庫進(jìn)行操作,存儲(chǔ)數(shù)據(jù)等。 ③成功操作完數(shù)據(jù)庫之后,業(yè)務(wù)層的代碼會(huì)再向表示層也就是顯示器端傳回一個(gè)指令通知你表格填寫成功從前端向后臺(tái)傳遞參數(shù)方法一、通過表單傳遞參數(shù) 1.前端部分,在前端jsp頁面設(shè)置form表單,確定需要傳遞的參數(shù)name讓用戶輸入,通過點(diǎn)擊按鈕后submit()提交到后臺(tái) 2.后臺(tái)對(duì)前端請(qǐng)求的反應(yīng),接收數(shù)據(jù),處理數(shù)據(jù)以及返回?cái)?shù)據(jù)。二.通過ajax傳遞參數(shù)(有post和get寫法) 1.ajax是如何將前端數(shù)據(jù)傳到后臺(tái)的type: "POST",//type是ajax的方法url : "<%=path%>/resource/usermenus",//參數(shù)url,要把參數(shù)傳到什么地方data : {parentid:parentid,parentpath:parentpath},//傳遞什么數(shù)據(jù)success : function(data){//sucess表示,當(dāng)數(shù)據(jù)返回成功后要怎么做,返回的數(shù)據(jù)存儲(chǔ)在data 2.后臺(tái)對(duì)前端請(qǐng)求的反應(yīng),接收數(shù)據(jù) 3.前端接收到后端返回的數(shù)據(jù)進(jìn)行處理的cookie的理解
cookie又叫會(huì)話跟蹤技術(shù),是由web服務(wù)器保存在用戶瀏覽器上的小文本文件,它可以記錄用戶ID、密碼、瀏覽過的網(wǎng)頁、停留的時(shí)間等信息。當(dāng)用戶再次來到該網(wǎng)站時(shí),網(wǎng)站通過讀取cookie,得知用戶相關(guān)信息,就可以做出相應(yīng)的動(dòng)作,如在頁面顯示歡迎用戶標(biāo)語,或者讓用戶不用輸入ID、密碼就直接登錄等等。如果用戶清理了cookie,那么用戶曾登錄過的網(wǎng)站信息就沒有了。優(yōu)點(diǎn)極高的擴(kuò)展性和可用性通過良好的編程,可以控制保存在cookie中的session對(duì)象的大小通過加密技術(shù)和安全傳輸技術(shù),減少cookie被破解的可能只在cookie中存放不敏感數(shù)據(jù),即使被盜也不會(huì)有重大的損失控制cookie的生命周期,使之不會(huì)永久有效。偷盜者可能拿到一個(gè)過期的cookie缺點(diǎn)cookie有數(shù)量和長度的限制。每個(gè)domain最多有20條cookie,長度不能超過4KB,否則會(huì)被裁掉。安全性問題。如果cookie被人攔截了,那個(gè)人就可以取得所有的session信息。即使加密也于事無補(bǔ),因?yàn)閿r截者不需要知道cookie的意義,他只需要原樣轉(zhuǎn)發(fā)就能達(dá)到目的。有些狀態(tài)不可能保存在客戶端。輸入網(wǎng)址到呈現(xiàn)網(wǎng)頁發(fā)生的過程
a.域名解析DNS解析,每一臺(tái)連上網(wǎng)計(jì)算機(jī)都有一個(gè)唯一標(biāo)識(shí)即它的IP地址,DNS解析就將輸入的網(wǎng)址解析成IP地址。 DNS解析是一個(gè)遞歸查詢的過程,例如要解析“www.baidu.com”時(shí),過程如下:在本地域名服務(wù)器中查詢IP地址,未找到域名;本地域名服務(wù)器會(huì)向根域名服務(wù)器發(fā)送請(qǐng)求,未找到域名;本地域名服務(wù)器向.com頂級(jí)域名服務(wù)器發(fā)送請(qǐng)求,未找到域名;本地域名服務(wù)器向.baidu.com域名服務(wù)器發(fā)送請(qǐng)求,找到該域名,將相應(yīng)的IP返回給本地域名服務(wù)器;b.發(fā)起TCP連接的三次握手HTTP協(xié)議是使用TCP協(xié)議作為其傳輸層協(xié)議的,在拿到服務(wù)器的IP地址后,客戶端瀏覽器會(huì)與服務(wù)器建立TCP連接,該過程包括三次握手:第一次握手:建立連接時(shí),客戶端向服務(wù)端發(fā)送請(qǐng)求報(bào)文(SYN)第二次握手:服務(wù)器收到請(qǐng)求報(bào)文后,如同意連接,則向客戶端發(fā)送確認(rèn)報(bào)文(SYN/ACK)第三次握手:客戶端收到服務(wù)器的確認(rèn)后,再次向服務(wù)器發(fā)送確認(rèn)報(bào)文,完成連接(ACK) 三次握手主要是為了防止已經(jīng)失效的請(qǐng)求報(bào)文字段發(fā)送給服務(wù)器,浪費(fèi)資源。c.建立TCP連接后瀏覽器發(fā)起HTTP請(qǐng)求瀏覽器構(gòu)建HTTP請(qǐng)求報(bào)文,并通過TCP協(xié)議傳送到服務(wù)器的指定端口。HTTP請(qǐng)求報(bào)文一共有三個(gè)部分:報(bào)文首部(請(qǐng)求行+各種首部字段+其他)空行(它的作用是通過一個(gè)空行,告訴服務(wù)器請(qǐng)求頭部到此為止。)報(bào)文主體(應(yīng)被發(fā)送的數(shù)據(jù))通常并不一定要有報(bào)文主體d.服務(wù)端響應(yīng)http請(qǐng)求,返回響應(yīng)報(bào)文 HTTP響應(yīng)報(bào)文由四部分組成:響應(yīng)行、響應(yīng)頭、空行、響應(yīng)體 響應(yīng)行響應(yīng)行一般由協(xié)議版本、狀態(tài)碼及其描述組成響應(yīng)頭響應(yīng)頭用于描述服務(wù)器的基本信息,以及數(shù)據(jù)的描述,服務(wù)器通過這些數(shù)據(jù)的描述信息,可以通知客戶端如何處理等一會(huì)兒它回送的數(shù)據(jù)。 常見的響應(yīng)頭字段含義:Allow:服務(wù)器支持哪些請(qǐng)求方法(如GET、POST等)。Content-Encoding:文檔的編碼(Encode)方法。只有在解碼之后才可以得到Content-Type頭指定的內(nèi)容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時(shí)間。Java的GZIPOutputStream可以很方便地進(jìn)行g(shù)zip壓縮,但只有Unix上的Netscape和Windows上的IE4、IE5才支持它。因此,Servlet應(yīng)該通過查看Accept-Encoding頭(即request.getHeader(“Accept- Encoding”))檢查瀏覽器是否支持gzip,為支持gzip的瀏覽器返回經(jīng)gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。Content-Length:表示內(nèi)容長度。只有當(dāng)瀏覽器使用持久HTTP連接時(shí)才需要這個(gè)數(shù)據(jù)。如果你想要利用持久連接的優(yōu)勢(shì),可以把輸出文檔寫入 ByteArrayOutputStram,完成后查看其大小,然后把該值放入Content-Length頭,最后通過byteArrayStream.writeTo(response.getOutputStream()發(fā)送內(nèi)容。Content- Type:表示后面的文檔屬于什么MIME類型。Servlet默認(rèn)為text/plain,但通常需要顯式地指定為text/html。由于經(jīng)常要設(shè)置 Content-Type,因此HttpServletResponse提供了一個(gè)專用的方法setContentType。Date:當(dāng)前的GMT時(shí)間,例如,Date:Mon,31Dec200104:25:57GMT。Date描述的時(shí)間表示世界標(biāo)準(zhǔn)時(shí),換算成本地時(shí)間,需要知道用戶所在的時(shí)區(qū)。你可以用setDateHeader來設(shè)置這個(gè)頭以避免轉(zhuǎn)換時(shí)間格式的麻煩。Expires:告訴瀏覽器把回送的資源緩存多長時(shí)間,-1或0則是不緩存。Last-Modified:文檔的最后改動(dòng)時(shí)間。客戶可以通過If-Modified-Since請(qǐng)求頭提供一個(gè)日期,該請(qǐng)求將被視為一個(gè)條件GET,只有改動(dòng)時(shí)間遲于指定時(shí)間的文檔才會(huì)返回,否則返回一個(gè)304(Not Modified)狀態(tài)。Last-Modified也可用setDateHeader方法來設(shè)置。Location:這個(gè)頭配合302狀態(tài)碼使用,用于重定向接收者到一個(gè)新URI地址。表示客戶應(yīng)當(dāng)?shù)侥睦锶ヌ崛∥臋n。Location通常不是直接設(shè)置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時(shí)設(shè)置狀態(tài)代碼為302。Refresh:告訴瀏覽器隔多久刷新一次,以秒計(jì)。Server:服務(wù)器通過這個(gè)頭告訴瀏覽器服務(wù)器的類型。Server響應(yīng)頭包含處理請(qǐng)求的原始服務(wù)器的軟件信息。此域能包含多個(gè)產(chǎn)品標(biāo)識(shí)和注釋,產(chǎn)品標(biāo)識(shí)一般按照重要性排序。Servlet一般不設(shè)置這個(gè)值,而是由Web服務(wù)器自己設(shè)置。Set-Cookie:設(shè)置和頁面關(guān)聯(lián)的Cookie。Servlet不應(yīng)使用response.setHeader(“Set-Cookie”, …),而是應(yīng)使用HttpServletResponse提供的專用方法addCookie。Transfer-Encoding:告訴瀏覽器數(shù)據(jù)的傳送格式。WWW-Authenticate:客戶應(yīng)該在Authorization頭中提供什么類型的授權(quán)信息?在包含401(Unauthorized)狀態(tài)行的應(yīng)答中這個(gè)頭是必需的。例如,response.setHeader(“WWW-Authenticate”, “BASIC realm=\”executives\”“)。注意Servlet一般不進(jìn)行這方面的處理,而是讓W(xué)eb服務(wù)器的專門機(jī)制來控制受密碼保護(hù)頁面的訪問。注:設(shè)置應(yīng)答頭最常用的方法是HttpServletResponse的setHeader,該方法有兩個(gè)參數(shù),分別表示應(yīng)答頭的名字和值。和設(shè)置狀態(tài)代碼相似,設(shè)置應(yīng)答頭應(yīng)該在發(fā)送任何文檔內(nèi)容之前進(jìn)行。setDateHeader方法和setIntHeader方法專門用來設(shè)置包含日期和整數(shù)值的應(yīng)答頭,前者避免了把Java時(shí)間轉(zhuǎn)換為GMT時(shí)間字符串的麻煩,后者則避免了把整數(shù)轉(zhuǎn)換為字符串的麻煩。HttpServletResponse還提供了許多設(shè)置setContentType:設(shè)置Content-Type頭。大多數(shù)Servlet都要用到這個(gè)方法。setContentLength:設(shè)置Content-Length頭。對(duì)于支持持久HTTP連接的瀏覽器來說,這個(gè)函數(shù)是很有用的。addCookie:設(shè)置一個(gè)Cookie(Servlet API中沒有setCookie方法,因?yàn)閼?yīng)答往往包含多個(gè)Set-Cookie頭)。響應(yīng)體 響應(yīng)體就是響應(yīng)的消息體,如果是純數(shù)據(jù)就是返回純數(shù)據(jù),如果請(qǐng)求的是HTML頁面,那么返回的就是HTML代碼,如果是JS就是JS代碼,如此之類。e.瀏覽器頁面渲染解析文檔構(gòu)建DOM樹構(gòu)建渲染樹布局和繪制渲染樹f.斷開TCP連接第一次揮手:客戶端想分手,發(fā)送消息(FIN)給服務(wù)器第二次揮手:服務(wù)器通知客戶端已經(jīng)接受的揮手請(qǐng)求,返回確認(rèn)消息(ACK),但還沒做好分手準(zhǔn)備第三次揮手:服務(wù)器已經(jīng)做好分手準(zhǔn)備,通知客戶端(FIN)第四次揮手:客戶端發(fā)送消息給服務(wù)器(ACK),確認(rèn)分手,服務(wù)器關(guān)閉連接。瀏覽器渲染原理及流程
1. 瀏覽器會(huì)將HTML解析成一個(gè)DOM樹,DOM 樹的構(gòu)建過程是一個(gè)深度遍歷過程:當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn)都構(gòu)建好后才會(huì)去構(gòu)建當(dāng)前節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。2. 將CSS解析成 CSS Rule Tree 。3. 根據(jù)DOM樹和CSSOM來構(gòu)造 Rendering Tree。注意:Rendering Tree 渲染樹并不等同于 DOM 樹,因?yàn)橐恍┫馠eader或display:none的東西就沒必要放在渲染樹中了。4. 有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系。下一步操作稱之為layout,顧名思義就是計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置。5. 再下一步就是繪制,即遍歷render樹,并使用UI后端層繪制每個(gè)節(jié)點(diǎn)。瀏覽器本地存儲(chǔ)
HTML5中的Web Storage包含了兩種存儲(chǔ)方式,sessionStorage和localStorage。還有indexedDB(適用于存儲(chǔ)字典,人工AI)sessionStorage用于本地存儲(chǔ)一個(gè)會(huì)話中的數(shù)據(jù),這些數(shù)據(jù)只有在同一個(gè)會(huì)話中的頁面才能訪問并且當(dāng)會(huì)話結(jié)束后數(shù)據(jù)也隨之銷毀。因此,sessionStorage不是一種持久化的本地存儲(chǔ),僅僅是會(huì)話級(jí)別的存儲(chǔ)。localStorage用于持久化的本地存儲(chǔ),除非主動(dòng)刪除數(shù)據(jù),否則數(shù)據(jù)永遠(yuǎn)不會(huì)過期首先總的來說,三者都是用于持久化數(shù)據(jù)存儲(chǔ)的手段,都是存儲(chǔ)在瀏覽器端,且同源.localStorage和sessionStorage都是Web存儲(chǔ),大小5M左右,完全存儲(chǔ)在客戶端,它們是因?yàn)楸镜卮鎯?chǔ)數(shù)據(jù)而存在.cookies也是存儲(chǔ)在瀏覽器端的,大小不超過4k,由服務(wù)器端存儲(chǔ)在客戶端。localStorage屬于永久性存儲(chǔ),數(shù)據(jù)存儲(chǔ)量大,而sessionStorage屬于當(dāng)會(huì)話結(jié)束的時(shí)候,存儲(chǔ)的值會(huì)被清空,而cookie是通過設(shè)置過期時(shí)間來存儲(chǔ)的。cookie,localStorage,sessionStorage區(qū)別
介紹 1.cookie又叫會(huì)話跟蹤技術(shù),是由web服務(wù)器保存在用戶瀏覽器上的小文本文件,它可以記錄用戶ID、密碼、瀏覽過的網(wǎng)頁、停留的時(shí)間等信息。當(dāng)用戶再次來到該網(wǎng)站時(shí),網(wǎng)站通過讀取cookie,得知用戶相關(guān)信息,如果用戶清理了cookie,那么用戶曾登錄過的網(wǎng)站信息就沒有了。 2.sessionStorage和localStorage是H5新增的本地存儲(chǔ)區(qū)別 1.存儲(chǔ)大小的不同localStorage的大小一般為5MsessionStorage的大小一般為5Mcookies的大小一般為4K 2.有效期不同:localStorage的有效期為永久有效,除非你進(jìn)行手動(dòng)刪除。sessionStorage在當(dāng)前會(huì)話下有效,關(guān)閉頁面或者瀏覽器時(shí)會(huì)被清空。cookies在設(shè)置的有效之前有效,當(dāng)超過有效期便會(huì)失效。 3.與服務(wù)器端的通信localStorage不參與服務(wù)器端的通信。sessionStorage不參與服務(wù)器端的通信。cookies參與服務(wù)器端通信,每次都會(huì)攜帶http的頭信息中。(如果使用cookie保存過多數(shù)據(jù)會(huì)帶來性能問題)應(yīng)用場景 1.因?yàn)榭紤]到每個(gè) HTTP 請(qǐng)求都會(huì)帶著 Cookie 的信息,比較常用的一個(gè)應(yīng)用場景就是判斷用戶是否登錄。針對(duì)登錄過的用戶,服務(wù)器端會(huì)在他登錄時(shí)往 Cookie 中插入一段加密過的唯一辨識(shí)單一用戶的辨識(shí)碼,下次只要讀取這個(gè)值就可以判斷當(dāng)前用戶是否登錄啦。曾經(jīng)還使用 Cookie 來保存用戶在電商網(wǎng)站的購物車信息,如今有了 localStorage,現(xiàn)在基本更加方便 2.sessionStorage:可以用來統(tǒng)計(jì)當(dāng)前頁面元素的點(diǎn)擊次數(shù)。 3.localStoragese:常用于長期登錄(判斷用戶是否已登錄),適合長期保存在本地的數(shù)據(jù)。sessionStorage:敏感賬號(hào)一次性登錄;登陸信息用cookie好還是localStorage好?1.建議登陸信息用 cookie。即設(shè)置過期時(shí)間的cookie,看法是 cookie 默認(rèn)會(huì)發(fā)送回到后端,這樣方便后端讀取,而使用localStorage,你需要在每次請(qǐng)求的時(shí)候,都手動(dòng)帶上這個(gè)信息,這大大增加了開發(fā)過程中帶來的困難,非常麻煩,而且還要手動(dòng)維護(hù)過期時(shí)間。2.cookie有時(shí)效,而localStorage如果不手動(dòng)清理則永久保存。3.如果要設(shè)置關(guān)閉網(wǎng)頁/標(biāo)簽就失效,請(qǐng)用SessionStorage。 這個(gè)類似你設(shè)置“不帶時(shí)間的cookie”。hash值獲取方式
可以通過window.location.hash獲取hash值document.write和innerHTML的區(qū)別
document.write會(huì)重繪整個(gè)頁面innerHTML重繪頁面的一部分進(jìn)程和線程的區(qū)別
一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,從而極大提高了程序的運(yùn)行效率每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制 從邏輯角度來看,多線程的意義在于一個(gè)應(yīng)用程序中,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。但操作系統(tǒng)并沒有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。這就是進(jìn)程和線程的重要區(qū)別babel原理
Babel 是一個(gè)通用的多功能 JavaScript 編譯器,但與一般編譯器不同的是它只是把同種語言的高版本規(guī)則轉(zhuǎn)換為低版本規(guī)則,而不是輸出另一種低級(jí)機(jī)器可識(shí)別的代碼,并且在依賴不同的拓展插件下可用于不同形式的靜態(tài)分析。(靜態(tài)分析:指在不需要執(zhí)行代碼的前提下對(duì)代碼進(jìn)行分析以及相應(yīng)處理的一個(gè)過程,主要應(yīng)用于語法檢查、編譯、代碼高亮、代碼轉(zhuǎn)換、優(yōu)化、壓縮等等)babel 做了什么 和編譯器類似,babel 的轉(zhuǎn)譯過程也分為三個(gè)階段,這三步具體是:1.解析 Parse 將代碼解析生成抽象語法樹( 即AST ),也就是計(jì)算機(jī)理解我們代碼的方式(擴(kuò)展:一般來說每個(gè) js 引擎都有自己的 AST,比如熟知的 v8,chrome 瀏覽器會(huì)把 js 源碼轉(zhuǎn)換為抽象語法樹,再進(jìn)一步轉(zhuǎn)換為字節(jié)碼或機(jī)器代碼),而 babel 則是通過 babylon 實(shí)現(xiàn)的 。簡單來說就是一個(gè)對(duì)于 JS 代碼的一個(gè)編譯過程,進(jìn)行了詞法分析與語法分析的過程。 2.轉(zhuǎn)換 Transform 對(duì)于 AST 進(jìn)行變換一系列的操作,babel 接受得到 AST 并通過 babel-traverse 對(duì)其進(jìn)行遍歷,在此過程中進(jìn)行添加、更新及移除等操作。 3.生成 Generate 將變換后的 AST 再轉(zhuǎn)換為 JS 代碼, 使用到的模塊是 babel-generator。而 babel-core 模塊則是將三者結(jié)合使得對(duì)外提供的API做了一個(gè)簡化。此外需要注意的是,babel 只是轉(zhuǎn)譯新標(biāo)準(zhǔn)引入的語法,比如ES6箭頭函數(shù):而新標(biāo)準(zhǔn)引入的新的原生對(duì)象,部分原生對(duì)象新增的原型方法,新增的 API 等(Proxy、Set 等), 這些事不會(huì)轉(zhuǎn)譯的,需要引入對(duì)應(yīng)的 polyfill 來解決。DVA工作流程
總結(jié)
- 上一篇: 利用计算机设计轴对称图案,“轴对称图形”
- 下一篇: 2017年html5行业报告,云适配发布