2019前端最全面試題

項目地址

HTML問題

HTML5語義化

什麼是語義化?就是用合理、正確的標籤來展現內容,好比h1~h6定義標題。javascript

好處

  • 易於用戶閱讀,樣式丟失的時候能讓頁面呈現清晰的結構。
  • 有利於SEO,搜索引擎根據標籤來肯定上下文和各個關鍵字的權重。
  • 方便其餘設備解析,如盲人閱讀器根據語義渲染網頁
  • 有利於開發和維護,語義化更具可讀性,代碼更好維護,與CSS3關係更和諧。

http://www.daqianduan.com/6549.htmlcss

爲何最好把 CSS 的<link>標籤放在<head></head>之間?爲何最好把 JS 的<script>標籤剛好放在</body>以前,有例外狀況嗎?

<link>放在<head>html

<link>標籤放在<head></head>之間是規範要求的內容。此外,這種作法可讓頁面逐步呈現,提升了用戶體驗。將樣式表放在文檔底部附近,會使許多瀏覽器(包括 Internet Explorer)不能逐步呈現頁面。一些瀏覽器會阻止渲染,以免在頁面樣式發生變化時,從新繪製頁面中的元素。這種作法能夠防止呈現給用戶空白的頁面或沒有樣式的內容。前端

<script>標籤剛好放在</body>以前vue

腳本在下載和執行期間會阻止 HTML 解析。把<script>標籤放在底部,保證 HTML 首先完成解析,將頁面儘早呈現給用戶。html5

例外狀況是當你的腳本里包含document.write()時。可是如今,document.write()不推薦使用。同時,將<script>標籤放在底部,意味着瀏覽器不能開始下載腳本,直到整個文檔(document)被解析。也許,對此比較好的作法是,<script>使用defer屬性,放在<head>中。java

什麼是漸進式渲染(progressive rendering)?

漸進式渲染是用於提升網頁性能(尤爲是提升用戶感知的加載速度),以儘快呈現頁面的技術。node

在之前互聯網帶寬較小的時期,這種技術更爲廣泛。現在,移動終端的盛行,而移動網絡每每不穩定,漸進式渲染在現代前端開發中仍然有用武之地。jquery

一些舉例:nginx

  • 圖片懶加載——頁面上的圖片不會一次性所有加載。當用戶滾動頁面到圖片部分時,JavaScript 將加載並顯示圖像。
  • 肯定顯示內容的優先級(分層次渲染)——爲了儘快將頁面呈現給用戶,頁面只包含基本的最少許的 CSS、腳本和內容,而後能夠使用延遲加載腳本或監聽DOMContentLoaded/load事件加載其餘資源和內容。
  • 異步加載 HTML 片斷——當頁面經過後臺渲染時,把 HTML 拆分,經過異步請求,分塊發送給瀏覽器。更多相關細節能夠在這裏找到。

viewport

Viewport :字面意思爲視圖窗口,在移動web開發中使用。表示將設備瀏覽器寬度虛擬成一個特定的值(或計算得出),這樣利於移動web站點跨設備顯示效果基本一致。移動版的 Safari 瀏覽器最新引進了 viewport 這個 meta tag,讓網頁開發者來控制 viewport 的大小和縮放,其餘手機瀏覽器也基本支持。

在移動端瀏覽器當中,存在着兩種視口,一種是可見視口(也就是咱們說的設備大小),另外一種是視窗視口(網頁的寬度是多少)。
舉個例子:若是咱們的屏幕是320像素 * 480像素的大小(iPhone4),假設在瀏覽器中,320像素的屏幕寬度可以展現980像素寬度的內容。那麼320像素的寬度就是可見視口的寬度,而可以顯示的980像素的寬度就是視窗視口的寬度。

爲了顯示更多的內容,大多數的瀏覽器會把本身的視窗視口擴大,簡易的理解,就是讓本來320像素的屏幕寬度可以容下980像素甚至更寬的內容(將網頁等比例縮小)。

Viewport屬性值

  • width 設置layout viewport 的寬度,爲一個正整數,或字符串"width-device"
  • initial-scale 設置頁面的初始縮放值,爲一個數字,能夠帶小數
  • minimum-scale 容許用戶的最小縮放值,爲一個數字,能夠帶小數
  • maximum-scale 容許用戶的最大縮放值,爲一個數字,能夠帶小數
  • height 設置layout viewport 的高度,這個屬性對咱們並不重要,不多使用
  • user-scalable 是否容許用戶進行縮放,值爲"no"或"yes", no 表明不容許,yes表明容許這些屬性能夠同時使用,也能夠單獨使用或混合使用,多個屬性同時使用時用逗號隔開就好了。

Reflow和Repaint

Reflow

當涉及到DOM節點的佈局屬性發生變化時,就會從新計算該屬性,瀏覽器會從新描繪相應的元素,此過程叫Reflow(迴流或重排)。

Repaint

當影響DOM元素可見性的屬性發生變化 (如 color) 時, 瀏覽器會從新描繪相應的元素, 此過程稱爲Repaint(重繪)。所以重排必然會引發重繪。

引發Repaint和Reflow的一些操做

  • 調整窗口大小
  • 字體大小
  • 樣式表變更
  • 元素內容變化,尤爲是輸入控件
  • CSS僞類激活,在用戶交互過程當中發生
  • DOM操做,DOM元素增刪、修改
  • width, clientWidth, scrollTop等佈局寬高的計算

Repaint和Reflow是不可避免的,只能說對性能的影響減到最小,給出下面幾條建議:

  • 避免逐條更改樣式。建議集中修改樣式,例如操做className。
  • 避免頻繁操做DOM。建立一個documentFragment或div,在它上面應用全部DOM操做,最後添加到文檔裏。設置display:none的元素上操做,最後顯示出來。
  • 避免頻繁讀取元素幾何屬性(例如scrollTop)。絕對定位具備複雜動畫的元素。
  • 絕對定位使它脫離文檔流,避免引發父元素及後續元素大量的迴流

https://harttle.land/2015/08/11/reflow-repaint.html

http://www.blueidea.com/tech/web/2011/8365.asp

img中的alt和元素的title屬性做用

  • img的alt屬性

    若是沒法顯示圖像,瀏覽器將顯示alt指定的內容
  • 元素title屬性

    在鼠標移到元素上時顯示title的內容

href和src區別

  • href

    href標識超文本引用,用在link和a等元素上,href是引用和頁面關聯,是在當前元素和引用資源之間創建聯繫

    若在文檔中添加href ,瀏覽器會識別該文檔爲 CSS 文件,就會並行下載資源而且不會中止對當前文檔的處理。這也是爲何建議使用 link 方式加載 CSS,而不是使用 @import 方式。
  • src

    src表示引用資源,替換當前元素,用在img,script,iframe上,src是頁面內容不可缺乏的一部分。

    當瀏覽器解析到src ,會暫停其餘資源的下載和處理(圖片不會暫停其餘資源下載和處理),直到將該資源加載、編譯、執行完畢,圖片和框架等也如此,相似於將所指向資源應用到當前內容。這也是爲何建議把 js 腳本放在底部而不是頭部的緣由。

https://blog.csdn.net/lhjuejiang/article/details/80795081

瀏覽器的渲染過程

  1. 解析HTML生成DOM樹。
  2. 解析CSS生成CSSOM規則樹。
  3. 將DOM樹與CSSOM規則樹合併在一塊兒生成渲染樹。
  4. 遍歷渲染樹開始佈局,計算每一個節點的位置大小信息。
  5. 將渲染樹每一個節點繪製到屏幕。

https://baijiahao.baidu.com/s?id=1593097105869520145&wfr=spider&for=pc

爲什麼會出現瀏覽器兼容問題

  • 同一產品,版本越老 bug 越多
  • 同一產品,版本越新,功能越多
  • 不一樣產品,不一樣標準,不一樣實現方式

    處理兼容問題的思路

  1. 要不要作
  • 產品的角度(產品的受衆、受衆的瀏覽器比例、效果優先仍是基本功能優先)
  • 成本的角度 (有無必要作某件事)

2.作到什麼程度

  • 讓哪些瀏覽器支持哪些效果

3..如何作

  • 根據兼容需求選擇技術框架/庫(jquery)
  • 根據兼容需求選擇兼容工具(html5shiv.js、respond.js、css reset、normalize.css、Modernizr)
  • 條件註釋、CSS Hack、js 能力檢測作一些修補

  • 漸進加強(progressive enhancement): 針對低版本瀏覽器進行構建頁面,保證最基本的功能,而後再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗
  • 優雅降級 (graceful degradation): 一開始就構建完整的功能,而後再針對低版本瀏覽器進行兼容。

https://github.com/jirengu/frontend-interview/issues/35

doctype有什麼用

doctype是一種標準通用標記語言的文檔類型聲明,目的是告訴標準通用標記語言解析器要使用什麼樣的文檔類型定義(DTD)來解析文檔。

<!DOCTYPE>聲明是用來指示web瀏覽器關於頁面使用哪一個HTML版本進行編寫的指令。

<!DOCTYPE>聲明必須是HTML文檔的第一行,位於html標籤以前。

瀏覽器自己分爲兩種模式,一種是標準模式,一種是怪異模式,瀏覽器經過doctype來區分這兩種模式,doctype在html中的做用就是觸發瀏覽器的標準模式,若是html中省略了doctype,瀏覽器就會進入到Quirks模式的怪異狀態,在這種模式下,有些樣式會和標準模式存在差別,而html標準和dom標準值規定了標準模式下的行爲,沒有對怪異模式作出規定,所以不一樣瀏覽器在怪異模式下的處理也是不一樣的,因此必定要在html開頭使用doctype。

行內元素和塊級元素有哪些

行內元素

一個行內元素只佔據它對應標籤的邊框所包含的空間

通常狀況下,行內元素只能包含數據和其餘行內元素

b, big, i, small, tt
abbr, acronym, cite, code, dfn, em, kbd, strong, samp, var
a, bdo, br, img, map, object, q, script, span, sub, sup
button, input, label, select, textarea

塊級元素

佔據一整行,高度、行高、內邊距和外邊距均可以改變,能夠容納塊級標籤和其餘行內標籤

header,form,ul,ol,table,article,div,hr,aside,figure,canvas,video,audio,footer

iframe框架有那些優缺點

