轉眼間9月的到來,十分感慨這時光的飛逝。9月對程序員有着十分重要的意義,想在這個優勝劣汰的代碼世界活下去,金3銀4,金9銀10,都屬於選擇的機會。javascript
在這優點略汰且經濟回隴的狀態下,筆者身處央企現在也開始考慮本身工做的問題,咱們能夠選擇的只能是,逐步的打好本身的基礎,才能在不安穩的社會形態下,逆行保持本身的安穩。筆者也該複習複習,在此彙總一下本身過去所學過的基礎。css
本文的難度級別,我的定位爲中級前端開發工程師。我的任務是前端重要基礎的均彙總,若有遺漏,及時提醒,願聽聞。筆者也是逐步前進的小夥,當前也須要及時的補充本身,過程若有不對的地方,儘快指出。如文章對你有幫助,但願能給於鼓勵,手動點個贊吧。html
彙總內容包含看過的書籍,本身對程序的理解,以及部分大神的借鑑(不少都是曾經記下的知識點,來源我也忘記是從哪裏,如沒有說起但願包涵)。前端
但文章全文,均爲筆者一字一字手敲。寫給本身供於複習,同時分享給在前端一塊兒努力朋友。vue
本章一共有兩篇:java
下篇:juejin.cn/post/687316…node
前端基礎,我的認爲就是html + js + css。不管過程如何,不管你用的是less仍是sass,不管你用的vue仍是react,輸出的結果,只有html + js + css。react
此部分列舉,筆者以爲重點的知識點,若有遺漏,歡迎指出。jquery
html章節,本文僅列出筆者任務相對重要的知識點,且介紹上,針對重點。固然,遺漏很正常,但願能收到你的意見。css3
所謂,語義化的標籤,說明讓標籤有本身的含義。也是近十年。最典型的栗子就是header,footer等,它可讓你在沒有樣式的狀況下,就大概能想到,他就是個頭部或者底部。他存在的意義,就是讓前端開發人員,在開發過程當中,更容易去閱讀代碼,以及明白這些代碼的意義。
它的好處是: 1.可以更好的展現內容結構 2.便於團隊的維護與開發 3.有利於SEO,爬蟲能夠分析每一個關鍵詞的權重。 4.方便其餘設備解析 (如屏幕閱讀器)
做爲前端,你不得不知道的SEO,這涉及到公司的網站推廣。
SEO,中文稱搜索引擎優化,一種利用搜索引擎的搜索規則來提升目前網站在有關搜索引擎內的天然排名的方式。他的實現原來分別爲,頁面抓取,分析入庫,檢索排序。
如何優化SEO:
1)title、description、keywords 2)利用好html語義化 3)重要的東西放前面 4)少用iframe
有興趣深刻SEO優化的朋友:segmentfault.com/a/119000001…
前端常常在html頭部看到DOCTYPE的聲明,通常常位於文檔的第一行。那麼他的做用是什麼,可能對新的瀏覽器或者新的網站暫無什麼影響,可是相對古老的瀏覽器或者是網站,可能會出現不一樣。由於瀏覽器有標準模式與兼容模式,差別相對比較大。
標準模式的渲染方式和 JS 引擎的解析方式都是以該瀏覽器支持的最高標準運行。 兼容模式中,頁面以寬鬆的向後兼容的方式顯示 ,模擬老式瀏覽器的行爲以防止站點沒法工做。
而DOCTYPE的存在,就是爲了聲明,該頁面使用標準模式。不聲明,可能一些舊的網站會出現兼容模式。
link與import , 本質使用上,咱們都是用他來引入css,可是他們有必定的區別。
link是一種引入資源的標籤,import是引入css的方式。因此,import引入的只能是css,而link能夠引入全部的資源,包括圖片,RSS等。
加載順序上也有一些差別。 link引用的CSS會同時被加載。 import引用的CSS會等到頁面所有被下載完再加載。
兼容性的差異。 link無任何兼容問題,import兼容IE5以上。(固然,IE5估計也找不到了)
動態引入樣式 link能夠後期引入樣式,而import是不能夠後期引入的,只能初始化頁面以前引入。
複用率的問題 import能夠複用以前的css文件,而link只能一次引用一個文件。 固然,import複用文件時,在瀏覽器其實是加載了多個文件,會有多個請求。而每個link只是一個http請求。
首先這兩個東西爲何而存在的問題。 在日漸複雜的前端,異常已是程序的一部分。若是出現一些小問題,或者服務器加載上出現延遲。而咱們默認的引入的script腳本,會阻塞後續的DOM渲染。一旦沒有部分異常沒法及時加載完成,那麼咱們的頁面由於阻塞問題,將整個白屏。
也許咱們能夠保證本身服務器的正常,可是你決定保證不了第三方服務器的正常,因而引入了async和defer來優化這個問題。
再來談談script的默認,async,defer的以前的差別。
默認狀況下: 瀏覽器會當即加載並執行指定的腳本。指定的腳本,指在script標籤之上的腳本。因此,若是script放在header中,而對應的文件還未加載完成,會造成阻塞。因此這就是如今不少頁面,都會使用默認且把scipt放在頁面結尾的緣由。
async狀況下: async ,加載和渲染後續文檔元素的過程將和 script.js 的加載與執行並行進行(異步)。async是亂序的。
defer狀況下: defer,加載後續文檔元素的過程將和 script.js 的加載並行進行(異步),可是 script.js 的執行要在全部元素解析完成以後,DOMContentLoaded 事件觸發以前完成。defer是順序執行。
此外,async跟defer,不支持或者不兼容IE9一下瀏覽器,整體來講,筆者仍是以爲script放最下方靠譜一些。
適合用事件委託的事件:click,mousedown,mouseup,keydown,keyup,keypress。
執行順序:捕捉--》目標--》冒泡
event.stopPropagation()阻止事件的傳遞行爲. event.preventDefault();阻止默認行爲,好比阻止a的href
優勢: 1.減小事件註冊,節省內存。例如上面代碼,只指定 父元素的處理程序,便可管理全部全部子元素的「click」事件; 2.簡化了dom節點更新時,相應事件的更新
缺點: 1.利用事件冒泡的原理,不支持不冒泡的事件; 2.層級過多,冒泡過程當中,可能會被某層阻止掉; 3. 理論上委託會致使瀏覽器頻繁調用處理函數,雖然極可能不須要處理。因此建議就近委託,好比在ol上代理li,而不是在document上代理li。 4. 把全部事件都用代理就可能會出現事件誤判。好比,在document中代理了全部button的click事件,另外的人在引用改js時,可能不知道,形成單擊button觸發了兩個click事件。
漸進加強:針對低版本瀏覽器進行構建頁面,保證最基本的功能,而後再針對高級瀏覽器進行效果、交互等改進,達到更好的用戶體驗。 優雅降級:一開始就構建完整的功能,而後再針對低版本瀏覽器進行兼容。
css章節,本文僅列出筆者任務相對重要的知識點,且介紹上,針對重點。固然,遺漏很正常,但願能收到你的意見。
盒子模型,我的的理解,就是一個來裝html標籤的容器,包裝的內容包括content+padding+border+margin。由這四個組成咱們的"盒子"。
咱們平常可能會遇到不一樣的瀏覽器,元素的高寬不一致。除了多是瀏覽器內置的margin跟padding不一樣以外,也多是IE跟w3c的盒子模型組成不一樣。
如下是兩種不一樣盒子的分類:
簡單的我的理解,block formatting context,塊級格式化上下文。產生了BFC的,造成了獨立容器,他的特性就是不會再佈局中影響到外邊的元素。
他的特性:
觸發的條件是:
此外,除了BFC,還有IFC、GFC、FFC的概念。咱們簡單瞭解一下。
水平方向上的 margin,border 和 padding在框之間獲得保留。框在垂直方向上能夠以不一樣的方式對齊:它們的頂部或底部對齊,或根據其中文字的基線對齊。包含那些框的長方形區域,會造成一行,叫作行框。 inline-block的元素的內部是一個BFC,可是它自己能夠和其它inline元素一塊兒造成IFC。
flex,即彈性佈局。一個由css3引入,爲咱們的盒子屬性帶來靈活性的一種佈局方式。一旦父級採用了flex佈局,裏邊的子控件將收flex佈局限制,部分本來的樣式(如float:left)也會失效。
基本api不作講解,不熟悉能夠看看:www.ruanyifeng.com/blog/2015/0…
特別注意: flex:0 0 30%的意義: 等於flex-grow=0(默認不放大)+flex-shrink=0(不縮小)+flex-basis=30%( 項目佔據主軸的空間)
前端的圖片分類格式,實際上是性能優化的很大部分。選擇好圖片的類型,對前端的性能影響很是大。
而前端對圖片的精髓,一方面是對圖片大小的評估,一方面是對圖片的類型選擇。
他的大小能夠這樣判斷:
好比一張200*200的圖片大小,這時候,他的像素點有40000個。每一個像素有 4 個通道, 因此一共有160000個字節,因此,咱們評估該圖片的大小大概爲:160000/1024 約等於 156(KB), 若是大不少,說明圖片大小有優化控件。若是小不少,說明此時是模糊的。
圖片類型 | 介紹 | 使用場景 |
---|---|---|
png | 適合顏色簡單,可是對圖片質量比較高。平常用的png8,此外還有png32, | 適合logo體積太大通常不用 |
jpeg | 不影響圖片質量的狀況有損壓縮,banner圖。適合大圖。 | 壓縮後大小可省略不少,通常大圖使用 |
svg | 對性能有損耗,體積小,壓縮性搶。可在質量不降低的過程被放大 | 部分瀏覽器兼容性不太好 |
webp | 只針對谷歌,兼容性很差。圖片大小能壓縮30~40%。 | 谷歌瀏覽器用,若有很是注重性能的產品,可判斷瀏覽器加載不一樣類型圖片 |
base64 | 壓縮成字符流,實際大小是變大了,可是好處就是減小了http請求 | 通常也針對小圖標 |
#### 6.移動端適配 | ||
列舉一下筆者所知道的適配方式: |
該方案的話,我的以爲是最佳的方案,也是經常使用UI庫很是喜歡的用處理方式之一。惟一很差的是:多套媒體方案,也意味多份的工做量。
利用單位vw/vh進行佈局。該方案的話,對總體的佈局仍是相對穩定,可是對部分細節等處理仍是不優化。且遇到手機屏幕差別較大的話,會出現嚴重的視差。
相對穩定的方法。根據屏幕大小計算出font-size;可是隻能求良好,很難求精。若是UI對一像素很是的敏感,這個方案多是個很是糟糕的選擇。
相信原生小程序開發者都用過rpx。這裏其實原理有點相似rem。可是,卻不是按屏幕大小去計算,而是不一樣的屏幕定義了本身的標準。
這個問題本次只列舉了幾個常見的,非所有列出。如需具體,可另查資料。
1)間距差別是否大,致使文本換行,或者間隔太大。 緣由:每一個瀏覽器的margin和padding的默認值不一樣。 解決方案:全局文件設置統一默認margin和padding。
2)圖片默認有間距 緣由:由於img標籤是行內屬性標籤,因此只要不超出容器寬度,img標籤都會排在一行裏,可是部分瀏覽器的img標籤之間會有個間距。去掉這個間距使用float是正道。(個人一個學生使用負margin,雖然能解決,但負margin自己就是容易引發瀏覽器兼容問題的用法,因此我禁止他們使用) 解決方案:使用float屬性爲img佈局
3)較小的高度(小於10px),時,ie可能會超出高度 緣由:IE有一個默認的行高的高度 解決方案:給超出高度的標籤設置overflow:hidden;或者設置行高line-height 小於你設置的高度。
爲min-height自己就是一個不兼容的CSS屬性
4)透明度兼容設置 緣由:不一樣瀏覽器各自透明度關鍵字不統一。 解決方案:filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: 0.5;
5)IE的hover圖片會閃爍 緣由:IE6的每次觸發 hover 的時候都會從新加載 解決方案:提早緩存文件。document.execCommand("BackgroundImageCache", false, true);
該回復只給與思路,沒有具體寫法。由於我以爲你們都應該懂。
已知寬高: 1.margin 本身算高寬 2.定位 + margin-top + margin-left 3.定位 + margin:auto
未知寬高: 1.transform 但有IE兼容的問題 2.flex 佈局 3.display: table-cell
首先你可能須要瞭解一下物理像素跟獨立像素的區別。
物理像素: 一個物理像素是顯示器(手機屏幕)上最小的物理顯示單元,如:iPhone6上就有7501334個物理像素顆粒。 獨立像素:邏輯像素,程序使用的虛擬像素。如:iPhone6上就有375677個獨立像素。
那麼如何實現1px呢: 1.利用 transfrom 的 scale 縮放來實現 2.利用 background 的 linear-gradient 線性漸變來實現 3.meta viewport修改爲1比0.5。這樣整個屏幕的大小縮小了0.5。 4.利用box-shadow
該回復只給思路
1.CSS浮動 第一個float:left,第二個float:right,第三個設置margin-left和margin-right
2.絕對定位法 第一個定位到left,第二個定位到right,第三個設置margin-left和margin-right
3.flex佈局
初步聊聊我的的樣式優化方案以下:
1.避免css層級太深。有興趣瞭解一下css tree如何跟html tree融合成dom tree。 2.首屏(特別是緩衝效果圖)可適當使用內聯元素。這樣有利於更快的顯示。 3.異步加載CSS。非首次重要引入的css文件,不放在head裏邊。這樣會引發阻塞。 4.減小 迴流 的屬性。如display:none能夠考慮使用visibility 5.適當使用GPU渲染。如tranfrom等。 6.css動畫的性能,是遠遠的大於js動畫性能。 7.利用工具壓縮,去重。
僞類和僞元素的根本區別在於:它們是否創造了新的元素
僞類,指能夠經過元素選擇器,就能夠實現的效果,如frist-child,active等。 而僞元素,是指須要經過創元素,才能夠實現的效果,如first-letter,before,after等。
具體元素跟寫法有興趣,可參考:blog.csdn.net/qq_27674439…
javaScript篇,因爲擴展性十分全。對於大神來講,每個點,均可以作一篇簡介參考。 本文只能是概念上的簡介,或者是我的對應的理解。如理解有誤,歡迎吐槽。
內置對象,也叫原始類型。
原始類型有5個,null,undefined,boolean,number,string。 es6引入了symbol,能夠用來作獨立標識用。 es10引入了bigint, 主要用的大數據。number最大值2的53次方,超過只能使用bigint。 截至目前爲止,一共是7個。
原始類型存儲的都是值,他的原型彙總,是沒有任何函數的。若是你看到類型有函數,好比toString,那說明類型給轉換爲了對象類型,此時纔有toString方法。
原始類型存儲的是值,對象類型存儲的是地址。
簡單的理解是,一個綁定了執行環境的函數,能夠訪問到外部環境的變量。
他的好處就是: 變量常駐內存,對於實現某些業務頗有幫助,好比計數器之類的。 架起了一座橋樑,讓函數外部訪問函數內部變量成爲可能。 私有化,必定程序上解決命名衝突問題,能夠實現私有變量。
缺陷是: 他的變量常駐在內存中,其佔用內存沒法被GC回收,致使內存溢出。
注意,閉包的原理是做用域鏈,因此閉包訪問的上級做用域中的變量是個對象,其值爲其運算結束後的最後一個值。
代碼運行時,產生一個對應的執行環境,這個叫作執行上下文。
一般執行上下文,有三個環境: 1.全局環境:代碼首先進入的環境 2.函數環境:函數被調用時執行的環境 3.eval函數:www.cnblogs.com/chaoguo1234…
執行上下文,可分爲三個階段,分別爲建立,執行,銷燬階段。咱們簡單的分析一下,各個階段分別處理了什麼。
(1).生成變量對象 (2).創建做用域鏈 (3).肯定 this 指向
指構造函數的內置屬性,即prototype屬性。每一個構造函數都自帶prototype屬性,指向一個對象,經常使用實例共享屬性和方法的。
Prototype.constructor會指向原構造函數
對象的原型,也是個對象。只要對象的原型有值,不爲null,他就還有原型。因此構成了原型鏈。
變量隨着做用長輩函數一級一級往上搜索,直到找到爲止,找不到就報錯,這個過程就是做用域鏈起的做用。
做用域鏈的原理和原型鏈很相似,若是這個變量在本身的做用域中沒有,那麼它會尋找父級的,直到最頂層。 注意:JS沒有塊級做用域,若要造成塊級做用域,可經過(function(){})();當即執行的形式實現。
繼承的幾種方式:
1.原型鏈繼承 本質是重寫了對象。 缺點: 1)對象實例共享全部繼承的屬性和方法
2)不能傳遞參數
2.構造函數繼承 在子類構造函數的內部調用超類型構造函數。使用apply()和call() 方法 缺點: 1)函數複用性不高 ,每一個實例都是從新實例化構造函數,不存在共享屬性 2)只能繼承實例上的屬性,原型上的方法不可見
3.組合繼承 本質:原型鏈 + 構造函數 Parent.call(this) new Parent()避免了上述的缺點,經常使用。 優勢:可傳參,不會與父類引用屬性共享 缺點:繼承父類函數的時候調用了父類構造函數,致使子類的原型上多了不須要的父類屬性,存在內存上的浪費。
4.原型式繼承 實現本質:object()函數對傳入其中的對象執行了一次淺複製
5.寄生式繼承 借用構造函數來繼承屬性,經過原型鏈的混成形式來繼承方法
6.寄生組合 高效率只調用了一次構造函數,集寄生式繼承和組合繼承的優勢於一身,是實現基於類型繼承的最有效方式。 就是將父類的原型賦值給了子類,而且將構造函數設置爲子類,這樣既解決了無用的父類屬性問題 Parent.call + Object.create()
詳細可參考:juejin.cn/post/684490…
this大概有如下五種場景: 1.綁定事件指向事件自己 2.普通函數的,指向方法體。 3.new函數的指向當前類 4.箭頭函數,指向上級上下文 5.call/apply/bind
看如下代碼,這就是new的總體過程。 · function createThis( proto ){ var obj = new Object; obj.proto = proto.prototype; let [ constructor, ...args] = [ ...arguments ]; let result = constructor.apply( obj, args ); return typeof result === 'object' ? result : obj; }
能夠從代碼中看到new的執行過程,新建一個對象,設置原型鏈,改變this指向,根據對象返回結果。
談到js類型的判斷,咱們能想起 typeof,instanceof,constructor,Object.prototype.toString.call()。(沒了吧?還有的話提醒我一下)
那麼咱們對比一下他們的做用與區別。
typeof 對於原始類型來講,除了 null 均可以顯示正確的類型。可是對於對象來講,除了函數都會顯示 object,因此他的做用,僅僅只能判斷原始類型,判斷不了對象。
instanceof,用於判斷一個變量是否某個對象的實例,內部機制是經過原型鏈來判斷的。他的確能判斷是否類型的是否正確。但一點值得注意,instanceof 檢測的是原型,原型鏈上,每個類型,都會返回true。因此,只能用來判斷兩個對象是否屬於實例關係, 而不能判斷一個對象實例具體屬於哪一種類型。
constructor, 是原型prototype的一個屬性,當函數被定義時候,js引擎會爲函數添加原型prototype,而且這個prototype中constructor屬性指向函數引用, 所以重寫prototype會丟失原來的constructor。
可是他也有明顯的缺陷:
1:null 和 undefined 無constructor,這種方法判斷不了。 2:還有,若是自定義對象,開發者重寫prototype以後,原有的constructor會丟失,所以,爲了規範開發,在重寫對象原型時通常都須要從新給 constructor 賦值,以保證對象實例的類型不被篡改。
toString是幾個方案中,相對比較不錯的方案。建議使用。toString() 是 Object 的原型方法,調用該方法,默認返回當前對象的 [[Class]] 。這是一個內部屬性,其格式爲 [object Xxx] ,其中 Xxx 就是對象的類型。
js類型的轉換,能夠分爲三種狀況:
其中,轉化爲boolean,除了 undefined, null, false, NaN, '', 0, -0,其餘全部值都轉爲 true。咱們平常能夠用它來判斷對象是否未賦值。
比較運算符,是咱們經常使用到的。若是都爲number類型,比較值的大小,那麼固然簡單咯。若是是非number值的時候如何處理呢?
順序以下: 將值轉換爲原始值(ToPrimitive方法) 轉換爲數字(valueOf方法) 轉換爲字符串(toString方法)
補充: 有人提到ToPrimitive的過程,ToPrimitive有兩種狀況,一個是Number,一個是String。
若是是Number,執行以下:
若是是String, 則步驟2跟3調換。
那麼何時ToPrimitive的類型是String,何時type類型是Number。
這裏筆者的記憶是這樣的,分爲兩類:
只要有運算有字符串,那麼將所有轉爲字符串。 若是不是字符串(且數字),那就把它轉換爲(字符串)或數字。
那麼如何判斷先轉爲數字仍是轉爲字符串呢?這涉及到加法運算會觸發三種類型轉換。 參考「比較運算符」,ToPrimitive方法。
只要其中一方是數字,那麼另外一方就轉爲數字。
拷貝,任何語言都有本身的深拷貝以及淺拷貝。深拷貝有利於數據的徹底獨立,可是全是深拷貝的話,內存又不會不斷的往上漲,因而又有了淺拷貝。
基於內存的節省,咱們平常用到的函數,不少都屬於淺拷貝,好比咱們的擴展運算符,還有Object.assign,contact,slice等。都屬於淺拷貝。
而深拷貝:
* 能夠使用JSON.parse(JSON.stringify(obj))。性能最快。其弊端也必將明顯,首先沒法拷貝函數、undefined、或symbol等值。其二對象要是有自身循環調用,會報錯。
* 利用遞歸來實現每一層都從新建立對象並賦值
* 如何用jquery,能夠考慮,$.extend( [deep ], target, object1 [, objectN ] ),這也是深拷貝的一種。
* 也能夠利用lodash.js,cloneDeep方法進行深拷貝。
複製代碼
js的函數調用,有四種方式:
函數調用,自身攜帶的,記住有 this 和 arguments
接收函數做爲參數或者返回函數的函數,均可成爲高階函數。 因此常見的方法有:map,filter,bind,apply等。
須要瞭解一下,高階函數實現AOP。
高階函數,高階組件,有興趣深刻的朋友:juejin.cn/post/684490…
柯里化,實現上,就是返回一個高階函數,經過閉包把傳入的參數保存起來。當傳入的參數數量不足時,遞歸調用 bind 方法;數量足夠時則當即執行函數。學習一下 javascript 的高階用法仍是有意義的。
柯里化是一種將使用多個參數的一個函數轉換成一系列使用一個參數的函數的技術。
柯里化函數就是一種分步傳參的函數,能夠提早傳參而不讓他執行內容,可是參數知足時再調用函數。感受能夠用來作一些未知的判斷。
數組的方法能夠寫的實在是太多了。 藉助一下這位小夥伴的博客:juejin.cn/post/684490…
僞數組,說明它不是真正意義上的數組,他的輸出是個對象,但他的原型並不指向Array。
常見的僞數組包括:arguments、getElementsByTagName等獲取的NodeList對象
它的特性是:
僞數組也能夠轉換爲數組,能夠經過:
call,apply,bind,三者都是用來改變函數的this對象的指向的。且第一個參數都是this要指向的對象,也就是想指定的上下文。
但傳參的值也不一樣,apply後續只能傳遞數組,而call與bind能夠傳遞多個參數。
bind 是返回對應函數,便於稍後調用;apply 、call 則是當即調用。
use strict是否很熟悉?瞭解一下他的大概做用:
首先效率問題: for > forEach > map
如何選擇對應的循環呢:
此外,咱們要明白傳統for
這個 for-of 循環首先調用了 values 數組的 Symbol.iterator 方法,獲取了一個迭代器 (對 Symbol.iterator 的調用發生在 JS 引擎後臺)。接下來 iterator.next() 被調用,迭 代器結果對象的 value 屬性被讀出並放入了第一個結果變量。 若是你只是簡單地迭代數組或集合的值,那麼使用 for-of 循環而不是 for 循環就是個好 主意。 for-of 循環通常不易出錯,由於須要留意的條件更少;傳統的 for 循環被保留用 於處理更復雜的控制條件。 在不可迭代對象、 null 或 undefined 上使用 for-of 語句,會拋出錯誤。
在之前,js一直沒有模塊化的體系。這就會產生一個問題,當項目到達大型時,很大可能性出現方法重疊,以及安全性問題,成爲大型項目的一個痛點與障礙。而es6模塊化正式爲此誕生。
這裏簡述前端模塊化的區別:
1)AMD, commonJS, 與es6,都屬於預加載類型。然後期引入的CDM是懶加載。 何爲預加載, 也就是說,在程序調用,全部的模塊都加載完成。 而懶加載,是用到什麼的時候,纔去加載什麼。
2)AMD跟cmd專一於前端的規範。而commonjs跟es6 moudle可用於先後端。
3)AMD的表明作爲requirejs,cmd的表明做爲seajs。commonjs 與 es6,則無需引入, 只須要引入編譯器(如babel)便可。 seajs爲淘寶引入的規範,咱們都知道淘寶相對很大, 不採用懶加載,首屏的時間將會很長,不過如今已經中止維護。
4)es6 跟 commonJS作了以下改變:
1.ES6只能新增值,沒法從新賦值就會報錯 2.CommonJS 輸出是值的拷貝,即原來模塊中的值改變不會影響已經加載的該值, ES6靜態分析,動態引用,輸出的是值的引用,值改變,引用也改變,即原來模塊中的值改變則該加載的值也改變。 3.CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。 4.CommonJS 加載的是整個模塊,即將全部的接口所有加載進來, ES6 能夠單獨加載其中的某個接口(方法)。 5.CommonJS this 指向當前模塊,ES6 this指向undefined
變量聲明(var)會有變量提高。變量會提早初始化,也能夠提早訪問。當項目變量複雜的時候,很容易產生bug。es6就在這個時候,引入了let跟const。
固然,引入let與const不只僅解決了變量提高的問題,他們的不一樣以下:
新引入的let,const聲明,再不會再產生變量提高。避免了變量提早訪問的場景,間接的提升了嚴謹性。咱們能夠在程序運行時就知道了報錯,而非後期的調試中。
若是一個標識符已經在代碼塊內部被定義,那麼在此代碼塊內使用同一個標識符進行 let 聲明就會致使拋出錯誤
這是let與const的區別。const 聲明會阻止對於變量綁定與變量自身值的修改,避免了咱們平常開發中,了不當心改到常量的問題。
4)暫時性死區 下述案例,用let跟var定義的結果,就明白什麼叫暫時性死區
for( let i = 0; i<10; i++ ){
setTimeOut( function(){
alert(i );
}, 1000);
}
複製代碼
Symbol是JS新引入的基本類型。咱們都知道在ES5以前,JS 已有的基本類型(字符串、數值、布爾類型、 null 與 undefined )以外, ES6 引入 了一種新的基本類型。
符號起初被設計用於建立對象私有成員,而這也 是 JS 開發者期待已久的特性。 在符號誕生以前,將字符串做爲屬性名稱致使屬性能夠被輕易 訪問,不管命名規則如何。 而「私有名稱」意味着開發者能夠建立非字符串類型的屬性名稱,由 此能夠防止使用常規手段來探查這些名稱。
咱們經常使用於: 1.做爲內置屬性名稱。能夠避免同參數名的覆蓋。 2.使用Symbol來替代常量。Symbol來建立一些常量。好比訂單狀態等,能夠也能夠避免重複。 3.做爲私有變量,防止暴露
須要明白Array.of跟Array.from的意義。
首先上述提到,數組有了僞數組的概念,而轉化爲數組,能夠經過 Array.prototype.slice.call(arguments)。可是這個方法並不直觀,因此引入了更爲直觀的Array.form。
只要是部署了iterator(下邊會說起)接口的數據結構,Array.from都能將其轉爲數組。
而Array.of是爲了解決new Array()的嚴謹性的問題。 new Array( )後邊的值,可能表明長度,可能表明數值。
Array.of基本上能夠用來替代Array()或newArray(),而且不存在因爲參數不一樣而致使的重載,並且他們的行爲很是統一。
es6對函數的擴展,主要針對兩個,一個是箭頭函數,一個是解構函數。
箭頭函數跟普通函數的區別:
這裏,簡單說起解構函數,解構數組,以及字符串模版等概念。
數組在 JS 中的使用正如其餘語言的數組同樣,但缺乏更多類型的集合致使數組也常常被看成隊列與棧來使用。 數組只使用了數值型的索引,而若是非數值型的索引是必要的,開發者便會使用非數組的對 象。
Map Map與Object,其最本質的區別,鍵值對的集合(Hash 結構),可是傳統上只能用字符串看成鍵。
對於Map來講,undefined和null是兩個不一樣的鍵,布爾值true和字符串true是兩個不一樣的鍵,而NaN之間視爲同一個鍵 ,0和-0也是一個鍵,
const map = new Map();
map.set(['a'], 1);
map.get(['a'])
複製代碼
會輸出underfined。
WeakMap
WeakMap跟Map結構相似,也是用於生成鍵值對的集合,可是他只能用對象,來做爲鍵值。其次,WeakMap的鍵名所指向的對象,不計入垃圾回收機制。
WeakMap 與 Map 在 API 上的區別主要是兩個,一是沒有遍歷操做(即沒有keys()、values()和entries()方法),也沒有size屬性。由於沒有辦法列出全部鍵名,某個鍵名是否存在徹底不可預測,跟垃圾回收機制是否運行相關。這一刻能夠取到鍵名,下一刻垃圾回收機制忽然運行了,這個鍵名就沒了,爲了防止出現不肯定性,就統一規定不能取到鍵名。二是沒法清空,即不支持clear方法。所以,WeakMap只有四個方法可用:get()、set()、has()、delete()。
WeakMap的實例比較少,我的歷來沒有在實踐中使用。但有這麼一個實例相對適合:好比咱們要統計一個頁面統計該頁面全部節點的點擊次數。
Set Set可能相對更好理解,他能夠簡單理解爲是一個「無重複值」的「有序」列表,且運行值方便快速訪問以及判斷。
咱們能夠利用他去重。包括數組,字符串等。
也能夠利用他去接受一些具備 iterable 接口的其餘數據結構,例如咱們統計頁面有幾個div? new Set(document.querySelectorAll('div'));
WeakSet 跟WeakMap相似,仍是兩個關鍵字:「對象」,「內存」。
迭代器iterator, 能夠理解成一個爲不一樣的數據結構,統一訪問的機制(Symbol.iterator屬性)。只要對應的數據結構有Symbol.iterator屬性,就能夠完成遍歷操做。
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
複製代碼
咱們的字符串,數組、類數組的對象、Set和Map,都具有Iterator接口。因此他們都是可迭代對象。
可迭代的做用有三個:
經常使用到iterator的場景包括:
嚴格來講generator(生成器)屬於ES5,並非ES6。但因爲涉及迭代器等,因此併入es6模塊。
生成器( generator )是能返回一個迭代器的函數。生成器函數由放在 function 關鍵字之 後的一個星號( * )來表示,並能使用新的 yield 關鍵字。將星號緊跟在 function 關鍵 字以後,或是在中間留出空格,都是沒問題的.
形式上,Generator 函數是一個普通函數,可是有兩個特徵。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不一樣的內部狀態(yield在英語裏的意思就是「產出」)。
Generator有着"中止","開始"的狀態,那咱們能夠用他來控制異步編程,因此,他也是異步的解決方案之一。
Generator要next一步一步往下執行。若是想一步執行,能夠藉助Thunk 函數(固然他的原理也是遍歷幫咱們執行了next。)
Promise 被設計用於改善 JS 中的異步編程,與事件及回調函數對比,在異步操做方面爲你提供了更多的控制權與組合性。 Promise 調度被添加到 JS 引擎做業隊列,以便稍後執行。不過此處有另外一個做業隊列追蹤着 Promise 的完成與拒絕處理函數,以確保適當的執行。
Promise 具備三種狀態:掛起、已完成、已拒絕。一個 Promise 起始於掛起態,並在成功時轉爲完成態,或在失敗時轉爲拒絕態。在這兩種狀況下,處理函數都能被添加以代表Promise 什麼時候被解決。
Promise的缺陷:
proxy: 代理對目標對象進行了虛擬,所以該代理與該目標對象表面上能夠被看成同一個對象來對待。代理容許你攔截在目標對象上的底層操做,而這本來是 JS 引擎的內部能力。攔截行爲使用了一個可以響應特定操做的函數(被稱爲陷阱)。
Reflect: 是給底層操做提供默認行爲的方法的集合,這些操做是可以被代理重寫的。每一個代理陷阱都有一個對應的反射方法,每一個方法都與對應的陷阱函數同名,而且接收的參數也與之一致。
JS 運行環境包含一些不可枚舉、不可寫入的 對象屬性,然而在 ES5 以前開發者沒法定義他們本身的不可枚舉屬性或不可寫入屬性。 ES5引入了 Object.defineProperty() 方法以便開發者在這方面可以像 JS 引擎那樣作。
ES6 讓開發者能進一步接近 JS 引擎的能力,這些能力原先只存在於內置對象上。語言經過代理( proxy )暴露了在對象上的內部工做,代理是一種封裝,可以攔截並改變 JS 引擎的底層操做。
Class寫法,能夠簡單理解成ES6的一個語法糖。咱們平常用他所實現的功能,其實用ES5均可以作到,可是class的寫法,讓對象原型的寫法更加清晰。 但不只僅是糖語法。
此外,咱們須要瞭解一下Class寫法中關鍵super、static、constructor、new.target。本文不作詳細介紹。
** cookie,localStorage,sessionStorage.IndexedDB **
比較一下差別:
cookie在瀏覽器和服務器間來回傳遞; sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存;
localStorage<=5M; sessionStorage<=5M; cookie<4K;(ie內核瀏覽器佔主流地位,且ie6仍佔有至關大的市場份額,因此在程序中應當使用少於20個cookie,且不大於4k)
localStorage:始終有效,窗口或瀏覽器關閉也一直保存,所以用做持久數據; sessionStorage:僅在當前瀏覽器窗口關閉前有效,不能持久保持; cookie:只在設置的cookie過時時間以前一直有效,即便窗口或瀏覽器關閉也不會消失;
localStorage :在全部同源窗口中都是共享的; sessionStorage:同時「獨立」打開的不一樣窗口,即便是同一頁面,sessionStorage對象也是不一樣的; cookie:在全部同源窗口中都是共享的
sessionStorage的瀏覽器最小版本:IE八、Chrome 5。
cookie:保存回話信息 localStorage:持久保存的數據 sessionStorage:擁有獨立特性的數據
1.Service Worker 是運行在瀏覽器背後的獨立線程。 必須HTTPS。
三個步奏:註冊(下載:sw.js),監聽(等其餘worker失效),查看緩存 1)sw線程可以用來和服務器溝通數據(service worker的上下文內置了fetch和Push API) 2)可以用來進行大量複雜的運算而不影響UI響應。 3)它能攔截全部的請求
2.Memory Cache 將資源緩存在了內存中。事實上,全部的網絡請求都會被瀏覽器緩存到內存中,固然,內存容量有限,緩存不能無限存放在內存中,所以,註定是個短時間緩存。 內存緩存的控制權在瀏覽器,先後端都不能干涉。
3.Disk Cache 存儲在硬盤中的緩存 強緩存和協商緩存, HTTP Header 來實現的。 Cache-Control > Expires(http1.0產物, 受本地時間影響) > ETag(http1.1出現) > Last-Modified(Last-Modified 打開文件的時候會變,以秒計算的)
4.Push Cache
服務器推送,http2
字節數據-->字符串-->標記(token)-->node-->dom
字節數據-->字符串-->標記(token)-->node-->cssdom
總體的渲染過程:
兩個重要的概念,重繪與迴流:
迴流一定會發生重繪,重繪不必定會引起迴流。 迴流所需的成本比重繪高的多,改變深層次的節點極可能致使父節點的一系列迴流。 當 Event loop 執行完 Microtasks 後,會判斷 document 是否須要更新。由於瀏覽器是 60Hz 的刷新率,每 16ms 纔會更新一次。
致使性能問題:
減小重繪和迴流的細節:
原理:(1)構造URL (2)發佈內容式 (3)蠕蟲式
1)驗證碼。 2)HTTP Referer是header的一部分 3)token
拼接腳本
(1)檢查服務器是否判斷了上傳文件類型及後綴。 (2) 定義上傳文件類型白名單,即只容許白名單裏面類型的文件上傳。 (3) 文件上傳目錄禁止執行腳本解析,避免攻擊者進行二次攻擊。
首先什麼是跨域,違反瀏覽器同源策略的就是跨域。跨域自己就是就是爲了保護瀏覽器的安全, 主要是用來防止 CSRF 攻擊的
那什麼是同源策略?所謂的同源,指的是協議,域名,端口相同。瀏覽器處於安全方面的考慮,只容許本域名下的接口交互,不一樣源的客戶端腳本,在沒有明確受權的狀況下,不能讀寫對方的資源。
解決同源策略的方案:
瀏覽器(一般指)的內存分配,64位系統下大約爲1.4GB,在32位系統下大約爲0.7G。
咱們一般定義變量時候就完成了分配內存,使用時候是對內存的讀寫操做,內存的釋放依賴於瀏覽器的垃圾回收機制。
形成內存泄露
64位下新生代的空間爲64M,老生代爲1400M 32位下新生代的空間爲16M,老生代爲700M.
javaScript使用垃圾回收機制來自動管理內存,垃圾回收是一把雙刃劍
一、V8最初是爲了瀏覽器設計的,不太可能遇到大內存的場景 二、js垃圾回收的時候程序會暫停線程執行,會佔用必定時間。
它有兩種狀況會回收,一種是定時回收,一種內存不夠了回收。
1.新生代算法 Scavenge GC(GC 複製算法) 分爲兩個空間:form 跟 to。
2.老生代算法 標記清除算法 標記壓縮算法
對垃圾回收算法有興趣的朋友:www.jianshu.com/p/a8a04fd00…
javascript是一門單線程語言, Event Loop是javascript的執行機制libuv
需明白什麼叫事件循環事件,微任務,宏任務。以及如何運行。
不知覺中,文章已來到了2W字。貌似掘金的限制是2W字?筆者決定分開多篇文章來彙總,避免有人關心下一章節的內容,因此本文先給出大概菜單,預計時間一週之內,有興趣敬請關注!