前言:本文會羅列出十道比較基礎(chǔ)的題目,我個(gè)人作為剛?cè)腴T的初級前端,寫這篇文章正好可以總結(jié)匯總一下近期的知識,看到這篇文章的朋友也可以看看這十道題你是否都能正確的、完整的答出來。我個(gè)人會總結(jié)出答案放于文后,歡迎討論。
題目詳情:
1、請寫出一個(gè)符合 W3C 規(guī)范的 HTML 文件,要求如下:
- 頁面標(biāo)題為「我的頁面」
- 頁面中引入了一個(gè)外部 CSS 文件,文件路徑為 /style.css
- 頁面中引入了另一個(gè)外部 CSS 文件,路徑為 /print.css,該文件僅在打印時(shí)生效
- 頁面中引入了另一個(gè)外部 CSS 文件,路徑為 /mobile.css,該文件僅在設(shè)備寬度小于 500 像素時(shí)生效
- 頁面中引入了一個(gè)外部 JS 文件,路徑為 /main.js
- 頁面中引入了一個(gè)外部 JS 文件,路徑為 /gbk.js,文件編碼為 GBK
- 頁面中有一個(gè) SVG 標(biāo)簽,SVG 里面有一個(gè)直徑為 100 像素的圓圈,顏色隨意
- 注意題目中的路徑
2、 移動端是怎么做適配的?
注:回答要點(diǎn):
- meta viewport
- 媒體查詢
- 動態(tài) rem 方案
3、用過CSS3嗎? 實(shí)現(xiàn)圓角矩形和陰影怎么做?
4、什么是閉包,閉包的用途是什么?
5、函數(shù)中call
、apply
、bind
的用法分別是什么?
6、請說出至少 8 個(gè) HTTP 狀態(tài)碼,并描述各狀態(tài)碼的意義。
7、請寫出一個(gè) HTTP post 請求的內(nèi)容,包括四部分。
其中
第四部分的內(nèi)容是 username=ff&password=123
第二部分必須含有 Content-Type
字段
請求的路徑為 /path
8、請說出至少三種排序的思路,這三種排序的時(shí)間復(fù)雜度分別為
- O(n*n)
- O(n log2 n)
- O(n + max)
9、一個(gè)頁面從輸入 URL 到頁面加載顯示完成,這個(gè)過程中都發(fā)生了什么?
10、如何實(shí)現(xiàn)數(shù)組去重?
假設(shè)有數(shù)組 array = [1,5,2,3,4,2,3,1,3,4]
你要寫一個(gè)函數(shù) unique,使得
unique(array)
的值為 [1,5,2,3,4]
也就是把重復(fù)的值都去掉,只保留不重復(fù)的值。
要求:
- 不要做多重循環(huán),只能遍歷一次
- 請給出兩種方案,一種能在 ES 5 環(huán)境中運(yùn)行,一種能在 ES 6 環(huán)境中運(yùn)行(提示 ES 6 環(huán)境多了一個(gè) Set 對象)
參考答案
注:答案為我個(gè)人總結(jié)而得,僅供參考,歡迎討論。
No.1 HTML基本格式 & 媒體查詢 & <svg>
& 文件編碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的頁面</title>
<link rel="stylesheet" href="./style.css">
<link rel="stylesheet" href="./print.css" media="print">
<link rel="stylesheet" href="./mobile.css" media="(max-width:500px)">
</head>
<body>
<svg>
<circle cx="50" cy="50" r="50" fill="red"/>
</svg>
<script src="./main.js"></script>
<script src="./gbk.js" charset="gbk"></script>
</body>
</html>
- 媒體查詢詳見下一題。
- 關(guān)于文件編碼,一般情況下都是后端來設(shè)置,但是為了以防萬一,我們可以在引入如css,js文件時(shí),順便也設(shè)置一下引入文件的文件編碼保證不會出錯(cuò)。
舉例說明:<script src="./gbk.js" charset="gbk"></script>
- 關(guān)于
<svg>
,詳情可以看MDN文檔,這里僅對題目要求進(jìn)行解釋:
<svg>
中,畫圓使用<circle>
標(biāo)簽,其中cx
、cy
屬性指的是圓心的坐標(biāo),r
指的是圓的半徑,需要注意的是,svg
填充顏色用的是fill
屬性。
No.2 移動端適配:meta viewport
& 媒體查詢 & 動態(tài)rem
關(guān)于meta viewport
和 媒體查詢詳情可參考這篇博客
關(guān)于動態(tài)rem詳情可參考這篇博客
移動端的適配有以下要點(diǎn):
首先必須使用這么一行代碼來禁止手機(jī)自動縮放頁面:
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
,
其中width=device-width
意思是頁面寬度等于設(shè)備寬度、user-scalable=no
禁止用戶縮放頁面、initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
即原始縮放比例,最大縮放比例,最小縮放比例都是1.0使用 media 查詢來響應(yīng)不同分辨率
如在引入外部樣式時(shí),只有滿足條件最大寬度為800px時(shí),example.css才生效:
<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
在CSS內(nèi)部,也可以用media來設(shè)置特定的情況下讓某些樣式生效,如下,即當(dāng)最大寬度為600px時(shí),該樣式生效:
<style>
@media (max-width: 600px) {
……
}
</style>
- 使用動態(tài) REM 方案保證手機(jī)端的顯示效果
rem指的是根元素的字體大小,根元素一般指的是<html>
動態(tài)rem即在js中設(shè)置
var pageWidth = window.innerWidth
document.write('<style>html{font-size:'+pageWidth/10+'px;}</style>')
讓1rem=0.1設(shè)備寬度,然后所有的css寬高使用rem為單位即可。
使用scss可以自動讓px轉(zhuǎn)化為rem:
@function px( $px ){
@return $px/$designWidth*10 + rem;
}
$designWidth : 640; // 640 是設(shè)計(jì)稿的寬度,你要根據(jù)設(shè)計(jì)稿的寬度填寫。
No.3 CSS3 & 圓角矩形 & 陰影
-
CSS3 MDN文檔
css3 中的新特性,比較常用的:
新增加的偽類如nth-child()
等、flex
布局、使用transform
對元素進(jìn)行變換、transition
過度,通過定義keyframes
做一些動畫效果、添加陰影box-shadow
、移動端適配中會用到媒體查詢等。 -
border-radious 文檔
- 后面接一個(gè)值時(shí):為元素的四個(gè)角都設(shè)置相同的圓角;
- 后面接兩個(gè)值:第一個(gè)值設(shè)置的是左上角和右下角的值,第二個(gè)值指的是右上角和左下角的值;
- 后面接四個(gè)值時(shí):四個(gè)值分別設(shè)置的圓角順序?yàn)?,從左上角開始順時(shí)針的四個(gè)角,即分別為左上角,右上角,右下角,左下角。
- 如果我們要做一個(gè)圓形,可以這么寫:
border-radious:50%;
- 使用圓角還可以做橢圓:border-radius還可以用斜杠設(shè)置第二組值。這時(shí),第一組值表示水平半徑,第二組值表示垂直半徑。第二組值也可以同時(shí)設(shè)置1到4個(gè)值,應(yīng)用規(guī)則與第一組值相同。如:
border-radius: 15px 5px 25px 5px / 3px 5px 10px 15px;
-
box-shadow 文檔
box-shadow
可以使用一個(gè)或多個(gè)投影,如果使用多個(gè)投影時(shí)必須需要用逗號“,”分開。用法如下:
對象選擇器 {box-shadow:inset x-offset y-offset blur-radius spread-radius color}
對象選擇器 {box-shadow:投影方式 X軸偏移量 Y軸偏移量 陰影模糊半徑 陰影擴(kuò)展半徑 陰影顏色}
No.4 閉包
- 閉包的定義:如果一個(gè)函數(shù)使用了它范圍外的變量,那么(這個(gè)函數(shù)和這個(gè)變量)就叫做閉包。舉個(gè)例子:
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
上述代碼中,變量local
和函數(shù)bar
合稱為閉包,即在函數(shù)bar
中使用了函數(shù)外定義的變量local
。
- 閉包的用途:我們之所以使用閉包,是應(yīng)為閉包可以用來「間接訪問一個(gè)變量」。換句話說,「隱藏一個(gè)變量」。
舉個(gè)例子:
!function(){
var lives = 50
window.addLives = function(){
lives += 1
}
window.reduceLives = function(){
lives -= 1
}
}()
上述代碼中,變量lives
為局部變量,該立即函數(shù)的外面是無法直接訪問該變量的,在該立即執(zhí)行函數(shù)內(nèi)部,聲明了addLives
函數(shù)和reduceLives
函數(shù),由此我們可以在函數(shù)外部通過調(diào)用這兩個(gè)函數(shù)來間接地調(diào)用lives
這個(gè)變量。這就是閉包的意義所在。
總結(jié):閉包的用處:
- 可以間接調(diào)用函數(shù)內(nèi)部的局部變量。
- 可以讓這些變量的值始終保持在內(nèi)存中。
- 可以暫存數(shù)據(jù),給變量開辟私密空間,避免外部污染
No.5 call
& apply
& bind
的用法
參考博客
在 javascript 中,call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上下文(context)而存在的,換句話說,就是為了改變函數(shù)體內(nèi)部 this 的指向。
call()
方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值和分別地提供的參數(shù)(參數(shù)的列表)。apply()
方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值,以及作為一個(gè)數(shù)組(或類似數(shù)組的對象)提供的參數(shù)。bind()
方法創(chuàng)建一個(gè)新的函數(shù),被調(diào)用時(shí),將其this關(guān)鍵字設(shè)置為提供的值,在調(diào)用新函數(shù)時(shí),在任何提供之前提供一個(gè)給定的參數(shù)序列。對于
apply
、call
二者而言,作用完全一樣,只是接受參數(shù)的方式不太一樣,call
需要把參數(shù)按順序傳遞進(jìn)去,而apply
則是把參數(shù)放在數(shù)組里。apply
、call
、bind
三者都是用來改變函數(shù)的this對象的指向的;
apply
、call
、bind
三者第一個(gè)參數(shù)都是this要指向的對象,也就是想指定的上下文;
apply
、call
、bind
三者都可以利用后續(xù)參數(shù)傳參;
bind
是返回對應(yīng)函數(shù),便于稍后調(diào)用;apply
、call
則是立即調(diào)用 。
舉例說明:
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
// 三個(gè)輸出的都是81,但是注意看使用 bind() 方法的,他后面多了對括號。
//也就是說,區(qū)別是,當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時(shí)候,使用 bind() 方法。而 apply/call 則會立即執(zhí)行函數(shù)。
No.6 HTTP 狀態(tài)碼
HTTP狀態(tài)碼 維基百科
一篇更形象的介紹狀態(tài)碼的博客
下面列舉一些比較常見的狀態(tài)碼
- 1xx消息:代表請求已被接受,需要繼續(xù)處理。這類響應(yīng)是臨時(shí)響應(yīng),只包含狀態(tài)行和某些可選的響應(yīng)頭信息,并以空行結(jié)束。(不常用,大致知道即可)
2XX:表示成功
- 200 OK:請求已成功,請求所希望的響應(yīng)頭或數(shù)據(jù)體將隨此響應(yīng)返回。
- 204 No Content:表示請求已成功處理,但是沒有內(nèi)容返回,意思等同于請求執(zhí)行成功,但是沒有數(shù)據(jù),瀏覽器不用刷新頁面,也不用導(dǎo)向新的頁面。
- 206 Partial Content:服務(wù)器已經(jīng)成功處理了部分GET請求。(客戶端進(jìn)行了范圍請求) 響應(yīng)報(bào)文中包含Content-Range指定范圍的實(shí)體內(nèi)容。
3XX:重定向
- 301 Moved Permanently:表示訪問的資源被永久移除,即請求的資源已經(jīng)永久的搬到了其他位置 。
- 302 Found :表示所訪問的資源臨時(shí)被移除,以后還會回來,即臨時(shí)重定向,表示請求的資源臨時(shí)搬到了其他位置 。
- 303 See Other :表示請求資源存在另一個(gè)URI,應(yīng)使用GET定向獲取請求資源 。
- 304 Not Modified :表示資源未被修改,即客戶端仍然具有以前下載的副本,不需要重新傳輸資源。
- 307 Temporary Redirect:臨時(shí)重定向,和302有著相同含義 ,盡管302標(biāo)準(zhǔn)禁止POST變?yōu)镚ET,但沒人聽他的 ,而307就會遵照標(biāo)準(zhǔn),不會從POST變?yōu)镚ET
但處理響應(yīng)行為,各個(gè)瀏覽器可能不同。
4XX:客戶端錯(cuò)誤
- 400 Bad Request:表示請求報(bào)文存在語法錯(cuò)誤或參數(shù)錯(cuò)誤,服務(wù)器不理解 ,服務(wù)器不應(yīng)該重復(fù)提交這個(gè)請求 ,需要修改請求內(nèi)容后再次發(fā)送。
- 401 Unauthorized:表示發(fā)送的請求需要有HTTP認(rèn)證信息或者是認(rèn)證失敗了 ,返回401的響應(yīng)必須包含一個(gè)適用于被請求資源的WWW-Authenticate首部以質(zhì)詢用戶信息 ,瀏覽器初次接受401時(shí),會彈出認(rèn)證窗口。
- 403 Forbidden :表示對請求資源的訪問被服務(wù)器拒絕了 ,服務(wù)器可以對此作出解釋,也可以不解釋 ,想說明的話可以在響應(yīng)實(shí)體的主體部分描述原因 。比如說你可能沒有訪問權(quán)限。
- 404 Not Found:表示服務(wù)器找不到你請求的資源 ,但允許用戶的后續(xù)請求。
5XX:服務(wù)器錯(cuò)誤
- 500 Internal Server Error:通用錯(cuò)誤消息,服務(wù)器遇到了一個(gè)未曾預(yù)料的狀況,導(dǎo)致了它無法完成對請求的處理。沒有給出具體錯(cuò)誤信息。
- 502 Bad Gateway:作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請求時(shí),從上游服務(wù)器接收到無效的響應(yīng)。
- 503 Service Unavailable:表示服務(wù)器超負(fù)載或正停機(jī)維護(hù),無法處理請求 ,如果服務(wù)器知道還需要多長時(shí)間,就寫入Retry-After首部字段返回。
No.7 HTTP post 請求
具體格式,參照博客
參考答案:
POST /path HTTP/1.1
Host: www.baidu.com
User-Agent: curl/7.54.0
Accept: */*
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
username=ff&password=123
注意:第二部分一般都要有Host
、Content-Length
、Content-Type
No.8 排序算法
排序算法維基百科 ,很多前端對算法的了解都很淺,但在面試中大多時(shí)候都會考察一些算法的知識,所以最基本的排序算法我們還是應(yīng)該大致了解一下的。下面大概提幾個(gè)常見的排序算法思路。注:這個(gè)網(wǎng)站提供了常見排序算法的動態(tài)展示效果。
- 冒泡排序,時(shí)間復(fù)雜度O(n^2):
遍歷整個(gè)數(shù)組,比較每相鄰兩個(gè)元素,將小的排在前面,大的排后面,這樣就可以得到最大的元素,遍歷除了已經(jīng)排序過的在最后的最大值,重復(fù)以上操作。 - 選擇排序,時(shí)間復(fù)雜度O(n^2):
遍歷整個(gè)數(shù)組,選擇一個(gè)最小的數(shù)字放在第一位,然后遍歷剩下的數(shù)字,在剩下的數(shù)字中選擇最小的放在第二位,以此類推。 - 插入排序,時(shí)間復(fù)雜度O(n^2):
先排好前兩個(gè)數(shù)字的順序,從第三個(gè)數(shù)字開始,與已經(jīng)排好的數(shù)字對比,將其插入到對應(yīng)的位置,以此類推 - 歸并排序,時(shí)間復(fù)雜度O(nlog n):
把數(shù)據(jù)分為兩段,從兩段中逐個(gè)選最小的元素移入新數(shù)據(jù)段的末尾。 - 快速排序,時(shí)間復(fù)雜度O(nlog n):
找其中的一個(gè)數(shù)作為標(biāo)桿,小于標(biāo)桿的數(shù)字放在左邊,大于標(biāo)桿的數(shù)字放在右邊,這一次排完之后再重復(fù)前面的操作,直到只有一個(gè)數(shù)字為止 - 計(jì)數(shù)排序,時(shí)間復(fù)雜度O(n + max):
統(tǒng)計(jì)小于等于該元素值的元素的個(gè)數(shù)i,于是該元素就放在目標(biāo)數(shù)組的索引i位 - 桶排序,時(shí)間復(fù)雜度O(n):
將值為i的元素放入i號桶,最后依次把桶里的元素倒出來。 - 基數(shù)排序,時(shí)間復(fù)雜度O(K × n):
創(chuàng)建10個(gè)桶,給每個(gè)數(shù)位(0到9),從個(gè)位數(shù)開始遍歷數(shù)列中的每個(gè)元素的數(shù)位,把每個(gè)元素按照隊(duì)列排列到對應(yīng)數(shù)位的桶中,再從隊(duì)列中恢復(fù)至數(shù)列,再遍歷十位數(shù),重復(fù)以上操作,直到遍歷到最大元素的位數(shù)。 - 堆排序,時(shí)間復(fù)雜度O(nlogn):
1、將已知數(shù)組看成一個(gè)完全二叉樹;
2、從二叉樹最后一層最右邊開始遍歷(即數(shù)組的最后一個(gè)數(shù));
3、進(jìn)行最大堆調(diào)整,使得最頂層的數(shù)成為數(shù)組中最大的數(shù);
4、將最頂層的數(shù)與最后一層最右邊的數(shù)調(diào)換位置,并使最大數(shù)不再參與下一次最大堆調(diào)整;
5、因最頂層的元素改變,從第二層開始進(jìn)行最大堆調(diào)整,第二次最大堆調(diào)整使得數(shù)組中第二大的數(shù)字變換到最頂層;
6、最頂層的數(shù)與最后一層最右邊的數(shù)換位并不再參與下一次最大堆調(diào)整;
7、重復(fù)5、6的步驟直至確定數(shù)組中所有數(shù)的位置;
8、輸出重新排序后的數(shù)組
No.9 一個(gè)頁面從輸入 URL 到加載顯示完成,這個(gè)過程中都發(fā)生了什么
這是一道很經(jīng)典的前端面試題,網(wǎng)上有各種各樣的資料,總體來說這一題是考察你的知識邊界,這里只大概的說一下相關(guān)的過程(不夠全面)。
參考博客:這篇博客寫的非常全面,從敲擊鍵盤開始講起,包含了很多硬件知識以及操作系統(tǒng)、內(nèi)存等,我本人目前知識有限,無法介紹的那么詳細(xì),有興趣的可以點(diǎn)擊上面的鏈接查看。
總體來說分為以下幾個(gè)過程:
- DNS解析:
DNS解析的過程就是尋找哪臺機(jī)器上有你需要資源的過程。當(dāng)你在瀏覽器中輸入一個(gè)地址時(shí),例如www.baidu.com,其實(shí)不是百度網(wǎng)站真正意義上的地址?;ヂ?lián)網(wǎng)上每一臺計(jì)算機(jī)的唯一標(biāo)識是它的IP地址,但是IP地址并不方便記憶。用戶更喜歡用方便記憶的網(wǎng)址去尋找互聯(lián)網(wǎng)上的其它計(jì)算機(jī),也就是上面提到的百度的網(wǎng)址。所以互聯(lián)網(wǎng)設(shè)計(jì)者需要在用戶的方便性與可用性方面做一個(gè)權(quán)衡,這個(gè)權(quán)衡就是一個(gè)網(wǎng)址到IP地址的轉(zhuǎn)換,這個(gè)過程就是DNS解析。它實(shí)際上充當(dāng)了一個(gè)翻譯的角色,實(shí)現(xiàn)了網(wǎng)址到IP地址的轉(zhuǎn)換。 - TCP連接:
知道了服務(wù)器的 IP 地址,下面便開始與服務(wù)器建立連接了。
通俗地講,通信連接的建立需要經(jīng)歷以下三個(gè)過程:
(1)主機(jī)向服務(wù)器發(fā)送一個(gè)建立連接的請求(您好,我想認(rèn)識您);
(2)服務(wù)器接到請求后發(fā)送同意連接的信號(好的,很高興認(rèn)識您);
(3)主機(jī)接到同意連接的信號后,再次向服務(wù)器發(fā)送了確認(rèn)信號(我也很高興認(rèn)識您),自此,主機(jī)與服務(wù)器兩者建立了連接。 - 發(fā)送HTTP請求
發(fā)送HTTP請求的過程就是構(gòu)建HTTP請求報(bào)文并通過TCP協(xié)議中發(fā)送到服務(wù)器指定端口(HTTP協(xié)議80/8080, HTTPS協(xié)議443)。HTTP請求報(bào)文是由三部分組成: 請求行, 請求報(bào)頭和請求正文。
數(shù)據(jù)經(jīng)過應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層、物理層逐層封裝,傳輸?shù)较乱粋€(gè)目的地。其中每一層的作用如下:
(5)應(yīng)用層:為應(yīng)用進(jìn)程提供服務(wù),加應(yīng)用層首部封裝為協(xié)議數(shù)據(jù)單元。
(4)傳輸層:實(shí)現(xiàn)端到端通信,加TCP首部封裝為數(shù)據(jù)包,TCP控制了數(shù)據(jù)包的發(fā)送序列的產(chǎn)生,不斷的調(diào)整發(fā)送序列,實(shí)現(xiàn)流控和數(shù)據(jù)完整。
(3)網(wǎng)絡(luò)層:轉(zhuǎn)發(fā)分組并選擇路由;加IP首部封裝為IP分組。
(2)數(shù)據(jù)鏈路層:相鄰的節(jié)點(diǎn)間的數(shù)據(jù)傳輸;加首部[mac地址]和尾部封裝為幀。
(1)物理層:具體物理媒介中的數(shù)據(jù)傳送,數(shù)據(jù)轉(zhuǎn)換為比特流。
下一個(gè)目的地接受到數(shù)據(jù)后,從物理層得到數(shù)據(jù)然后經(jīng)過逐層的解包 到 鏈路層 到 網(wǎng)絡(luò)層,然后開始上述的處理,在經(jīng)網(wǎng)絡(luò)層 鏈路層 物理層將數(shù)據(jù)封裝好繼續(xù)傳往下一個(gè)地址。
到達(dá)最終目的地,再經(jīng)過5層結(jié)構(gòu),逐層剝離,最終將數(shù)據(jù)送到目的主機(jī)的目的端口。 - 服務(wù)器處理請求并返回HTTP報(bào)文:
后端從在固定的端口接收到TCP報(bào)文開始,這一部分對應(yīng)于編程語言中的socket。它會對TCP連接進(jìn)行處理,對HTTP協(xié)議進(jìn)行解析,并按照報(bào)文格式進(jìn)一步封裝成HTTP Request對象,供上層使用。這一部分工作一般是由Web服務(wù)器去進(jìn)行。
HTTP響應(yīng)報(bào)文也是由三部分組成: 狀態(tài)碼, 響應(yīng)報(bào)頭和響應(yīng)報(bào)文。 - 瀏覽器解析渲染頁面:
瀏覽器是一個(gè)邊解析邊渲染的過程。首先瀏覽器解析HTML文件構(gòu)建DOM樹,然后解析CSS文件構(gòu)建渲染樹,等到渲染樹構(gòu)建完成后,瀏覽器開始布局渲染樹并將其繪制到屏幕上。這個(gè)過程比較復(fù)雜,涉及到兩個(gè)概念: reflow(回流)和repain(重繪)。DOM節(jié)點(diǎn)中的各個(gè)元素都是以盒模型的形式存在,這些都需要瀏覽器去計(jì)算其位置和大小等,這個(gè)過程稱為relow;當(dāng)盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之后,瀏覽器便開始繪制內(nèi)容,這個(gè)過程稱為repain。頁面在首次加載時(shí)必然會經(jīng)歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設(shè)備上,它會破壞用戶體驗(yàn),有時(shí)會造成頁面卡頓。所以我們應(yīng)該盡可能少的減少reflow和repain。 - 連接結(jié)束:
(1)主機(jī)向服務(wù)器發(fā)送一個(gè)斷開連接的請求(不早了,我該走了);
(2)服務(wù)器接到請求后發(fā)送確認(rèn)收到請求的信號(知道了);
(3)服務(wù)器向主機(jī)發(fā)送斷開通知(我也該走了);
(4)主機(jī)接到斷開通知后斷開連接并反饋一個(gè)確認(rèn)信號(嗯,好的),服務(wù)器收到確認(rèn)信號后斷開連接;
No.10 數(shù)組去重
ES5寫法1:
function unique(array){
let tempArray = []
let hash = {}
for(let i = 0;i<array.length;i++){
if(hash[array[i]] === undefined){
tempArray.push(array[i])
hash[array[i]] = true
}
}
return tempArray
}
ES5寫法2:當(dāng)數(shù)組中出現(xiàn)數(shù)字3
和字符串 '3'
時(shí),第一種寫法會將其當(dāng)成同一個(gè)值返回,而第二種寫法可以判斷數(shù)字3
和字符串 '3'
的不同。
function uniqueCom(array) {
let hash = {}
let tempArray = []
array.forEach(function(value) {
let key = (typeof value) + value;
if (!hash[key]) {
hash[key] = true
tempArray.push(value)
}
})
return tempArray
}
ES6寫法:使用Set
對象,MDN文檔
注:用...
(展開操作符)操作符將Set轉(zhuǎn)換為Array
function unique6(array){
return [...new Set(array)]
}