優勢:

  • iframe可以原封不動的把嵌入的網頁展示出來。
  • 若是有多個網頁引用iframe,那麼你只須要修改iframe的內容,就能夠實現調用的每個頁面內容的更改,方便快捷。
  • 網頁若是爲了統一風格,頭部和版本都是同樣的,就能夠寫成一個頁面,用iframe來嵌套,能夠增長代碼的可重用。
  • 若是遇到加載緩慢的第三方內容如圖標和廣告,這些問題能夠由iframe來解決。

    缺點:

  • 搜索引擎的爬蟲程序沒法解讀這種頁面
  • 框架結構中出現各類滾動條
  • 使用框架結構時,保證設置正確的導航連接。
  • iframe頁面會增長服務器的http請求

label標籤有什麼做用

label 標籤一般是寫在表單內,它關聯一個控件,使用 label 能夠實現點擊文字選取對應的控件。

<input type="checkbox" id="test">
<label for="test" >test</label>

HTML5的form如何關閉自動完成功能

將不想要自動完成的 forminput 設置爲 autocomplete=off

MDN

DOM和BOM有什麼區別

  • DOM

Document Object Model,文檔對象模型

DOM 是爲了操做文檔出現的 API,document 是其的一個對象

DOM和文檔有關,這裏的文檔指的是網頁,也就是html文檔。DOM和瀏覽器無關,他關注的是網頁自己的內容。

  • BOM

Browser Object Model,瀏覽器對象模型

BOM 是爲了操做瀏覽器出現的 API,window 是其的一個對象

window 對象既爲 javascript 訪問瀏覽器提供API,同時在 ECMAScript 中充當 Global 對象



CSS問題

CSS 選擇器的優先級是如何計算的?

瀏覽器經過優先級規則,判斷元素展現哪些樣式。優先級經過 4 個維度指標肯定,咱們假定以a、b、c、d命名,分別表明如下含義:

  1. a表示是否使用內聯樣式(inline style)。若是使用,a爲 1,不然爲 0。
  2. b表示 ID 選擇器的數量。
  3. c表示類選擇器、屬性選擇器和僞類選擇器數量之和。
  4. d表示標籤(類型)選擇器和僞元素選擇器之和。

優先級的結果並不是經過以上四個值生成一個得分,而是每一個值分開比較。a、b、c、d權重從左到右,依次減少。判斷優先級時,從左到右,一一比較,直到比較出最大值,便可中止。因此,若是b的值不一樣,那麼cd無論多大,都不會對結果產生影響。好比0,1,0,0的優先級高於0,0,10,10

當出現優先級相等的狀況時,最晚出現的樣式規則會被採納。若是你在樣式表裏寫了相同的規則(不管是在該文件內部仍是其它樣式文件中),那麼最後出現的(在文件底部的)樣式優先級更高,所以會被採納。

在寫樣式時,我會使用較低的優先級,這樣這些樣式能夠輕易地覆蓋掉。尤爲對寫 UI 組件的時候更爲重要,這樣使用者就不須要經過很是複雜的優先級規則或使用!important的方式,去覆蓋組件的樣式了。

參考
  • https://www.smashingmagazine.com/2007/07/css-specificity-things-you-should-know/
  • https://www.sitepoint.com/web-foundations/specificity/

重置(resetting)CSS 和 標準化(normalizing)CSS 的區別是什麼?你會選擇哪一種方式,爲何?

  • 重置(Resetting): 重置意味着除去全部的瀏覽器默認樣式。對於頁面全部的元素,像marginpaddingfont-size這些樣式所有置成同樣。你將必須從新定義各類元素的樣式。
  • 標準化(Normalizing): 標準化沒有去掉全部的默認樣式,而是保留了有用的一部分,同時還糾正了一些常見錯誤。

當須要實現很是個性化的網頁設計時,我會選擇重置的方式,由於我要寫不少自定義的樣式以知足設計需求,這時候就再也不須要標準化的默認樣式了。

參考
  • https://stackoverflow.com/questions/6887336/what-is-the-difference-between-normalize-css-and-reset-css

請闡述Float定位的工做原理。

浮動(float)是 CSS 定位屬性。浮動元素從網頁的正常流動中移出,可是保持了部分的流動性,會影響其餘元素的定位(好比文字會圍繞着浮動元素)。這一點與絕對定位不一樣,絕對定位的元素徹底從文檔流中脫離。

CSS 的clear屬性經過使用leftrightboth,讓該元素向下移動(清除浮動)到浮動元素下面。

若是父元素只包含浮動元素,那麼該父元素的高度將塌縮爲 0。咱們能夠經過清除(clear)從浮動元素後到父元素關閉前之間的浮動來修復這個問題。

有一種 hack 的方法,是自定義一個.clearfix類,利用僞元素選擇器::after清除浮動。另外還有一些方法,好比添加空的<div></div>和設置浮動元素父元素的overflow屬性。與這些方法不一樣的是,clearfix方法,只須要給父元素添加一個類,定義以下:

.clearfix::after {
  content: '';
  display: block;
  clear: both;
}

值得一提的是,把父元素屬性設置爲overflow: autooverflow: hidden,會使其內部的子元素造成塊格式化上下文(Block Formatting Context),而且父元素會擴張本身,使其可以包圍它的子元素。

參考
  • https://css-tricks.com/all-about-floats/

請闡述z-index屬性,並說明如何造成層疊上下文(stacking context)。

CSS 中的z-index屬性控制重疊元素的垂直疊加順序。z-index只能影響position值不是static的元素。

沒有定義z-index的值時,元素按照它們出如今 DOM 中的順序堆疊(層級越低,出現位置越靠上)。非靜態定位的元素(及其子元素)將始終覆蓋靜態定位(static)的元素,而無論 HTML 層次結構如何。

層疊上下文是包含一組圖層的元素。 在一組層疊上下文中,其子元素的z-index值是相對於該父元素而不是 document root 設置的。每一個層疊上下文徹底獨立於它的兄弟元素。若是元素 B 位於元素 A 之上,則即便元素 A 的子元素 C 具備比元素 B 更高的z-index值,元素 C 也永遠不會在元素 B 之上.

每一個層疊上下文是自包含的:當元素的內容發生層疊後,整個該元素將會在父層疊上下文中按順序進行層疊。少數 CSS 屬性會觸發一個新的層疊上下文,例如opacity小於 1,filter不是nonetransform不是none

參考
  • https://css-tricks.com/almanac/properties/z/z-index/
  • https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
  • https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

請闡述塊格式化上下文(Block Formatting Context)及其工做原理。

塊格式上下文(BFC)是 Web 頁面的可視化 CSS 渲染的部分,是塊級盒佈局發生的區域,也是浮動元素與其餘元素交互的區域。

一個 HTML 盒(Box)知足如下任意一條,會建立塊格式化上下文:

  • float的值不是none.
  • position的值不是staticrelative.
  • display的值是table-celltable-captioninline-blockflex、或inline-flex
  • overflow的值不是visible

在 BFC 中,每一個盒的左外邊緣都與其包含的塊的左邊緣相接。

兩個相鄰的塊級盒在垂直方向上的邊距會發生合併(collapse)。更多內容請參考邊距合併(margin collapsing)

參考
  • https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
  • https://www.sitepoint.com/understanding-block-formatting-contexts-in-css/

有哪些清除浮動的技術,都適用哪些狀況?

  • div方法:<div style="clear:both;"></div>
  • Clearfix 方法:上文使用.clearfix類已經提到。
  • overflow: autooverflow: hidden方法:上文已經提到。

在大型項目中,我會使用 Clearfix 方法,在須要的地方使用.clearfix。設置overflow: hidden的方法可能使其子元素顯示不完整,當子元素的高度大於父元素時。

請解釋什麼是雪碧圖(css sprites),以及如何實現?

雪碧圖是把多張圖片整合到一張上的圖片。它被運用在衆多使用了不少小圖標的網站上(Gmail 在使用)。實現方法:

  1. 使用生成器將多張圖片打包成一張雪碧圖,併爲其生成合適的 CSS。
  2. 每張圖片都有相應的 CSS 類,該類定義了background-imagebackground-positionbackground-size屬性。
  3. 使用圖片時,將相應的類添加到你的元素中。

好處:

  • 減小加載多張圖片的 HTTP 請求數(一張雪碧圖只須要一個請求)。可是對於 HTTP2 而言,加載多張圖片再也不是問題。
  • 提早加載資源,防止在須要時纔在開始下載引起的問題,好比只出如今:hover僞類中的圖片,不會出現閃爍。
參考
  • https://css-tricks.com/css-sprites/

如何解決不一樣瀏覽器的樣式兼容性問題?

  • 在肯定問題緣由和有問題的瀏覽器後,使用單獨的樣式表,僅供出現問題的瀏覽器加載。這種方法須要使用服務器端渲染。
  • 使用已經處理好此類問題的庫,好比 Bootstrap。
  • 使用 autoprefixer 自動生成 CSS 屬性前綴。
  • 使用 Reset CSS 或 Normalize.css。

如何爲功能受限的瀏覽器提供頁面? 使用什麼樣的技術和流程?

  • 優雅的降級:爲現代瀏覽器構建應用,同時確保它在舊版瀏覽器中正常運行。
  • Progressive enhancement - The practice of building an application for a base level of user experience, but adding functional enhancements when a browser supports it.
  • 漸進式加強:構建基於用戶體驗的應用,但在瀏覽器支持時添加新增功能。
  • 利用 caniuse.com 檢查特性支持。
  • 使用 autoprefixer 自動生成 CSS 屬性前綴。
  • 使用 Modernizr進行特性檢測。

有什麼不一樣的方式能夠隱藏內容(使其僅適用於屏幕閱讀器)?

這些方法與可訪問性(a11y)有關。

  • visibility: hidden:元素仍然在頁面流中,並佔用空間。
  • width: 0; height: 0:使元素不佔用屏幕上的任何空間,致使不顯示它。
  • position: absolute; left: -99999px: 將它置於屏幕以外。
  • text-indent: -9999px:這隻適用於block元素中的文本。
  • Metadata: 例如經過使用 Schema.org,RDF 和 JSON-LD。
  • WAI-ARIA:如何增長網頁可訪問性的 W3C 技術規範。

即便 WAI-ARIA 是理想的解決方案,我也會採用絕對定位方法,由於它具備最少的注意事項,適用於大多數元素,並且使用起來很是簡單。

參考
  • https://www.w3.org/TR/wai-aria-1.1/
  • https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
  • http://a11yproject.com/

除了screen,你還能說出一個 @media 屬性的例子嗎?

  • all

    適用於全部設備。
  • print

    爲了加載合適的文檔到當前使用的可視窗口. 須要提早諮詢 paged media(媒體屏幕尺寸), 以知足個別設備網頁尺寸不匹配等問題。
  • screen

    主要適用於彩色的電腦屏幕
  • speech

    解析speech這個合成器. 注意: CSS2已經有一個類似的媒體類型叫aural.

    https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media

編寫高效的 CSS 應該注意什麼?

首先,瀏覽器從最右邊的選擇器,即關鍵選擇器(key selector),向左依次匹配。根據關鍵選擇器,瀏覽器從 DOM 中篩選出元素,而後向上遍歷被選元素的父元素,判斷是否匹配。選擇器匹配語句鏈越短,瀏覽器的匹配速度越快。避免使用標籤和通用選擇器做爲關鍵選擇器,由於它們會匹配大量的元素,瀏覽器必需要進行大量的工做,去判斷這些元素的父元素們是否匹配。

BEM (Block Element Modifier) methodology recommends that everything has a single class, and, where you need hierarchy, that gets baked into the name of the class as well, this naturally makes the selector efficient and easy to override.
BEM (Block Element Modifier)原則上建議爲獨立的 CSS 類命名,而且在須要層級關係時,將關係也體如今命名中,這天然會使選擇器高效且易於覆蓋。

搞清楚哪些 CSS 屬性會觸發從新佈局(reflow)、重繪(repaint)和合成(compositing)。在寫樣式時,避免觸發從新佈局的可能。

參考
  • https://developers.google.com/web/fundamentals/performance/rendering/
  • https://csstriggers.com/

使用 CSS 預處理的優缺點分別是什麼?

優勢:

  • 提升 CSS 可維護性。
  • 易於編寫嵌套選擇器。
  • 引入變量,增添主題功能。能夠在不一樣的項目中共享主題文件。
  • 經過混合(Mixins)生成重複的 CSS。
  • Splitting your code into multiple files. CSS files can be split up too but doing so will require a HTTP request to download each CSS file.
  • 將代碼分割成多個文件。不進行預處理的 CSS,雖然也能夠分割成多個文件,但須要創建多個 HTTP 請求加載這些文件。

缺點:

  • 須要預處理工具。
  • 從新編譯的時間可能會很慢。

對於你使用過的 CSS 預處理,說說喜歡和不喜歡的地方?

喜歡:

  • 絕大部分優勢上題以及提過。
  • Less 用 JavaScript 實現,與 NodeJS 高度結合。

Dislikes:

  • 我經過node-sass使用 Sass,它用 C ++ 編寫的 LibSass 綁定。在 Node 版本切換時,我必須常常從新編譯。
  • Less 中,變量名稱以@做爲前綴,容易與 CSS 關鍵字混淆,如@media@import@font-face

如何實現一個使用非標準字體的網頁設計?

使用@font-face併爲不一樣的font-weight定義font-family

解釋瀏覽器如何肯定哪些元素與 CSS 選擇器匹配。

這部分與上面關於編寫高效的 CSS 有關。瀏覽器從最右邊的選擇器(關鍵選擇器)根據關鍵選擇器,瀏覽器從 DOM 中篩選出元素,而後向上遍歷被選元素的父元素,判斷是否匹配。選擇器匹配語句鏈越短,瀏覽器的匹配速度越快。

例如,對於形如p span的選擇器,瀏覽器首先找到全部<span>元素,並遍歷它的父元素直到根元素以找到<p>元素。對於特定的<span>,只要找到一個<p>,就知道'`已經匹配並中止繼續匹配。

參考
  • https://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left

描述僞元素及其用途。

CSS 僞元素是添加到選擇器的關鍵字,去選擇元素的特定部分。它們能夠用於裝飾(:first-line:first-letter)或將元素添加到標記中(與 content:...組合),而沒必要修改標記(:before:after)。

  • :first-line:first-letter能夠用來修飾文字。
  • 上面提到的.clearfix方法中,使用clear: both來添加不佔空間的元素。
  • 使用:beforeafter展現提示中的三角箭頭。鼓勵關注點分離,由於三角被視爲樣式的一部分,而不是真正的 DOM。若是不使用額外的 HTML 元素,只用 CSS 樣式繪製三角形是不太可能的。
參考
  • https://css-tricks.com/almanac/selectors/a/after-and-before/

說說你對盒模型的理解,以及如何告知瀏覽器使用不一樣的盒模型渲染布局。

CSS 盒模型描述了以文檔樹中的元素而生成的矩形框,並根據排版模式進行佈局。每一個盒子都有一個內容區域(例如文本,圖像等)以及周圍可選的paddingbordermargin區域。

CSS 盒模型負責計算:

  • 塊級元素佔用多少空間。
  • 邊框是否重疊,邊距是否合併。
  • 盒子的尺寸。

盒模型有如下規則:

  • 塊級元素的大小由widthheightpaddingbordermargin決定。
  • 若是沒有指定height,則塊級元素的高度等於其包含子元素的內容高度加上padding(除非有浮動元素,請參閱下文)。
  • 若是沒有指定width,則非浮動塊級元素的寬度等於其父元素的寬度減去父元素的padding
  • 元素的height是由內容的height來計算的。
  • 元素的width是由內容的width來計算的。
  • 默認狀況下,paddingborder不是元素widthheight的組成部分。
參考
  • https://www.smashingmagazine.com/2010/06/the-principles-of-cross-browser-css-coding/#understand-the-css-box-model

* { box-sizing: border-box; }會產生怎樣的效果?

  • 元素默認應用了box-sizing: content-box,元素的寬高只會決定內容(content)的大小。
  • box-sizing: border-box改變計算元素widthheight的方式,borderpadding的大小也將計算在內。
  • 元素的height = 內容(content)的高度 + 垂直方向的padding + 垂直方向border的寬度
  • 元素的width = 內容(content)的寬度 + 水平方向的padding + 水平方向border的寬度

display的屬性值都有哪些?

  • none, block, inline, inline-block, table, table-row, table-cell, list-item.

inlineinline-block有什麼區別?

我把block也加入其中,爲了得到更好的比較。

block inline-block inline
大小 填充其父容器的寬度。 取決於內容。 取決於內容。
定位 重新的一行開始,而且不容許旁邊有 HTML 元素(除非是float 與其餘內容一塊兒流動,並容許旁邊有其餘元素。 與其餘內容一塊兒流動,並容許旁邊有其餘元素。
可否設置widthheight 不能。 設置會被忽略。
能夠使用vertical-align對齊 不能夠 能夠 能夠
邊距(margin)和填充(padding) 各個方向都存在 各個方向都存在 只有水平方向存在。垂直方向會被忽略。 儘管borderpaddingcontent周圍,但垂直方向上的空間取決於'line-height'
浮動(float) - - 就像一個block元素,能夠設置垂直邊距和填充。

relativefixedabsolutestatic四種定位有什麼區別?

通過定位的元素,其position屬性值必然是relativeabsolutefixedsticky

  • static:默認定位屬性值。該關鍵字指定元素使用正常的佈局行爲,即元素在文檔常規流中當前的佈局位置。此時 top, right, bottom, left 和 z-index 屬性無效。
  • relative:該關鍵字下,元素先放置在未添加定位時的位置,再在不改變頁面佈局的前提下調整元素位置(所以會在此元素未添加定位時所在位置留下空白)。
  • absolute:不爲元素預留空間,經過指定元素相對於最近的非 static 定位祖先元素的偏移,來肯定元素位置。絕對定位的元素能夠設置外邊距(margins),且不會與其餘邊距合併。
  • fixed:不爲元素預留空間,而是經過指定元素相對於屏幕視口(viewport)的位置來指定元素位置。元素的位置在屏幕滾動時不會改變。打印時,元素會出如今的每頁的固定位置。fixed 屬性會建立新的層疊上下文。當元素祖先的 transform 屬性非 none 時,容器由視口改成該祖先。
  • sticky:盒位置根據正常流計算(這稱爲正常流動中的位置),而後相對於該元素在流中的 flow root(BFC)和 containing block(最近的塊級祖先元素)定位。在全部狀況下(即使被定位元素爲 table 時),該元素定位均不對後續元素形成影響。當元素 B 被粘性定位時,後續元素的位置仍按照 B 未定位時的位置來肯定。position: stickytable 元素的效果與 position: relative 相同。
參考
  • https://developer.mozilla.org/en/docs/Web/CSS/position

你使用過哪些現有的 CSS 框架?你是如何改進它們的?

  • Bootstrap: 更新週期緩慢。Bootstrap 4 已經處於 alpha 版本將近兩年了。添加了在頁面中普遍使用的微調按鈕組件。
  • Semantic UI:源代碼結構使得自定義主題很難理解。很是規主題系統的使用體驗不好。外部庫的路徑須要硬編碼(hard code)配置。變量從新賦值沒有 Bootstrap 設計得好。
  • Bulma: 須要不少非語義的類和標記,顯得不少餘。不向後兼容,以致於升級版本後,會破壞應用的正常運行。

你瞭解 CSS Flex 和 Grid 嗎?

Flex 主要用於一維佈局,而 Grid 則用於二維佈局。

Flex

flex容器中存在兩條軸, 橫軸和縱軸, 容器中的每一個單元稱爲flex item。

在容器上能夠設置6個屬性:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

注意:當設置 flex 佈局以後,子元素的 float、clear、vertical-align 的屬性將會失效。

Flex 項目屬性

有六種屬性可運用在 item 項目上:

  1. order
  2. flex-basis
  3. flex-grow
  4. flex-shrink
  5. flex
  6. align-self

Grid

CSS網格佈局用於將頁面分割成數個主要區域,或者用來定義組件內部元素間大小、位置和圖層之間的關係。

像表格同樣,網格佈局讓咱們可以按行或列來對齊元素。 可是,使用CSS網格可能仍是比CSS表格更容易佈局。 例如,網格容器的子元素能夠本身定位,以便它們像CSS定位的元素同樣,真正的有重疊和層次。

響應式設計與自適應設計有何不一樣?

響應式設計和自適應設計都以提升不一樣設備間的用戶體驗爲目標,根據視窗大小、分辨率、使用環境和控制方式等參數進行優化調整。

響應式設計的適應性原則:網站應該憑藉一份代碼,在各類設備上都有良好的顯示和使用效果。響應式網站經過使用媒體查詢,自適應柵格和響應式圖片,基於多種因素進行變化,創造出優良的用戶體驗。就像一個球經過膨脹和收縮,來適應不一樣大小的籃圈。

自適應設計更像是漸進式加強的現代解釋。與響應式設計單一地去適配不一樣,自適應設計經過檢測設備和其餘特徵,從早已定義好的一系列視窗大小和其餘特性中,選出最恰當的功能和佈局。與使用一個球去穿過各類的籃筐不一樣,自適應設計容許使用多個球,而後根據不一樣的籃筐大小,去選擇最合適的一個。

參考
  • https://developer.mozilla.org/en-US/docs/Archive/Apps/Design/UI_layout_basics/Responsive_design_versus_adaptive_design
  • http://mediumwell.com/responsive-adaptive-mobile/
  • https://css-tricks.com/the-difference-between-responsive-and-adaptive-design/

你有沒有使用過視網膜分辨率的圖形?當中使用什麼技術?

我傾向於使用更高分辨率的圖形(顯示尺寸的兩倍)來處理視網膜顯示。更好的方法是使用媒體查詢,像@media only screen and (min-device-pixel-ratio: 2) { ... },而後改變background-image

對於圖標類的圖形,我會盡量使用 svg 和圖標字體,由於它們在任何分辨率下,都能被渲染得十分清晰。

還有一種方法是,在檢查了window.devicePixelRatio的值後,利用 JavaScript 將<img>src屬性修改,用更高分辨率的版本進行替換。

參考
  • https://www.sitepoint.com/css-techniques-for-retina-displays/

什麼狀況下,用translate()而不用絕對定位?何時,狀況相反。

translate()transform的一個值。改變transformopacity不會觸發瀏覽器從新佈局(reflow)或重繪(repaint),只會觸發複合(compositions)。而改變絕對定位會觸發從新佈局,進而觸發重繪和複合。transform使瀏覽器爲元素建立一個 GPU 圖層,但改變絕對定位會使用到 CPU。 所以translate()更高效,能夠縮短平滑動畫的繪製時間。

當使用translate()時,元素仍然佔據其原始空間(有點像position:relative),這與改變絕對定位不一樣。

參考
  • https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

其餘答案

  • https://neal.codes/blog/front-end-interview-css-questions
  • https://quizlet.com/28293152/front-end-interview-questions-css-flash-cards/
  • http://peterdoes.it/2015/12/03/a-personal-exercise-front-end-job-interview-questions-and-my-answers-all/

行內元素、塊級元素區別

行內元素:和其餘元素都在一行上,高度、行高及外邊距和內邊距都不可改變,文字圖片的寬度不可改變,只能容納文本或者其餘行內元素;其中img是行元素

塊級元素:老是在新行上開始,高度、行高及外邊距和內邊距均可控制,能夠容納內斂元素和其餘元素;行元素轉換爲塊級元素方式:display:block;

一邊固定寬度一邊寬度自適應

能夠使用flex佈局 複製下面的HTML和CSS代碼 用瀏覽器打開能夠看到效果

<div class="wrap">
  <div class="div1"></div>
  <div class="div2"></div>
</div>

.wrap {
  display: flex;
  justify-content: space-between;
}
.div1 {
  min-width: 200px;
}
.div2 {
  width: 100%;
  background: #e6e6e6;
}
html,
body,
div {
  height: 100%;
  margin: 0;
}

水平垂直居中的方式

flex

// 父容器
display: flex;
justify-content: center;
align-items: center;

position

// 父容器
position: relative;

// 子容器
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;

position+transform

// 父容器
position: relative;

// 子容器
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

table-cell

<div class="box">
    <div class="content">
        <div class="inner"></div>
    </div>
</div>

html, body {
    height: 100%;
    width: 100%;
    margin: 0;
}
.box {
    display: table;
    height: 100%;
    width: 100%;
}
.content {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
.inner {
    background-color: #000;
    display: inline-block;
    width: 200px;
    height: 200px;
}

display:none、visibile:hidden、opacity:0的區別

是否隱藏 是否在文檔中佔用空間 是否會觸發事件
display: none
visibile: hidden
opacity: 0

CSS中link和@import的區別

  • link屬於HTML標籤,而@import是CSS提供的
  • 頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
  • import只在IE5以上才能識別,而link是HTML標籤,無兼容問題
  • link方式的樣式的權重 高於@import的權重

如何用css實現瀑布流佈局

利用column-count和break-inside這兩個CSS3屬性便可,複製以下代碼便可察看效果

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body {
            margin: 0;
        }
        .waterfall-container {
            /*分幾列*/
            column-count: 2;
            width: 100%;
            /* 列間距 */
            column-gap: 10px;
        }

        .waterfall-item {
            break-inside: avoid;
            width: 100%;
            height: 100px;
            margin-bottom: 10px;
            background: #ddd;
            column-gap: 0;
            text-align: center;
            color: #fff;
            font-size: 40px;
        }
    </style>
</head>
<body>
    <div class="waterfall-container">
        <div class="waterfall-item" style="height: 100px">1</div>
        <div class="waterfall-item" style="height: 300px">2</div>
        <div class="waterfall-item" style="height: 400px">3</div>
        <div class="waterfall-item" style="height: 100px">4</div>
        <div class="waterfall-item" style="height: 300px">5</div>
        <div class="waterfall-item" style="height: 600px">6</div>
        <div class="waterfall-item" style="height: 400px">7</div>
        <div class="waterfall-item" style="height: 300px">8</div>
        <div class="waterfall-item" style="height: 700px">9</div>
        <div class="waterfall-item" style="height: 100px">10</div>
    </div>
</body>
</html>

文本超出部分顯示省略號

單行

overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;

多行

display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; // 最多顯示幾行
overflow: hidden;

利用僞元素畫三角

.info-tab {
    position: relative;
}
.info-tab::after {
    content: '';
    border: 4px solid transparent;
    border-top-color: #2c8ac2;
    position: absolute;
    top: 0;
}

已知父級盒子的寬高,子級img寬高未知,想讓img鋪滿父級盒子且圖片不能變形

須要用到cssobject-fit屬性

div {
    width: 200px;
    height: 200px;
}
img {
    object-fit: cover;
    width: 100%;
    height: 100%;
}

MDN

iframe的做用

iframe是用來在網頁中插入第三方頁面,早期的頁面使用iframe主要是用於導航欄這種不少頁面都相同的部分,這樣在切換頁面的時候避免重複下載。

優勢

  1. 便於修改,模擬分離,像一些信息管理系統會用到。
  2. 但如今基本不推薦使用。除非特殊須要,通常不推薦使用。

缺點

  1. iframe的建立比通常的DOM元素慢了1-2個數量級
  2. iframe標籤會阻塞頁面的的加載,若是頁面的onload事件不能及時觸發,會讓用戶以爲網頁加載很慢,用戶體驗很差,在Safari和Chrome中能夠經過js動態設置iframe的src屬性來避免阻塞。
  3. iframe對於SEO不友好,替換方案通常就是動態語言的Incude機制和ajax動態填充內容等。

css hack是什麼

因爲不一樣的瀏覽器,好比Internet Explorer 6,Internet Explorer 7,Mozilla Firefox等,對CSS的解析認識不同,所以會致使生成的頁面效果不同,得不到咱們所須要的頁面效果。

這個時候咱們就須要針對不一樣的瀏覽器去寫不一樣的CSS,讓它可以同時兼容不一樣的瀏覽器,能在不一樣的瀏覽器中也能獲得咱們想要的頁面效果。

這個針對不一樣的瀏覽器寫不一樣的CSS code的過程,就叫CSS hack,也叫寫CSS hack。

具體請看:

http://www.cnblogs.com/Renyi-Fan/p/9006084.html

過渡與動畫的區別是什麼

  • transition

    能夠在必定的時間內實現元素的狀態過渡爲最終狀態,用於模擬以一種過渡動畫效果,可是功能有限,只能用於製做簡單的動畫效果而動畫屬性
  • animation

    能夠製做相似Flash動畫,經過關鍵幀控制動畫的每一步,控制更爲精確,從而能夠製做更爲複雜的動畫。

什麼是外邊距合併

外邊距合併指的是,當兩個垂直外邊距相遇時,它們將造成一個外邊距。

合併後的外邊距的高度等於兩個發生合併的外邊距的高度中的較大者。

去除inline-block元素間間距的方法

  • 移除空格
  • 使用margin負值
  • 使用font-size:0
  • letter-spacing
  • word-spacing

更詳細的介紹請看:去除inline-block元素間間距的N種方法




JavaScript問題

同源策略

同源策略可防止 JavaScript 發起跨域請求。源被定義爲 URI、主機名和端口號的組合。此策略可防止頁面上的惡意腳本經過該頁面的文檔對象模型,訪問另外一個網頁上的敏感數據。

跨域

  • 緣由

    瀏覽器的同源策略致使了跨域
  • 做用

    用於隔離潛在惡意文件的重要安全機制
  • 解決
  1. jsonp ,容許 script 加載第三方資源
  2. 反向代理(nginx 服務內部配置 Access-Control-Allow-Origin *)
  3. cors 先後端協做設置請求頭部,Access-Control-Allow-Origin 等頭部信息
  4. iframe 嵌套通信,postmessage

https://zhuanlan.zhihu.com/p/41479807

跨域資源共享 CORS 阮一峯

JSONP

這是我認爲寫得比較通俗易懂的一篇文章 直接轉載過來

https://blog.csdn.net/hansexploration/article/details/80314948

域名收斂

PC 時代爲了突破瀏覽器的域名併發限制。有了域名發散。

瀏覽器有併發限制,是爲了防止DDOS攻擊。

域名收斂:就是將靜態資源放在一個域名下。減小DNS解析的開銷。

域名發散:是將靜態資源放在多個子域名下,就能夠多線程下載,提升並行度,使客戶端加載靜態資源更加迅速。

域名發散是pc端爲了利用瀏覽器的多線程並行下載能力。而域名收斂多用與移動端,提升性能,由於dns解析是是從後向前迭代解析,若是域名過多性能會降低,增長DNS的解析開銷。

事件綁定的方式

  • 嵌入dom
<button onclick="func()">按鈕</button>
  • 直接綁定
btn.onclick = function(){}
  • 事件監聽
btn.addEventListener('click',function(){})

事件委託

事件委託利用了事件冒泡,只指定一個事件處理程序,就能夠管理某一類型的全部事件。全部用到按鈕的事件(多數鼠標事件和鍵盤事件)都適合採用事件委託技術,
使用事件委託能夠節省內存。

<ul>
  <li>蘋果</li>
  <li>香蕉</li>
  <li>鳳梨</li>
</ul>

// good
document.querySelector('ul').onclick = (event) => {
  let target = event.target
  if (target.nodeName === 'LI') {
    console.log(target.innerHTML)
  }
}

// bad
document.querySelectorAll('li').forEach((e) => {
  e.onclick = function() {
    console.log(this.innerHTML)
  }
})

事件循環

事件循環是一個單線程循環,用於監視調用堆棧並檢查是否有工做即將在任務隊列中完成。若是調用堆棧爲空而且任務隊列中有回調函數,則將回調函數出隊並推送到調用堆棧中執行。

事件模型

  • DOM0

    直接綁定
<input onclick="sayHi()"/>

btn.onclick = function() {}
btn.onclick = null
  • DOM2

    DOM2級事件能夠冒泡和捕獲
    經過addEventListener綁定
    經過removeEventListener解綁
// 綁定
btn.addEventListener('click', sayHi)
// 解綁
btn.removeEventListener('click', sayHi)
  • DOM3

    DOM3具備更多事件類型
    DOM3級事件在DOM2級事件的基礎上添加了更多的事件類型,所有類型以下:
UI事件,當用戶與頁面上的元素交互時觸發,如:load、scroll
焦點事件,當元素得到或失去焦點時觸發,如:blur、focus
鼠標事件,當用戶經過鼠標在頁面執行操做時觸發如:dbclick、mouseup
滾輪事件,當使用鼠標滾輪或相似設備時觸發,如:mousewheel
文本事件,當在文檔中輸入文本時觸發,如:textInput
鍵盤事件,當用戶經過鍵盤在頁面上執行操做時觸發,如:keydown、keypress
合成事件,當爲IME(輸入法編輯器)輸入字符時觸發,如:compositionstart
變更事件,當底層DOM結構發生變化時觸發,如:DOMsubtreeModified

https://www.jianshu.com/p/3acdf5f71d5b

如何自定義事件

  1. 原生提供了3個方法實現自定義事件
  2. createEvent,設置事件類型,是 html 事件仍是 鼠標事件
  3. initEvent 初始化事件,事件名稱,是否容許冒泡,是否阻止自定義事件
  4. dispatchEvent 觸發事件

MDN

target和currentTarget區別

  • event.target

    返回觸發事件的元素
  • event.currentTarget

    返回綁定事件的元素

prototype和__proto__的關係是什麼
全部的對象都擁有__proto__屬性,它指向對象構造函數的prototype屬性

let obj = {}
obj.__proto__ === Object.prototype // true

function Test(){}
test.__proto__ == Test.prototype // true

全部的函數都同時擁有__proto__和protytpe屬性
函數的__proto__指向本身的函數實現 函數的protytpe是一個對象 因此函數的prototype也有__proto__屬性 指向Object.prototype

function func() {}
func.prototype.__proto__ === Object.prototype // true

Object.prototype.__proto__指向null

Object.prototype.__proto__ // null

原型繼承

全部的JS對象都有一個prototype屬性,指向它的原型對象。當試圖訪問一個對象的屬性時,若是沒有在該對象上找到,它還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾。

繼承

JS高程第3版 第6章 繼承
寄生組合式繼承

function SuperType(name) {
    this.name = name
    this.colors = ['red']
}

SuperType.prototype.sayName = function() {
    console.log(this.name)
}
// 繼承實例屬性
function SubType(name, age) {
    SuperType.call(this, name)
    this.age = age
}

function inheritPrototype(subType, superType) {
    let prototype = Object.create(superType.prototype)
    prototype.constructor = subType
    subType.prototype = prototype
}
// 繼承原型方法
inheritPrototype(SubType, SuperType)

// 定義本身的原型方法
SubType.prototype.sayAge = function() {
    console.log(this.age)
}

閉包

閉包是指有權訪問另外一個函數做用域中的變量的函數。

function sayHi(name) {
    return () => {
       console.log(`Hi! ${name}`)
    }
}
const test = sayHi('xiaoming')
test() // Hi! xiaoming

雖然sayHi函數已經執行完畢,可是其活動對象也不會被銷燬,由於test函數仍然引用着sayHi函數中的變量name,這就是閉包。

但也由於閉包引用着另外一個函數的變量,致使另外一個函數已經不使用了也沒法銷燬,因此閉包使用過多,會佔用較多的內存,這也是一個反作用。

有一個函數,參數是一個函數,返回值也是一個函數,返回的函數功能和入參的函數類似,但這個函數只能執行3次,再次執行無效,如何實現

這個題目是考察閉包的使用

function sayHi() {
    console.log('hi')
}

function threeTimes(fn) {
    let times = 0
    return () => {
        if (times++ < 3) {
            fn()
        }
    }
}

const newFn = threeTimes(sayHi)
newFn()
newFn()
newFn()
newFn()
newFn() // 後面兩次執行都無任何反應

經過閉包變量 times 來控制函數的執行

實現add函數,讓add(a)(b)和add(a,b)兩種調用結果相同

function add(a, b) {
    if (b === undefined) {
        return function(x) {
            return a + x
        }
    }

    return a + b
}

Ajax

Ajax(asynchronous JavaScript and XML)是使用客戶端上的許多 Web 技術,建立異步 Web 應用的一種 Web 開發技術。藉助 Ajax,Web 應用能夠異步(在後臺)向服務器發送數據和從服務器檢索數據,而不會干擾現有頁面的顯示和行爲。經過將數據交換層與表示層分離,Ajax 容許網頁和擴展 Web 應用程序動態更改內容,而無需從新加載整個頁面。實際上,如今一般將 JSON 替換爲 XML,由於 JavaScript 對 JSON 有原生支持優點。

XMLHttpRequest API 常常用於異步通訊。此外還有最近流行的fetch API。

let xmlhttp
if (window.XMLHttpRequest) {
    //  IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼
    xmlhttp = new XMLHttpRequest()
} else {
    // IE6, IE5 瀏覽器執行代碼
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
}
xmlhttp.onreadystatechange = () => {
    if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        document.getElementById("myDiv").innerHTML = xmlhttp.responseText
    }
}
xmlhttp.open("GET", "/ajax/test.txt", true)
xmlhttp.send()

使用Ajax的優缺點分別是什麼

優勢

  • 交互性更好。來自服務器的新內容能夠動態更改,無需從新加載整個頁面。
  • 減小與服務器的鏈接,由於腳本和樣式只須要被請求一次。
  • 狀態能夠維護在一個頁面上。JavaScript 變量和 DOM 狀態將獲得保持,由於主容器頁面未被從新加載。
  • 基本上包括大部分 SPA 的優勢。

缺點

  • 動態網頁很難收藏。
  • 若是 JavaScript 已在瀏覽器中被禁用,則不起做用。
  • 有些網絡爬蟲不執行 JavaScript,也不會看到 JavaScript 加載的內容。
  • 基本上包括大部分 SPA 的缺點。

https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questions.md

Ajax和Fetch區別

  • ajax是使用XMLHttpRequest對象發起的,可是用起來很麻煩,因此ES6新規範就有了fetch,fetch發一個請求不用像ajax那樣寫一大堆代碼。
  • 使用fetch沒法取消一個請求,這是由於fetch基於Promise,而Promise沒法作到這一點。
  • 在默認狀況下,fetch不會接受或者發送cookies
  • fetch沒有辦法原生監測請求的進度,而XMLHttpRequest能夠
  • fetch只對網絡請求報錯,對400,500都當作成功的請求,須要封裝去處理
  • fetch因爲是ES6規範,兼容性上比不上XMLHttpRequest

變量提高

var會使變量提高,這意味着變量能夠在聲明以前使用。let和const不會使變量提高,提早使用會報錯。
變量提高(hoisting)是用於解釋代碼中變量聲明行爲的術語。使用var關鍵字聲明或初始化的變量,會將聲明語句「提高」到當前做用域的頂部。 可是,只有聲明纔會觸發提高,賦值語句(若是有的話)將保持原樣。

使用let、var和const建立變量有什麼區別

用var聲明的變量的做用域是它當前的執行上下文,它能夠是嵌套的函數,也能夠是聲明在任何函數外的變量。let和const是塊級做用域,意味着它們只能在最近的一組花括號(function、if-else 代碼塊或 for 循環中)中訪問。

function foo() {
  // 全部變量在函數中均可訪問
  var bar = 'bar';
  let baz = 'baz';
  const qux = 'qux';

  console.log(bar); // bar
  console.log(baz); // baz
  console.log(qux); // qux
}

console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined
if (true) {
  var bar = 'bar';
  let baz = 'baz';
  const qux = 'qux';
}

// 用 var 聲明的變量在函數做用域上均可訪問
console.log(bar); // bar
// let 和 const 定義的變量在它們被定義的語句塊以外不可訪問
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined

var會使變量提高,這意味着變量能夠在聲明以前使用。let和const不會使變量提高,提早使用會報錯。

console.log(foo); // undefined

var foo = 'foo';

console.log(baz); // ReferenceError: can't access lexical declaration 'baz' before initialization

let baz = 'baz';

console.log(bar); // ReferenceError: can't access lexical declaration 'bar' before initialization

const bar = 'bar';

用var重複聲明不會報錯,但let和const會。

var foo = 'foo';
var foo = 'bar';
console.log(foo); // "bar"

let baz = 'baz';
let baz = 'qux'; // Uncaught SyntaxError: Identifier 'baz' has already been declared

let和const的區別在於:let容許屢次賦值,而const只容許一次。

// 這樣不會報錯。
let foo = 'foo';
foo = 'bar';

// 這樣會報錯。
const baz = 'baz';
baz = 'qux';

https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Chinese/questions/javascript-questions.md#%E4%BD%BF%E7%94%A8letvar%E5%92%8Cconst%E5%88%9B%E5%BB%BA%E5%8F%98%E9%87%8F%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB

對象淺拷貝和深拷貝有什麼區別

JS 中,除了基本數據類型,還存在對象、數組這種引用類型。
基本數據類型,拷貝是直接拷貝變量的值,而引用類型拷貝的實際上是變量的地址。

let o1 = {a: 1}
let o2 = o1

在這種狀況下,若是改變 o1o2 其中一個值的話,另外一個也會變,由於它們都指向同一個地址。

o2.a = 3
console.log(o1.a) // 3

而淺拷貝和深拷貝就是在這個基礎之上作的區分,若是在拷貝這個對象的時候,只對基本數據類型進行了拷貝,而對引用數據類型只是進行了引用的傳遞,而沒有從新建立一個新的對象,則認爲是淺拷貝。反之,在對引用數據類型進行拷貝的時候,建立了一個新的對象,而且複製其內的成員變量,則認爲是深拷貝。

怎麼實現對象深拷貝

let o1 = {a:{
    b:1
  }
}
let o2 = JSON.parse(JSON.stringify(o1))

另外一種方法

function deepCopy(s) {
    const d = {}
    for (let k in s) {
        if (typeof s[k] == 'object') {
            d[k] = deepCopy(s[k])
        } else {
            d[k] = s[k]
        }
    }

    return d
}

數組去重

ES5

function unique(arry) {
    const temp = []
    arry.forEach(e => {
        if (temp.indexOf(e) == -1) {
            temp.push(e)
        }
    })
    
    return temp
}

ES6

function unique (arr) {
   return Array.from(new Set(arr))
}

數據類型

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  6. Object
  7. symbol(ES6新增)

內置函數(原生函數)

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error
  • Symbol

原始值 "I am a string" 並非一個對象,它只是一個字面量,而且是一個不可變的值。
若是要在這個字面量上執行一些操做,好比獲取長度、訪問其中某個字符等,那須要將其
轉換爲 String 對象。
幸虧,在必要時語言會自動把字符串字面量轉換成一個 String 對象,也就是說你並不須要
顯式建立一個對象。

如何判斷數組與對象

Array.isArray([]) // true
Array.isArray({}) // false

typeof [] // "object"
typeof {} // "object"

Object.prototype == [].__proto__ // false
Object.prototype == {}.__proto__ // true
Array.prototype == [].__proto__ // true
Array.prototype == {}.__proto__ // false

自動分號

有時 JavaScript 會自動爲代碼行補上缺失的分號,即自動分號插入(Automatic SemicolonInsertion,ASI)。

由於若是缺失了必要的 ; ,代碼將沒法運行,語言的容錯性也會下降。ASI 能讓咱們忽略那些沒必要要的 ; 。

請注意,ASI 只在換行符處起做用,而不會在代碼行的中間插入分號。

若是 JavaScript 解析器發現代碼行可能由於缺失分號而致使錯誤,那麼它就會自動補上分
號。而且,只有在代碼行末尾與換行符之間除了空格和註釋以外沒有別的內容時,它纔會
這樣作。

浮點數精度

https://www.css88.com/archives/7340

cookie、localStorage、sessionStorage區別

特性 cookie localStorage sessionStorage
由誰初始化 客戶端或服務器,服務器能夠使用Set-Cookie請求頭。 客戶端 客戶端
數據的生命週期 通常由服務器生成,可設置失效時間,若是在瀏覽器生成,默認是關閉瀏覽器以後失效 永久保存,可清除 僅在當前會話有效,關閉頁面後清除
存放數據大小 4KB 5MB 5MB
與服務器通訊 每次都會攜帶在HTTP頭中,若是使用cookie保存過多數據會帶來性能問題 僅在客戶端保存 僅在客戶端保存
用途 通常由服務器生成,用於標識用戶身份 用於瀏覽器緩存數據 用於瀏覽器緩存數據
訪問權限 任意窗口 任意窗口 當前頁面窗口

自執行函數?用於什麼場景?好處?

自執行函數:一、聲明一個匿名函數二、立刻調用這個匿名函數。

做用:建立一個獨立的做用域。

好處:防止變量彌散到全局,以避免各類js庫衝突。隔離做用域避免污染,或者截斷做用域鏈,避免閉包形成引用變量沒法釋放。利用當即執行特性,返回須要的業務函數或對象,避免每次經過條件判斷來處理

場景:通常用於框架、插件等場景

多個頁面之間如何進行通訊

有以下幾個方式:

  • cookie
  • web worker
  • localeStorage和sessionStorage

css動畫和js動畫的差別

  1. 代碼複雜度,js 動畫代碼相對複雜一些
  2. 動畫運行時,對動畫的控制程度上,js 可以讓動畫,暫停,取消,終止,css動畫不能添加事件
  3. 動畫性能看,js 動畫多了一個js 解析的過程,性能不如 css 動畫好

https://zhuanlan.zhihu.com/p/41479807

如何實現文件斷點續傳

斷點續傳最核心的內容就是把文件「切片」而後再一片一片的傳給服務器,可是這看似簡單的上傳過程卻有着無數的坑。

首先是文件的識別,一個文件被分紅了若干份以後如何告訴服務器你切了多少塊,以及最終服務器應該如何把你上傳上去的文件進行合併,這都是要考慮的。

所以在文件開始上傳以前,咱們和服務器要有一個「握手」的過程,告訴服務器文件信息,而後和服務器約定切片的大小,當和服務器達成共識以後就能夠開始後續的文件傳輸了。

前臺要把每一塊的文件傳給後臺,成功以後前端和後端都要標識一下,以便後續的斷點。

當文件傳輸中斷以後用戶再次選擇文件就能夠經過標識來判斷文件是否已經上傳了一部分,若是是的話,那麼咱們能夠接着上次的進度繼續傳文件,以達到續傳的功能。
有了HTML5 的 File api以後切割文件比想一想的要簡單的多的多。

只要用slice 方法就能夠了

var packet = file.slice(start, end);

參數start是開始切片的位置,end是切片結束的位置 單位都是字節。經過控制start和end 就能夠是實現文件的分塊

file.slice(0,1000);
file.slice(1000,2000);
file.slice(2000,3000);
// ......

在把文件切成片以後,接下來要作的事情就是把這些碎片傳到服務器上。
若是中間掉線了,下次再傳的時候就得先從服務器獲取上一次上傳文件的位置,而後以這個位置開始上傳接下來的文件內容。

https://www.cnblogs.com/zhwl/p/3580776.html

new一個對象經歷了什麼

function Test(){}
const test = new Test()
  1. 建立一個新對象:
const obj = {}
  1. 設置新對象的constructor屬性爲構造函數的名稱,設置新對象的__proto__屬性指向構造函數的prototype對象
obj.constructor = Test
obj.__proto__ = Test.prototype
  1. 使用新對象調用函數,函數中的this被指向新實例對象
Test.call(obj)
  1. 將初始化完畢的新對象地址,保存到等號左邊的變量中

bind、call、apply的區別

call和apply實際上是同樣的,區別就在於傳參時參數是一個一個傳或者是以一個數組的方式來傳。

call和apply都是在調用時生效,改變調用者的this指向。

let name = 'Jack'
const obj = {name: 'Tom'}
function sayHi() {console.log('Hi! ' + this.name)}

sayHi() // Hi! Jack
sayHi.call(obj) // Hi! Tom

bind也是改變this指向,不過不是在調用時生效,而是返回一個新函數。

const newFunc = sayHi.bind(obj)
newFunc() // Hi! Tom

請簡述JavaScript中的this

JS 中的this是一個相對複雜的概念,不是簡單幾句能解釋清楚的。粗略地講,函數的調用方式決定了this的值。我閱讀了網上不少關於this的文章,Arnav Aggrawal 寫的比較清楚。this取值符合如下規則:

  1. 在調用函數時使用new關鍵字,函數內的this是一個全新的對象。
  2. 若是applycallbind方法用於調用、建立一個函數,函數內的 this 就是做爲參數傳入這些方法的對象。
  3. 當函數做爲對象裏的方法被調用時,函數內的this是調用該函數的對象。好比當obj.method()被調用時,函數內的 this 將綁定到obj對象。
  4. 若是調用函數不符合上述規則,那麼this的值指向全局對象(global object)。瀏覽器環境下this的值指向window對象,可是在嚴格模式下('use strict'),this的值爲undefined
  5. 若是符合上述多個規則,則較高的規則(1 號最高,4 號最低)將決定this的值。
  6. 若是該函數是 ES2015 中的箭頭函數,將忽略上面的全部規則,this被設置爲它被建立時的上下文。

想得到更深刻的解釋,請查看他在 Medium 上的文章

https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Chinese/questions/javascript-questions.md#%E8%AF%B7%E7%AE%80%E8%BF%B0javascript%E4%B8%AD%E7%9A%84this

如何肯定this指向

若是要判斷一個運行中函數的 this 綁定,就須要找到這個函數的直接調用位置。找到以後就能夠順序應用下面這四條規則來判斷 this 的綁定對象。

  1. 由 new 調用?綁定到新建立的對象。
  2. 由 call 或者 apply (或者 bind )調用?綁定到指定的對象。
  3. 由上下文對象調用?綁定到那個上下文對象。
  4. 默認:在嚴格模式下綁定到 undefined ,不然綁定到全局對象。

必定要注意,有些調用可能在無心中使用默認綁定規則。若是想「更安全」地忽略 this 綁定,你能夠使用一個 DMZ 對象,好比 ø = Object.create(null) ,以保護全局對象。

ES6 中的箭頭函數並不會使用四條標準的綁定規則,而是根據當前的詞法做用域來決定this ,具體來講,箭頭函數會繼承外層函數調用的 this 綁定(不管 this 綁定到什麼)。這其實和 ES6 以前代碼中的 self = this 機制同樣

參考:《你不知道的JavaScript》

== 和 ===的區別是什麼

==是抽象相等運算符,而===是嚴格相等運算符。==運算符是在進行必要的類型轉換後,再比較。===運算符不會進行類型轉換,因此若是兩個值不是相同的類型,會直接返回false。使用==時,可能發生一些特別的事情,例如:

1 == '1'; // true
1 == [1]; // true
1 == true; // true
0 == ''; // true
0 == '0'; // true
0 == false; // true

若是你對=====的概念不是特別瞭解,建議大多數狀況下使用===

箭頭函數和普通函數有什麼區別

  • 函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象,用call apply bind也不能改變this指向
  • 不能夠看成構造函數,也就是說,不能夠使用new命令,不然會拋出一個錯誤。
  • 不能夠使用arguments對象,該對象在函數體內不存在。若是要用,能夠用 rest 參數代替。
  • 不能夠使用yield命令,所以箭頭函數不能用做 Generator 函數。
  • 箭頭函數沒有原型對象prototype

首屏時間、白屏時間

Performance 接口能夠獲取到當前頁面中與性能相關的信息。

該類型的對象能夠經過調用只讀屬性 Window.performance 來得到。

白屏時間:

performance.timing.responseStart - performance.timing.navigationStart

首屏時間

window.onload = () => {
    new Date() - performance.timing.responseStart
}

https://developer.mozilla.org/zh-CN/docs/Web/API/Performance

當你在瀏覽器輸入一個地址後發生了什麼

https://github.com/skyline75489/what-happens-when-zh_CN/blob/master/README.rst?utm_medium=social&utm_source=wechat_session&from=timeline&isappinstalled=0

頁面大量圖片,如何優化加載,優化用戶體驗

  1. 圖片懶加載。在頁面的未可視區域添加一個滾動事件,判斷圖片位置與瀏覽器頂端的距離與頁面的距離,若是前者小於後者,優先加載。
  2. 若是爲幻燈片、相冊等,能夠使用圖片預加載技術,將當前展現圖片的前一張和後一張優先下載。
  3. 若是圖片爲css圖片,能夠使用CSSsprite,SVGsprite等技術。
  4. 若是圖片過大,能夠使用特殊編碼的圖片,加載時會先加載一張壓縮的特別厲害的縮略圖,以提升用戶體驗。
  5. 若是圖片展現區域小於圖片的真實大小,應在服務器端根據業務須要先進行圖片壓縮,圖片壓縮後大小與展現一致。

https://www.jianshu.com/p/5d82bba9e1a1

js網絡請求性能優化之防抖與節流

  • 防抖(debounce)

    在函數須要頻繁觸發時,只有當有足夠空閒的時間時,才執行一次。就好像在百度搜索時,每次輸入以後都有聯想詞彈出,這個控制聯想詞的方法就不多是輸入框內容一改變就觸發的,他必定是當你結束輸入一段時間以後纔會觸發。

  • 節流(thorttle)

    預約一個函數只有在大於等於執行週期時才執行,週期內調用不執行。就好像你在淘寶搶購某一件限量熱賣商品時,你不斷點刷新點購買,但是總有一段時間你點上是沒有效果,這裏就用到了節流,就是怕點的太快致使系統出現bug。

  • 區別

    在發生持續觸發事件時,防抖設置事件延遲並在空閒時間去觸發事件,而節流則是隔必定的時間觸發一次。

具體請看:

https://blog.csdn.net/jacoox/article/details/80719456

如何作到修改url參數頁面不刷新

HTML5引入了 history.pushState()history.replaceState() 方法,它們分別能夠添加和修改歷史記錄條目。

let stateObj = {
    foo: "bar",
};

history.pushState(stateObj, "page 2", "bar.html");

假設當前頁面爲 foo.html,執行上述代碼後會變爲 bar.html,點擊瀏覽器後退,會變爲 foo.html,但瀏覽器並不會刷新。
pushState() 須要三個參數: 一個狀態對象, 一個標題 (目前被忽略), 和 (可選的) 一個 URL. 讓咱們來解釋下這三個參數詳細內容:

  • 狀態對象 — 狀態對象 state 是一個 JavaScript 對象,經過 pushState () 建立新的歷史記錄條目。不管何時用戶導航到新的狀態,popstate 事件就會被觸發,且該事件的 state 屬性包含該歷史記錄條目狀態對象的副本。
    狀態對象能夠是能被序列化的任何東西。緣由在於 Firefox 將狀態對象保存在用戶的磁盤上,以便在用戶重啓瀏覽器時使用,咱們規定了狀態對象在序列化表示後有640k的大小限制。若是你給 pushState() 方法傳了一個序列化後大於 640k 的狀態對象,該方法會拋出異常。若是你須要更大的空間,建議使用 sessionStorage 以及 localStorage.

  • 標題 — Firefox 目前忽略這個參數,但將來可能會用到。傳遞一個空字符串在這裏是安全的,而在未來這是不安全的。二選一的話,你能夠爲跳轉的 state 傳遞一個短標題。

  • URL — 該參數定義了新的歷史URL記錄。注意,調用 pushState() 後瀏覽器並不會當即加載這個 URL,但可能會在稍後某些狀況下加載這個 URL,好比在用戶從新打開瀏覽器時。新URL沒必要須爲絕對路徑。若是新URL是相對路徑,那麼它將被做爲相對於當前 URL 處理。新 URL 必須與當前URL同源,不然 pushState() 會拋出一個異常。該參數是可選的,缺省爲當前 URL。

格式化金錢,每千分位加逗號

function format(str) {
    let s = ''
    let count = 0
    for (let i = str.length - 1; i >= 0; i--) {
        s = str[i] + s
        count++
        if (count % 3 == 0 && i != 0) {
            s = ',' + s
        }
    }
    return s
}
function format(str) {
    return str.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
}

請用js去除字符串空格

去除全部空格

str.replace(/\s/g, '')

去除兩邊空格

str.replace(/^\s+|\s+$/g, '')
// 原生方法
str.trim()




HTTP問題

RESTful

REST 指的是一組架構約束條件和原則。知足這些約束條件和原則的應用程序或設計就是 RESTful。

  • GET

    get方法在Rest中主要用於獲取資源,可以發送參數,不過有限制,且參數都會以?開頭的形 式附加在URL尾部。
    規範的get方法處理器應該是冪等的,也就是說對一個資源不論發送多少次get請求都不會更改數據或形成破壞。
  • POST

    post方法在Rest請求中主要用於添加資源,參數信息存放在請求報文的消息體中相對安全,且可發送較大信息
  • PUT

    put方法在Rest中主要用於更新資源,由於大多數瀏覽器不支持put和delete,會自動將put和delete請求轉化爲get和post. 所以爲了使用put和delete方法,
    須要以post發送請求,在表單中使用隱藏域發送真正的請求。
    put方法的參數是同post同樣是存放在消息中的,一樣具備安全性,可發送較大信息。
    put方法是冪等的,對同一URL資源作出的同一數據的任意次put請求其對數據的改變都是一致的。
  • DELETE

    Delete在Rest請求中主要用於刪除資源,由於大多數瀏覽器不支持put和delete,會自動將put和delete請求轉化爲get和post。
    所以爲了使用put和delete方法,須要以post發送請求,在表單中使用隱藏域發送真正的請求。
    Delete方法的參數同post同樣存放在消息體中,具備安全性,可發送較大信息 Delete方法是冪等的,不論對同一個資源進行多少次delete請求都不會破壞數據

https://blog.csdn.net/jnshu_it/article/details/80203696

GET和POST的區別

  • GET產生一個TCP數據包;POST產生兩個TCP數據包。
  • GET在瀏覽器回退時是無害的,而POST會再次提交請求。
  • GET產生的URL地址能夠被Bookmark,而POST不能夠。
  • GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
  • GET請求只能進行url編碼,而POST支持多種編碼方式。
  • GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。
  • GET請求在URL中傳送的參數是有長度限制的,而POST麼有。
  • 對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
  • GET比POST更不安全,由於參數直接暴露在URL上,因此不能用來傳遞敏感信息。
  • GET參數經過URL傳遞,POST放在Request body中。

Accept和Content-Type

Accept 請求頭用來告知客戶端能夠處理的內容類型,這種內容類型用MIME類型來表示。
服務器使用 Content-Type 應答頭通知客戶端它的選擇。

Accept: text/html
Accept: image/*
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

1.Accept屬於請求頭, Content-Type屬於實體頭。

Http報頭分爲通用報頭,請求報頭,響應報頭和實體報頭。

請求方的http報頭結構:通用報頭|請求報頭|實體報頭

響應方的http報頭結構:通用報頭|響應報頭|實體報頭

2.Accept表明發送端(客戶端)但願接受的數據類型。

好比:Accept:text/xml;

表明客戶端但願接受的數據類型是xml類型

Content-Type表明發送端(客戶端|服務器)發送的實體數據的數據類型。

好比:Content-Type:text/html;

表明發送端發送的數據格式是html。

兩者合起來,

Accept:text/xml;

Content-Type:text/html

即表明但願接受的數據類型是xml格式,本次請求發送的數據的數據格式是html。

狀態碼

狀態碼 類別 描述
1xx Informational(信息狀態碼) 接受請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 須要附加操做已完成請求
4xx Client Error(客戶端錯誤狀態碼) 服務器沒法處理請求
5xx Server Error(服務器錯誤狀態碼) 服務器處理請求出錯

HTTP緩存

https://segmentfault.com/a/1190000010690320

如何處理不讓別人盜用你的圖片,訪問你的服務器資源

  • http header, 對refer作判斷看來源是否是本身的網站,若是不是就拒絕
  • 經過session校驗,若是不經過特定服務生成cookie和session就不能請求獲得資源

Http與Https的區別

  • HTTP 的URL 以http:// 開頭,而HTTPS 的URL 以https:// 開頭
  • HTTP 是不安全的,而 HTTPS 是安全的
  • HTTP 標準端口是80 ,而 HTTPS 的標準端口是443
  • 在OSI 網絡模型中,HTTP工做於應用層,而HTTPS 的安全傳輸機制工做在傳輸層
  • HTTP 沒法加密,而HTTPS 對傳輸的數據進行加密
  • HTTP無需證書,而HTTPS 須要CA機構wosign的頒發的SSL證書

https://zhuanlan.zhihu.com/p/33778904

什麼是Http協議無狀態協議?怎麼解決Http協議無狀態協議?

無狀態協議對於事務處理沒有記憶能力。缺乏狀態意味着若是後續處理須要前面的信息也就是說,

當客戶端一次HTTP請求完成之後,客戶端再發送一次HTTP請求,HTTP並不知道當前客戶端是一個」老用戶「。

能夠使用Cookie來解決無狀態的問題,Cookie就至關於一個通行證,第一次訪問的時候給客戶端發送一個Cookie,

當客戶端再次來的時候,拿着Cookie(通行證),那麼服務器就知道這個是」老用戶「。

https://zhuanlan.zhihu.com/p/33778904

經常使用的HTTP方法有哪些

  • GET:用於請求訪問已經被URL(統一資源標識符)識別的資源,能夠經過URL傳參給服務器。
  • POST:用於傳輸信息給服務器,主要功能與Get方法相似,但通常推薦POST方式。
  • PUT:傳輸文件,報文主體包含文件內容,保存到對應URL位置。
  • HEAD:獲取報文首部,與GET方法相似,只是不返回報文主體,通常用於驗證URL是否有效。
  • DELET:刪除文件,與PUT方法相反,刪除對應URL位置的文件。OPTIONS:查詢相應URL支持的HTTP方法。

一次完整的HTTP請求所經歷的7個步驟

HTTP通訊機制是在一次完整的HTTP通訊過程當中,Web瀏覽器與Web服務器之間將完成下列7個步驟:

  • 創建TCP鏈接

在HTTP工做開始以前,Web瀏覽器首先要經過網絡與Web服務器創建鏈接,該鏈接是經過TCP來完成的,該協議與IP協議共同構建 Internet,即著名的TCP/IP協議族,所以Internet又被稱做是TCP/IP網絡。HTTP是比TCP更高層次的應用層協議,根據規則, 只有低層協議創建以後才能,才能進行更層協議的鏈接,所以,首先要創建TCP鏈接,通常TCP鏈接的端口號是80。

  • Web瀏覽器向Web服務器發送請求行

一旦創建了TCP鏈接,Web瀏覽器就會向Web服務器發送請求命令。例如:GET /sample/hello.jsp HTTP/1.1。

  • Web瀏覽器發送請求頭

瀏覽器發送其請求命令以後,還要以頭信息的形式向Web服務器發送一些別的信息,以後瀏覽器發送了一空白行來通知服務器,它已經結束了該頭信息的發送。

  • Web服務器應答

客戶機向服務器發出請求後,服務器會客戶機回送應答, HTTP/1.1 200 OK ,應答的第一部分是協議的版本號和應答狀態碼。

  • Web服務器發送應答頭

正如客戶端會隨同請求發送關於自身的信息同樣,服務器也會隨同應答向用戶發送關於它本身的數據及被請求的文檔。

  • Web服務器向瀏覽器發送數據

Web服務器向瀏覽器發送頭信息後,它會發送一個空白行來表示頭信息的發送到此爲結束,接着,它就以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據。

  • Web服務器關閉TCP鏈接

通常狀況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP鏈接,而後若是瀏覽器或者服務器在其頭信息加入了這行代碼:

Connection:keep-alive

TCP鏈接在發送後將仍然保持打開狀態,因而,瀏覽器能夠繼續經過相同的鏈接發送請求。保持鏈接節省了爲每一個請求創建新鏈接所需的時間,還節約了網絡帶寬。

創建TCP鏈接->發送請求行->發送請求頭->(到達服務器)發送狀態行->發送響應頭->發送響應數據->斷TCP鏈接

https://juejin.im/post/5a8102e0f265da4e710f5910




Vue問題

什麼是mvvm

MVVM最先由微軟提出來,它借鑑了桌面應用程序的MVC思想,在前端頁面中,把Model用純JavaScript對象表示,View負責顯示,二者作到了最大限度的分離
把Model和View關聯起來的就是ViewModel。

ViewModel負責把Model的數據同步到View顯示出來,還負責把View的修改同步回Model

View 和 Model 之間的同步工做徹底是自動的,無需人爲干涉(由viewModel完成,在這裏指VUE)

所以開發者只需關注業務邏輯,不須要手動操做DOM, 不須要關注數據狀態的同步問題,複雜的數據狀態維護徹底由 MVVM 來統一管理

ViewModel如何編寫?

須要用JavaScript編寫一個通用的ViewModel,這樣,就能夠複用整個MVVM模型了

一個MVVM框架和jQuery操做DOM相比有什麼區別?
咱們先看用jQuery實現的修改兩個DOM節點的例子:

<!-- HTML -->
<p>Hello, <span id="name">Bart</span>!</p>
<p>You are <span id="age">12</span>.</p>

Hello, Bart!

You are 12.

用jQuery修改name和age節點的內容:

var name = 'Homer';
var age = 51;

$('#name').text(name);
$('#age').text(age);

若是咱們使用MVVM框架來實現一樣的功能,咱們首先並不關心DOM的結構,而是關心數據如何存儲。最簡單的數據存儲方式是使用JavaScript對象:

var person = {
    name: 'Bart',
    age: 12
}

咱們把變量person看做Model,把HTML某些DOM節點看做View,並假定它們之間被關聯起來了。

要把顯示的name從Bart改成Homer,把顯示的age從12改成51,咱們並不操做DOM,而是直接修改JavaScript對象:

person.name = 'Homer';
person.age = 51;

執行上面的代碼,咱們驚訝地發現,改變JavaScript對象的狀態,會致使DOM結構做出對應的變化!這讓咱們的關注點從如何操做DOM變成了如何更新JavaScript對象的狀態,而操做JavaScript對象比DOM簡單多了!

這就是MVVM的設計思想:關注Model的變化,讓MVVM框架去自動更新DOM的狀態,從而把開發者從操做DOM的繁瑣步驟中解脫出來!
下圖能夠很好的解釋view viewModel model之間的關係

在這裏插入圖片描述

Vue的優勢是什麼

mvvm的優勢便是vue的優勢,在這裏再總結一下:

數據和視頻之間的同步工做徹底是自動的,無需人爲干涉,因此開發者只需關注業務邏輯,不須要手動操做DOM, 不須要關注數據狀態的同步問題,
複雜的數據狀態維護徹底由 MVVM 來統一管理,節省了不少精力。

對於生命週期的理解

建立一個Vue實例,是一個漫長的過程,要經歷初始化,數據合併,模板解析,數據渲染等等一系列過程。
因此,爲了能實如今這個過程裏面插入本身想要提早作的事情,就有了生命週期鉤子函數。

舉個例子:

一輛公交車,從出發點A站到終點站B,中間有不少站點,公交車每到一個站點,就得停下來,
等待客人上車,而後再駛往下一個站點,一直到終點站爲止。
A和B之間的站點,就像是這個路程的生命週期。每個站點都是一個不一樣的生命週期(站點名不一樣),
只要到了站點,就得執行該站點對應的生命週期函數,
只不過每一個站點的生命週期函數都是同樣的(等待客人上車)。

Vue中的生命週期也是同樣,對應了Vue實例從建立到結束之間的每個過程。
例如,Vue的beforeCreate週期,指的就是Vue在實例初始化以後,數據觀測 (data observer) 和 event/watcher 事件配置以前被調用。

至於Vue具體的生命週期函數有哪些,請看官網API文檔

組件傳值

  • 父組件經過prop向子組件傳值
  • 子組件經過事件向父組件傳值
  • 子組件與子組件之間不能直接傳值,須要經過父組件來作間接傳值,在這種狀況下推薦使用vuex

具體例子請看官方文檔

vue數據綁定原理

Vue的數據雙向綁定都是依據Object.defineProperty()這一方法來作的

Object.defineProperty到底有什麼做用呢?
MDN

Object.defineProperty(obj, prop, descriptor)

obj
要在其上定義屬性的對象。

prop
要定義或修改的屬性的名稱。

descriptor
將被定義或修改的屬性描述符。

簡單來講 這個方法能夠定義一個對象某個屬性的描述符

咱們須要用到的就是描述符當中的getter和setter

const obj = {a:1}
obj.a // 1

obj.a = 2

像上面代碼中的兩個操做 讀取和賦值 就是在訪問obj.a的getter和setter

當咱們輸入obj.a時 就是在訪問obj對象a屬性的getter 當輸入obj.a = 2 時就是在訪問obj對象a屬性的setter

Object.defineProperty(obj, 'a', {
  get : function(){
    return val
  },
  set : function(newValue){
    val = newValue
  },
  enumerable : true,
  configurable : true
})

getter和setter都是一個函數 咱們還能夠這樣作 例如

get: function() {
  // 每次訪問obj.a時都會執行這段代碼
  console.log('hello, 你在讀取a的值')
  return val
}
set: function(newValue) {
  val = newValue
  // 每次給obj.a賦值時都會執行這段代碼
  console.log('你設置了a的值')
}

Vue的雙向數據綁定就是根據上面的原理來實現的
只要在讀取值時收集觀察者 在賦值時觸發觀察者更新函數 就能夠實現數據變動 從而實現DOM從新渲染

說到這可能還不是很明白 不要急 慢慢來 先看一下這段代碼 複製放到HTML文件裏本身運行一下
而後打開網頁 在控制檯裏輸入data.user.name看看 會有驚喜

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>動態數據綁定(一)</title>
</head>
<body>
 <script>
    var data = {
        user: {
            name: 'xiaoming',
            age: 18,
            occupation: 'frontend'
        },
        address: {
            city: 'shaoguan'
        }
    }; 
    function Observer(data) {
        this.data = data;
        this.walk(data);
    }
    Observer.prototype = {
        walk: function(obj) {
            var value,
                key;
            for (key in obj) {
                if (obj.hasOwnProperty(key)) {
                    value = obj[key];
                    if (typeof value === 'object') {
                        new Observer(value);
                    }
                    this.convert(key, value); 
                }   
            }
        },
        convert: function(key, value) {
            Object.defineProperty(this.data, key, {
                get : function(){ 
                    console.log("你訪問了" + key);
                    return value; 
                },
                set : function(newValue){ 
                    value = newValue; 
                    console.log('你設置了' + key + '=' + value);
                }
            });
        }
    }  
    var example = new Observer(data);
 </script>   
</body>
</html>

vue-router原理

說簡單點,vue-router的原理就是經過對URL地址變化的監聽,繼而對不一樣的組件進行渲染。

每當URL地址改變時,就對相應的組件進行渲染。原理是很簡單,實現方式可能有點複雜,主要有hash模式和history模式。

若是想了解得詳細點,建議百度或者閱讀源碼。

vuex原理

vuex的原理其實很是簡單,它爲何能實現全部的組件共享同一份數據?

由於vuex生成了一個store實例,而且把這個實例掛在了全部的組件上,全部的組件引用的都是同一個store實例。

store實例上有數據,有方法,方法改變的都是store實例上的數據。因爲其餘組件引用的是一樣的實例,因此一個組件改變了store上的數據,
致使另外一個組件上的數據也會改變,就像是一個對象的引用。

若是對vuex的實現有興趣,能夠看看我本身造的一個vue輪子對應的vuex插件。它實現了除vuex模塊外的全部功能。

v-if和v-show的區別

v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。

v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。

相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。

通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用v-if 較好。

https://cn.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show

vue怎麼實現頁面的權限控制

利用 vue-routerbeforeEach 事件,能夠在跳轉頁面前判斷用戶的權限(利用 cookie 或 token),是否可以進入此頁面,若是不能則提示錯誤或重定向到其餘頁面,在後臺管理系統中這種場景常常能遇到。

keep-alive有什麼做用

Vue 中,每次切換組件時,都會從新渲染。若是有多個組件切換,又想讓它們保持原來的狀態,避免從新渲染,這個時候就能夠使用 keep-alive
keep-alive 能夠使被包含的組件保留狀態,或避免從新渲染。

計算屬性有什麼做用

先來看一下計算屬性的定義:

當其依賴的屬性的值發生變化的時,計算屬性會從新計算。反之則使用緩存中的屬性值。

計算屬性和vue中的其它數據同樣,都是響應式的,只不過它必須依賴某一個數據實現,而且只有它依賴的數據的值改變了,它纔會更新。

$route和$router的區別

$route 是路由信息對象,包括pathparamshashqueryfullPathmatchedname 等路由信息參數。

$router 是路由實例對象,包括了路由的跳轉方法,鉤子函數等

watch的做用是什麼

watch 主要做用是監聽某個數據值的變化。和計算屬性相比除了沒有緩存,做用是同樣的。

藉助 watch 還能夠作一些特別的事情,例如監聽頁面路由,當頁面跳轉時,咱們能夠作相應的權限控制,拒絕沒有權限的用戶訪問頁面。

相關文章
相關標籤/搜索