Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
章轉(zhuǎn)載:樂(lè)字節(jié)
簡(jiǎn)答題
1、什么是防抖和節(jié)流?有什么區(qū)別?如何實(shí)現(xiàn)?
參考答案
防抖
觸發(fā)高頻事件后n秒內(nèi)函數(shù)只會(huì)執(zhí)行一次,如果n秒內(nèi)高頻事件再次被觸發(fā),則重新計(jì)算時(shí)間
思路:
每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法
function debounce(fn) {
let timeout=null; // 創(chuàng)建一個(gè)標(biāo)記用來(lái)存放定時(shí)器的返回值
return function () {
clearTimeout(timeout); // 每當(dāng)用戶(hù)輸入的時(shí)候把前一個(gè) setTimeout clear 掉
timeout=setTimeout(()=> { // 然后又創(chuàng)建一個(gè)新的 setTimeout, 這樣就能保證輸入字符后的 interval 間隔內(nèi)如果還有字符輸入的話,就不會(huì)執(zhí)行 fn 函數(shù)
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log('防抖成功');
}
var inp=document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖
節(jié)流
高頻事件觸發(fā),但在n秒內(nèi)只會(huì)執(zhí)行一次,所以節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率
思路:
每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù)
function throttle(fn) {
let canRun=true; // 通過(guò)閉包保存一個(gè)標(biāo)記
return function () {
if (!canRun) return; // 在函數(shù)開(kāi)頭判斷標(biāo)記是否為true,不為true則return
canRun=false; // 立即設(shè)置為false
setTimeout(()=> { // 將外部傳入的函數(shù)的執(zhí)行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout執(zhí)行完畢后再把標(biāo)記設(shè)置為true(關(guān)鍵)表示可以執(zhí)行下一次循環(huán)了。當(dāng)定時(shí)器沒(méi)有執(zhí)行的時(shí)候標(biāo)記永遠(yuǎn)是false,在開(kāi)頭被return掉
canRun=true;
}, 500);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));
2、 get請(qǐng)求傳參長(zhǎng)度的誤區(qū)、get和post請(qǐng)求在緩存方面的區(qū)別
誤區(qū):我們經(jīng)常說(shuō)get請(qǐng)求參數(shù)的大小存在限制,而post請(qǐng)求的參數(shù)大小是無(wú)限制的。
參考答案
實(shí)際上HTTP 協(xié)議從未規(guī)定 GET/POST 的請(qǐng)求長(zhǎng)度限制是多少。對(duì)get請(qǐng)求參數(shù)的限制是來(lái)源與瀏覽器或web服務(wù)器,瀏覽器或web服務(wù)器限制了url的長(zhǎng)度。為了明確這個(gè)概念,我們必須再次強(qiáng)調(diào)下面幾點(diǎn):
HTTP 協(xié)議 未規(guī)定 GET 和POST的長(zhǎng)度限制
GET的最大長(zhǎng)度顯示是因?yàn)?瀏覽器和 web服務(wù)器限制了 URI的長(zhǎng)度
不同的瀏覽器和WEB服務(wù)器,限制的最大長(zhǎng)度不一樣
要支持IE,則最大長(zhǎng)度為2083byte,若只支持Chrome,則最大長(zhǎng)度 8182byte
補(bǔ)充補(bǔ)充一個(gè)get和post在緩存方面的區(qū)別:
get請(qǐng)求類(lèi)似于查找的過(guò)程,用戶(hù)獲取數(shù)據(jù),可以不用每次都與數(shù)據(jù)庫(kù)連接,所以可以使用緩存。
post不同,post做的一般是修改和刪除的工作,所以必須與數(shù)據(jù)庫(kù)交互,所以不能使用緩存。因此get請(qǐng)求適合于請(qǐng)求緩存。
3、模塊化發(fā)展歷程
可從IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、<script type="module"> 這幾個(gè)角度考慮。
參考答案
模塊化主要是用來(lái)抽離公共代碼,隔離作用域,避免變量沖突等。
IIFE:使用自執(zhí)行函數(shù)來(lái)編寫(xiě)模塊化,特點(diǎn):在一個(gè)單獨(dú)的函數(shù)作用域中執(zhí)行代碼,避免變量沖突。
(function(){
return {
data:[]
}
})()
AMD:使用requireJS 來(lái)編寫(xiě)模塊化,特點(diǎn):依賴(lài)必須提前聲明好。
define('./index.js',function(code){
// code 就是index.js 返回的內(nèi)容
})
CMD:使用seaJS 來(lái)編寫(xiě)模塊化,特點(diǎn):支持動(dòng)態(tài)引入依賴(lài)文件。
define(function(require, exports, module) {
var indexCode=require('./index.js');
})
CommonJS:nodejs 中自帶的模塊化。
var fs=require('fs');
UMD:兼容AMD,CommonJS 模塊化語(yǔ)法。
webpack(require.ensure):webpack 2.x 版本中的代碼分割。
ES Modules:ES6 引入的模塊化,支持import 來(lái)引入另一個(gè) js 。
import a from 'a';
4、npm 模塊安裝機(jī)制,為什么輸入 npm install 就可以自動(dòng)安裝對(duì)應(yīng)的模塊?
參考答案
1. npm 模塊安裝機(jī)制:
發(fā)出npm install命令
查詢(xún)node_modules目錄之中是否已經(jīng)存在指定模塊
npm 向 registry 查詢(xún)模塊壓縮包的網(wǎng)址
下載壓縮包,存放在根目錄下的.npm目錄里
解壓壓縮包到當(dāng)前項(xiàng)目的node_modules目錄
若存在,不再重新安裝
若不存在
2. npm 實(shí)現(xiàn)原理
輸入 npm install 命令并敲下回車(chē)后,會(huì)經(jīng)歷如下幾個(gè)階段(以 npm 5.5.1 為例):
1. npm 模塊安裝機(jī)制:
發(fā)出npm install命令
查詢(xún)node_modules目錄之中是否已經(jīng)存在指定模塊
npm 向 registry 查詢(xún)模塊壓縮包的網(wǎng)址
下載壓縮包,存放在根目錄下的.npm目錄里
解壓壓縮包到當(dāng)前項(xiàng)目的node_modules目錄
若存在,不再重新安裝
若不存在
2. npm 實(shí)現(xiàn)原理
輸入 npm install 命令并敲下回車(chē)后,會(huì)經(jīng)歷如下幾個(gè)階段(以 npm 5.5.1 為例):
執(zhí)行工程自身 preinstall
當(dāng)前 npm 工程如果定義了 preinstall 鉤子此時(shí)會(huì)被執(zhí)行。
確定首層依賴(lài)模塊
首先需要做的是確定工程中的首層依賴(lài),也就是 dependencies 和 devDependencies 屬性中直接指定的模塊(假設(shè)此時(shí)沒(méi)有添加 npm install 參數(shù))。
工程本身是整棵依賴(lài)樹(shù)的根節(jié)點(diǎn),每個(gè)首層依賴(lài)模塊都是根節(jié)點(diǎn)下面的一棵子樹(shù),npm 會(huì)開(kāi)啟多進(jìn)程從每個(gè)首層依賴(lài)模塊開(kāi)始逐步尋找更深層級(jí)的節(jié)點(diǎn)。
獲取模塊
獲取模塊是一個(gè)遞歸的過(guò)程,分為以下幾步:
獲取模塊信息。在下載一個(gè)模塊之前,首先要確定其版本,這是因?yàn)?package.json 中往往是 semantic version(semver,語(yǔ)義化版本)。此時(shí)如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有該模塊信息直接拿即可,如果沒(méi)有則從倉(cāng)庫(kù)獲取。如 packaeg.json 中某個(gè)包的版本是 ^1.1.0,npm 就會(huì)去倉(cāng)庫(kù)中獲取符合 1.x.x 形式的最新版本。
獲取模塊實(shí)體。上一步會(huì)獲取到模塊的壓縮包地址(resolved 字段),npm 會(huì)用此地址檢查本地緩存,緩存中有就直接拿,如果沒(méi)有則從倉(cāng)庫(kù)下載。
查找該模塊依賴(lài),如果有依賴(lài)則回到第1步,如果沒(méi)有則停止。
模塊扁平化(dedupe)
上一步獲取到的是一棵完整的依賴(lài)樹(shù),其中可能包含大量重復(fù)模塊。比如 A 模塊依賴(lài)于 loadsh,B 模塊同樣依賴(lài)于 lodash。在 npm3 以前會(huì)嚴(yán)格按照依賴(lài)樹(shù)的結(jié)構(gòu)進(jìn)行安裝,因此會(huì)造成模塊冗余。
從 npm3 開(kāi)始默認(rèn)加入了一個(gè) dedupe 的過(guò)程。它會(huì)遍歷所有節(jié)點(diǎn),逐個(gè)將模塊放在根節(jié)點(diǎn)下面,也就是 node-modules 的第一層。當(dāng)發(fā)現(xiàn)有重復(fù)模塊時(shí),則將其丟棄。
這里需要對(duì)重復(fù)模塊進(jìn)行一個(gè)定義,它指的是模塊名相同且 semver 兼容。每個(gè) semver 都對(duì)應(yīng)一段版本允許范圍,如果兩個(gè)模塊的版本允許范圍存在交集,那么就可以得到一個(gè)兼容版本,而不必版本號(hào)完全一致,這可以使更多冗余模塊在 dedupe 過(guò)程中被去掉。
比如 node-modules 下 foo 模塊依賴(lài) lodash@^1.0.0,bar 模塊依賴(lài) lodash@^1.1.0,則 ^1.1.0 為兼容版本。
而當(dāng) foo 依賴(lài) lodash@^2.0.0,bar 依賴(lài) lodash@^1.1.0,則依據(jù) semver 的規(guī)則,二者不存在兼容版本。會(huì)將一個(gè)版本放在 node_modules 中,另一個(gè)仍保留在依賴(lài)樹(shù)里。
舉個(gè)例子,假設(shè)一個(gè)依賴(lài)樹(shù)原本是這樣:
node_modules -- foo ---- lodash@version1
-- bar ---- lodash@version2
假設(shè) version1 和 version2 是兼容版本,則經(jīng)過(guò) dedupe 會(huì)成為下面的形式:
node_modules -- foo
-- bar
-- lodash(保留的版本為兼容版本)
假設(shè) version1 和 version2 為非兼容版本,則后面的版本保留在依賴(lài)樹(shù)中:
node_modules -- foo -- lodash@version1
-- bar ---- lodash@version2
安裝模塊
這一步將會(huì)更新工程中的 node_modules,并執(zhí)行模塊中的生命周期函數(shù)(按照 preinstall、install、postinstall 的順序)。
執(zhí)行工程自身生命周期
當(dāng)前 npm 工程如果定義了鉤子此時(shí)會(huì)被執(zhí)行(按照 install、postinstall、prepublish、prepare 的順序)。
最后一步是生成或更新版本描述文件,npm install 過(guò)程完成。
5、ES5的繼承和ES6的繼承有什么區(qū)別?
參考答案
ES5的繼承時(shí)通過(guò)prototype或構(gòu)造函數(shù)機(jī)制來(lái)實(shí)現(xiàn)。ES5的繼承實(shí)質(zhì)上是先創(chuàng)建子類(lèi)的實(shí)例對(duì)象,然后再將父類(lèi)的方法添加到this上(Parent.apply(this))。
ES6的繼承機(jī)制完全不同,實(shí)質(zhì)上是先創(chuàng)建父類(lèi)的實(shí)例對(duì)象this(所以必須先調(diào)用父類(lèi)的super()方法),然后再用子類(lèi)的構(gòu)造函數(shù)修改this。
具體的:ES6通過(guò)class關(guān)鍵字定義類(lèi),里面有構(gòu)造方法,類(lèi)之間通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承。子類(lèi)必須在constructor方法中調(diào)用super方法,否則新建實(shí)例報(bào)錯(cuò)。因?yàn)樽宇?lèi)沒(méi)有自己的this對(duì)象,而是繼承了父類(lèi)的this對(duì)象,然后對(duì)其進(jìn)行加工。如果不調(diào)用super方法,子類(lèi)得不到this對(duì)象。
ps:super關(guān)鍵字指代父類(lèi)的實(shí)例,即父類(lèi)的this對(duì)象。在子類(lèi)構(gòu)造函數(shù)中,調(diào)用super后,才可使用this關(guān)鍵字,否則報(bào)錯(cuò)。
6、setTimeout、Promise、Async/Await 的區(qū)別
參考答案
7、定時(shí)器的執(zhí)行順序或機(jī)制?
參考答案
**因?yàn)閖s是單線程的,瀏覽器遇到setTimeout或者setInterval會(huì)先執(zhí)行完當(dāng)前的代碼塊,在此之前會(huì)把定時(shí)器推入瀏覽器的待執(zhí)行事件隊(duì)列里面,等到瀏覽器執(zhí)行完當(dāng)前代碼之后會(huì)看一下事件隊(duì)列里面有沒(méi)有任務(wù),有的話才執(zhí)行定時(shí)器的代碼。**所以即使把定時(shí)器的時(shí)間設(shè)置為0還是會(huì)先執(zhí)行當(dāng)前的一些代碼。
function test(){
var aa=0;
var testSet=setInterval(function(){
aa++;
console.log(123);
if(aa<10){
clearInterval(testSet);
}
},20);
var testSet1=setTimeout(function(){
console.log(321)
},1000);
for(var i=0;i<10;i++){
console.log('test');
}
}
test()
輸出結(jié)果:
test //10次
undefined
123
321
8、['1','2','3'].map(parseInt) 輸出什么,為什么?
參考答案
輸出:[1, NaN, NaN]
首先讓我們回顧一下,map函數(shù)的第一個(gè)參數(shù)callback:
var new_array=arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])這個(gè)callback一共可以接收三個(gè)參數(shù),其中第一個(gè)參數(shù)代表當(dāng)前被處理的元素,而第二個(gè)參數(shù)代表該元素的索引。
而parseInt則是用來(lái)解析字符串的,使字符串成為指定基數(shù)的整數(shù)。parseInt(string, radix)接收兩個(gè)參數(shù),第一個(gè)表示被處理的值(字符串),第二個(gè)表示為解析時(shí)的基數(shù)。
了解這兩個(gè)函數(shù)后,我們可以模擬一下運(yùn)行情況
parseInt('1', 0) //radix為0時(shí),且string參數(shù)不以“0x”和“0”開(kāi)頭時(shí),按照10為基數(shù)處理。這個(gè)時(shí)候返回1
parseInt('2', 1) //基數(shù)為1(1進(jìn)制)表示的數(shù)中,最大值小于2,所以無(wú)法解析,返回NaN
parseInt('3', 2) //基數(shù)為2(2進(jìn)制)表示的數(shù)中,最大值小于3,所以無(wú)法解析,返回NaN
map函數(shù)返回的是一個(gè)數(shù)組,所以最后結(jié)果為[1, NaN, NaN]
9、Doctype作用? 嚴(yán)格模式與混雜模式如何區(qū)分?它們有何意義?
參考答案
Doctype聲明于文檔最前面,告訴瀏覽器以何種方式來(lái)渲染頁(yè)面,這里有兩種模式,嚴(yán)格模式和混雜模式。
嚴(yán)格模式的排版和 JS 運(yùn)作模式是 以該瀏覽器支持的最高標(biāo)準(zhǔn)運(yùn)行。
混雜模式,向后兼容,模擬老式瀏覽器,防止瀏覽器無(wú)法兼容頁(yè)面。
10、fetch發(fā)送2次請(qǐng)求的原因
參考答案
fetch發(fā)送post請(qǐng)求的時(shí)候,總是發(fā)送2次,第一次狀態(tài)碼是204,第二次才成功?
原因很簡(jiǎn)單,因?yàn)槟阌胒etch的post請(qǐng)求的時(shí)候,導(dǎo)致fetch 第一次發(fā)送了一個(gè)Options請(qǐng)求,詢(xún)問(wèn)服務(wù)器是否支持修改的請(qǐng)求頭,如果服務(wù)器支持,則在第二次中發(fā)送真正的請(qǐng)求。
http、瀏覽器對(duì)象
1、HTTPS 握手過(guò)程中,客戶(hù)端如何驗(yàn)證證書(shū)的合法性
參考答案
首先什么是HTTP協(xié)議?
http協(xié)議是超文本傳輸協(xié)議,位于tcp/ip四層模型中的應(yīng)用層;通過(guò)請(qǐng)求/響應(yīng)的方式在客戶(hù)端和服務(wù)器之間進(jìn)行通信;但是缺少安全性,http協(xié)議信息傳輸是通過(guò)明文的方式傳輸,不做任何加密,相當(dāng)于在網(wǎng)絡(luò)上裸奔;容易被中間人惡意篡改,這種行為叫做中間人攻擊;
加密通信:
為了安全性,雙方可以使用對(duì)稱(chēng)加密的方式key進(jìn)行信息交流,但是這種方式對(duì)稱(chēng)加密秘鑰也會(huì)被攔截,也不夠安全,進(jìn)而還是存在被中間人攻擊風(fēng)險(xiǎn);于是人們又想出來(lái)另外一種方式,使用非對(duì)稱(chēng)加密的方式;使用公鑰/私鑰加解密;通信方A發(fā)起通信并攜帶自己的公鑰,接收方B通過(guò)公鑰來(lái)加密對(duì)稱(chēng)秘鑰;然后發(fā)送給發(fā)起方A;A通過(guò)私鑰解密;雙發(fā)接下來(lái)通過(guò)對(duì)稱(chēng)秘鑰來(lái)進(jìn)行加密通信;但是這種方式還是會(huì)存在一種安全性;中間人雖然不知道發(fā)起方A的私鑰,但是可以做到偷天換日,將攔截發(fā)起方的公鑰key;并將自己生成的一對(duì)公/私鑰的公鑰發(fā)送給B;接收方B并不知道公鑰已經(jīng)被偷偷換過(guò);按照之前的流程,B通過(guò)公鑰加密自己生成的對(duì)稱(chēng)加密秘鑰key2;發(fā)送給A;這次通信再次被中間人攔截,盡管后面的通信,兩者還是用key2通信,但是中間人已經(jīng)掌握了Key2;可以進(jìn)行輕松的加解密;還是存在被中間人攻擊風(fēng)險(xiǎn);
解決困境:權(quán)威的證書(shū)頒發(fā)機(jī)構(gòu)CA來(lái)解決;
制作證書(shū):作為服務(wù)端的A,首先把自己的公鑰key1發(fā)給證書(shū)頒發(fā)機(jī)構(gòu),向證書(shū)頒發(fā)機(jī)構(gòu)進(jìn)行申請(qǐng)證書(shū);證書(shū)頒發(fā)機(jī)構(gòu)有一套自己的公私鑰,CA通過(guò)自己的私鑰來(lái)加密key1,并且通過(guò)服務(wù)端網(wǎng)址等信息生成一個(gè)證書(shū)簽名,證書(shū)簽名同樣使用機(jī)構(gòu)的私鑰進(jìn)行加密;制作完成后,機(jī)構(gòu)將證書(shū)發(fā)給A;
校驗(yàn)證書(shū)真?zhèn)危寒?dāng)B向服務(wù)端A發(fā)起請(qǐng)求通信的時(shí)候,A不再直接返回自己的公鑰,而是返回一個(gè)證書(shū);
說(shuō)明:各大瀏覽器和操作系統(tǒng)已經(jīng)維護(hù)了所有的權(quán)威證書(shū)機(jī)構(gòu)的名稱(chēng)和公鑰。B只需要知道是哪個(gè)權(quán)威機(jī)構(gòu)發(fā)的證書(shū),使用對(duì)應(yīng)的機(jī)構(gòu)公鑰,就可以解密出證書(shū)簽名;接下來(lái),B使用同樣的規(guī)則,生成自己的證書(shū)簽名,如果兩個(gè)簽名是一致的,說(shuō)明證書(shū)是有效的;簽名驗(yàn)證成功后,B就可以再次利用機(jī)構(gòu)的公鑰,解密出A的公鑰key1;接下來(lái)的操作,就是和之前一樣的流程了;
中間人是否會(huì)攔截發(fā)送假證書(shū)到B呢?
因?yàn)樽C書(shū)的簽名是由服務(wù)器端網(wǎng)址等信息生成的,并且通過(guò)第三方機(jī)構(gòu)的私鑰加密中間人無(wú)法篡改;所以最關(guān)鍵的問(wèn)題是證書(shū)簽名的真?zhèn)危?/p>
https主要的思想是在http基礎(chǔ)上增加了ssl安全層,即以上認(rèn)證過(guò)程;
2、TCP三次握手和四次揮手
參考答案
三次握手之所以是三次是保證client和server均讓對(duì)方知道自己的接收和發(fā)送能力沒(méi)問(wèn)題而保證的最小次數(shù)。
第一次client=> server 只能server判斷出client具備發(fā)送能力 第二次 server=> client client就可以判斷出server具備發(fā)送和接受能力。此時(shí)client還需讓server知道自己接收能力沒(méi)問(wèn)題于是就有了第三次 第三次 client=> server 雙方均保證了自己的接收和發(fā)送能力沒(méi)有問(wèn)題
其中,為了保證后續(xù)的握手是為了應(yīng)答上一個(gè)握手,每次握手都會(huì)帶一個(gè)標(biāo)識(shí) seq,后續(xù)的ACK都會(huì)對(duì)這個(gè)seq進(jìn)行加一來(lái)進(jìn)行確認(rèn)。
3、img iframe script 來(lái)發(fā)送跨域請(qǐng)求有什么優(yōu)缺點(diǎn)?
參考答案
iframe
優(yōu)點(diǎn):跨域完畢之后DOM操作和互相之間的JavaScript調(diào)用都是沒(méi)有問(wèn)題的
缺點(diǎn):1.若結(jié)果要以URL參數(shù)傳遞,這就意味著在結(jié)果數(shù)據(jù)量很大的時(shí)候需要分割傳遞,巨煩。2.還有一個(gè)是iframe本身帶來(lái)的,母頁(yè)面和iframe本身的交互本身就有安全性限制。
script
優(yōu)點(diǎn):可以直接返回json格式的數(shù)據(jù),方便處理
缺點(diǎn):只接受GET請(qǐng)求方式
圖片ping
優(yōu)點(diǎn):可以訪問(wèn)任何url,一般用來(lái)進(jìn)行點(diǎn)擊追蹤,做頁(yè)面分析常用的方法
缺點(diǎn):不能訪問(wèn)響應(yīng)文本,只能監(jiān)聽(tīng)是否響應(yīng)
4、http和https的區(qū)別?
參考答案
http傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,網(wǎng)景公司設(shè)置了SSL協(xié)議來(lái)對(duì)http協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行加密處理,簡(jiǎn)單來(lái)說(shuō)https協(xié)議是由http和ssl協(xié)議構(gòu)建的可進(jìn)行加密傳輸和身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議的安全性更高。主要的區(qū)別如下:
Https協(xié)議需要ca證書(shū),費(fèi)用較高。
http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
使用不同的鏈接方式,端口也不同,一般而言,http協(xié)議的端口為80,https的端口為443
http的連接很簡(jiǎn)單,是無(wú)狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
5、什么是Bom?有哪些常用的Bom屬性?
參考答案
Bom是瀏覽器對(duì)象
location對(duì)象
location.href-- 返回或設(shè)置當(dāng)前文檔的URL
location.search -- 返回URL中的查詢(xún)字符串部分。例如 http://www.dreamdu.com/dreamd... 返回包括(?)后面的內(nèi)容?id=5&name=dreamdu
location.hash -- 返回URL#后面的內(nèi)容,如果沒(méi)有#,返回空 location.host -- 返回URL中的域名部分,例如www.dreamdu.com
location.hostname -- 返回URL中的主域名部分,例如dreamdu.com
location.pathname -- 返回URL的域名后的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
location.port -- 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
location.protocol -- 返回URL中的協(xié)議部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的內(nèi)容http:
location.assign -- 設(shè)置當(dāng)前文檔的URL
location.replace() -- 設(shè)置當(dāng)前文檔的URL,并且在history對(duì)象的地址列表中移除這個(gè)URL location.replace(url);
location.reload() -- 重載當(dāng)前頁(yè)面
history對(duì)象
history.go() -- 前進(jìn)或后退指定的頁(yè)面數(shù)
history.go(num); history.back() -- 后退一頁(yè)
history.forward() -- 前進(jìn)一頁(yè)
Navigator對(duì)象
navigator.userAgent -- 返回用戶(hù)代理頭的字符串表示(就是包括瀏覽器版本信息等的字符串)
navigator.cookieEnabled -- 返回瀏覽器是否支持(啟用)cookie
6、Cookie、sessionStorage、localStorage的區(qū)別
參考答案
共同點(diǎn):都是保存在瀏覽器端,并且是同源的
Cookie:cookie數(shù)據(jù)始終在同源的http請(qǐng)求中攜帶(即使不需要),即cookie在瀏覽器和服務(wù)器間來(lái)回傳遞。而sessionStorage和localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存。cookie數(shù)據(jù)還有路徑(path)的概念,可以限制cookie只屬于某個(gè)路徑下,存儲(chǔ)的大小很小只有4K左右。(key:可以在瀏覽器和服務(wù)器端來(lái)回傳遞,存儲(chǔ)容量小,只有大約4K左右)
sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉前有效,自然也就不可能持久保持,localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù);cookie只在設(shè)置的cookie過(guò)期時(shí)間之前一直有效,即使窗口或?yàn)g覽器關(guān)閉。(key:本身就是一個(gè)回話過(guò)程,關(guān)閉瀏覽器后消失,session為一個(gè)回話,當(dāng)頁(yè)面不同即使是同一頁(yè)面打開(kāi)兩次,也被視為同一次回話)
localStorage:localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。(key:同源窗口都會(huì)共享,并且不會(huì)失效,不管窗口或者瀏覽器關(guān)閉與否都會(huì)始終生效)
補(bǔ)充說(shuō)明一下cookie的作用:
保存用戶(hù)登錄狀態(tài)。例如將用戶(hù)id存儲(chǔ)于一個(gè)cookie內(nèi),這樣當(dāng)用戶(hù)下次訪問(wèn)該頁(yè)面時(shí)就不需要重新登錄了,現(xiàn)在很多論壇和社區(qū)都提供這樣的功能。cookie還可以設(shè)置過(guò)期時(shí)間,當(dāng)超過(guò)時(shí)間期限后,cookie就會(huì)自動(dòng)消失。因此,系統(tǒng)往往可以提示用戶(hù)保持登錄狀態(tài)的時(shí)間:常見(jiàn)選項(xiàng)有一個(gè)月、三個(gè) 月、一年等。
跟蹤用戶(hù)行為。例如一個(gè)天氣預(yù)報(bào)網(wǎng)站,能夠根據(jù)用戶(hù)選擇的地區(qū)顯示當(dāng)?shù)氐奶鞖馇闆r。如果每次都需要選擇所在地是煩瑣的,當(dāng)利用了 cookie后就會(huì)顯得很人性化了,系統(tǒng)能夠記住上一次訪問(wèn)的地區(qū),當(dāng)下次再打開(kāi)該頁(yè)面時(shí),它就會(huì)自動(dòng)顯示上次用戶(hù)所在地區(qū)的天氣情況。因?yàn)橐磺卸际窃诤?臺(tái)完成,所以這樣的頁(yè)面就像為某個(gè)用戶(hù)所定制的一樣,使用起來(lái)非常方便
定制頁(yè)面。如果網(wǎng)站提供了換膚或更換布局的功能,那么可以使用cookie來(lái)記錄用戶(hù)的選項(xiàng),例如:背景色、分辨率等。當(dāng)用戶(hù)下次訪問(wèn)時(shí),仍然可以保存上一次訪問(wèn)的界面風(fēng)格。
7、Cookie如何防范XSS攻擊
參考答案
XSS(跨站腳本攻擊)是指攻擊者在返回的HTML中嵌入javascript腳本,為了減輕這些攻擊,需要在HTTP頭部配上,set-cookie:
httponly-這個(gè)屬性可以防止XSS,它會(huì)禁止javascript腳本來(lái)訪問(wèn)cookie。
secure - 這個(gè)屬性告訴瀏覽器僅在請(qǐng)求為https的時(shí)候發(fā)送cookie。
結(jié)果應(yīng)該是這樣的:Set-Cookie=.....
8、瀏覽器和 Node 事件循環(huán)的區(qū)別?
參考答案
其中一個(gè)主要的區(qū)別在于瀏覽器的event loop 和nodejs的event loop 在處理異步事件的順序是不同的,nodejs中有micro event;其中Promise屬于micro event 該異步事件的處理順序就和瀏覽器不同.nodejs V11.0以上 這兩者之間的順序就相同了.
function test () {
console.log('start')
setTimeout(()=> {
console.log('children2')
Promise.resolve().then(()=> {console.log('children2-1')})
}, 0)
setTimeout(()=> {
console.log('children3')
Promise.resolve().then(()=> {console.log('children3-1')})
}, 0)
Promise.resolve().then(()=> {console.log('children1')})
console.log('end')
}
test()
// 以上代碼在node11以下版本的執(zhí)行結(jié)果(先執(zhí)行所有的宏任務(wù),再執(zhí)行微任務(wù))
// start
// end
// children1
// children2
// children3
// children2-1
// children3-1
// 以上代碼在node11及瀏覽器的執(zhí)行結(jié)果(順序執(zhí)行宏任務(wù)和微任務(wù))
// start
// end
// children1
// children2
// children2-1
// children3
// children3-1
9、簡(jiǎn)述HTTPS中間人攻擊
參考答案
https協(xié)議由 http + ssl 協(xié)議構(gòu)成,具體的鏈接過(guò)程可參考SSL或TLS握手的概述
中間人攻擊過(guò)程如下:
服務(wù)器向客戶(hù)端發(fā)送公鑰。
攻擊者截獲公鑰,保留在自己手上。
然后攻擊者自己生成一個(gè)【偽造的】公鑰,發(fā)給客戶(hù)端。
客戶(hù)端收到偽造的公鑰后,生成加密hash值發(fā)給服務(wù)器。
攻擊者獲得加密hash值,用自己的私鑰解密獲得真秘鑰。
同時(shí)生成假的加密hash值,發(fā)給服務(wù)器。
服務(wù)器用私鑰解密獲得假秘鑰。
服務(wù)器用加秘鑰加密傳輸信息
防范方法:
服務(wù)端在發(fā)送瀏覽器的公鑰中加入CA證書(shū),瀏覽器可以驗(yàn)證CA證書(shū)的有效性
10、說(shuō)幾條web前端優(yōu)化策略
參考答案
(1). 減少HTTP請(qǐng)求數(shù)
這條策略基本上所有前端人都知道,而且也是最重要最有效的。都說(shuō)要減少HTTP請(qǐng)求,那請(qǐng)求多了到底會(huì)怎么樣呢?首先,每個(gè)請(qǐng)求都是有成本的,既包 含時(shí)間成本也包含資源成本。一個(gè)完整的請(qǐng)求都需要經(jīng)過(guò)DNS尋址、與服務(wù)器建立連接、發(fā)送數(shù)據(jù)、等待服務(wù)器響應(yīng)、接收數(shù)據(jù)這樣一個(gè)“漫長(zhǎng)”而復(fù)雜的過(guò)程。時(shí)間成本就是用戶(hù)需要看到或者“感受”到這個(gè)資源是必須要等待這個(gè)過(guò)程結(jié)束的,資源上由于每個(gè)請(qǐng)求都需要攜帶數(shù)據(jù),因此每個(gè)請(qǐng)求都需要占用帶寬。
另外,由于瀏覽器進(jìn)行并發(fā)請(qǐng)求的請(qǐng)求數(shù)是有上限的,因此請(qǐng)求數(shù)多了以后,瀏覽器需要分批進(jìn)行請(qǐng)求,因此會(huì)增加用戶(hù)的等待時(shí)間,會(huì)給 用戶(hù)造成站點(diǎn)速度慢這樣一個(gè)印象,即使可能用戶(hù)能看到的第一屏的資源都已經(jīng)請(qǐng)求完了,但是瀏覽器的進(jìn)度條會(huì)一直存在。減少HTTP請(qǐng)求數(shù)的主要途徑包括:
(2). 從設(shè)計(jì)實(shí)現(xiàn)層面簡(jiǎn)化頁(yè)面
如果你的頁(yè)面像百度首頁(yè)一樣簡(jiǎn)單,那么接下來(lái)的規(guī)則基本上都用不著了。保持頁(yè)面簡(jiǎn)潔、減少資源的使用時(shí)最直接的。如果不是這樣,你的頁(yè)面需要華麗的皮膚,則繼續(xù)閱讀下面的內(nèi)容。
(3). 合理設(shè)置HTTP緩存
緩存的力量是強(qiáng)大的,恰當(dāng)?shù)木彺嬖O(shè)置可以大大的減少HTTP請(qǐng)求。以有啊首頁(yè)為例,當(dāng)瀏覽器沒(méi)有緩存的時(shí)候訪問(wèn)一共會(huì)發(fā)出78個(gè)請(qǐng)求,共600多K 數(shù)據(jù)(如圖1.1),而當(dāng)?shù)诙卧L問(wèn)即瀏覽器已緩存之后訪問(wèn)則僅有10個(gè)請(qǐng)求,共20多K數(shù)據(jù)(如圖1.2)。(這里需要說(shuō)明的是,如果直接F5刷新頁(yè)面 的話效果是不一樣的,這種情況下請(qǐng)求數(shù)還是一樣,不過(guò)被緩存資源的請(qǐng)求服務(wù)器是304響應(yīng),只有Header沒(méi)有Body,可以節(jié)省帶寬)
怎樣才算合理設(shè)置?原則很簡(jiǎn)單,能緩存越多越好,能緩存越久越好。例如,很少變化的圖片資源可以直接通過(guò)HTTP Header中的Expires設(shè)置一個(gè)很長(zhǎng)的過(guò)期頭;變化不頻繁而又可能會(huì)變的資源可以使用Last-Modifed來(lái)做請(qǐng)求驗(yàn)證。盡可能的讓資源能夠 在緩存中待得更久。
(4). 資源合并與壓縮
如果可以的話,盡可能的將外部的腳本、樣式進(jìn)行合并,多個(gè)合為一個(gè)。另外,CSS、Javascript、Image都可以用相應(yīng)的工具進(jìn)行壓縮,壓縮后往往能省下不少空間。
(5). CSS Sprites
合并CSS圖片,減少請(qǐng)求數(shù)的又一個(gè)好辦法。
(6). Inline Images
使用data: URL scheme的方式將圖片嵌入到頁(yè)面或CSS中,如果不考慮資源管理上的問(wèn)題的話,不失為一個(gè)好辦法。如果是嵌入頁(yè)面的話換來(lái)的是增大了頁(yè)面的體積,而且無(wú)法利用瀏覽器緩存。使用在CSS中的圖片則更為理想一些。
(7). Lazy Load Images
這條策略實(shí)際上并不一定能減少HTTP請(qǐng)求數(shù),但是卻能在某些條件下或者頁(yè)面剛加載時(shí)減少HTTP請(qǐng)求數(shù)。對(duì)于圖片而言,在頁(yè)面剛加載的時(shí)候可以只 加載第一屏,當(dāng)用戶(hù)繼續(xù)往后滾屏的時(shí)候才加載后續(xù)的圖片。這樣一來(lái),假如用戶(hù)只對(duì)第一屏的內(nèi)容感興趣時(shí),那剩余的圖片請(qǐng)求就都節(jié)省了。有啊首頁(yè)曾經(jīng)的做法 是在加載的時(shí)候把第一屏之后的圖片地址緩存在Textarea標(biāo)簽中,待用戶(hù)往下滾屏的時(shí)候才“惰性”加載。
11、你了解的瀏覽器的重繪和回流導(dǎo)致的性能問(wèn)題
參考答案
重繪(Repaint)和回流(Reflow)
重繪和回流是渲染步驟中的一小節(jié),但是這兩個(gè)步驟對(duì)于性能影響很大。
重繪是當(dāng)節(jié)點(diǎn)需要更改外觀而不會(huì)影響布局的,比如改變 color就叫稱(chēng)為重繪
回流是布局或者幾何屬性需要改變就稱(chēng)為回流。
回流必定會(huì)發(fā)生重繪,重繪不一定會(huì)引發(fā)回流。回流所需的成本比重繪高的多,改變深層次的節(jié)點(diǎn)很可能導(dǎo)致父節(jié)點(diǎn)的一系列回流。
所以以下幾個(gè)動(dòng)作可能會(huì)導(dǎo)致性能問(wèn)題:
改變 window 大小
改變字體
添加或刪除樣式
文字改變
定位或者浮動(dòng)
盒模型
很多人不知道的是,重繪和回流其實(shí)和 Event loop 有關(guān)。
當(dāng) Event loop 執(zhí)行完 Microtasks 后,會(huì)判斷 document 是否需要更新。因?yàn)闉g覽器是 60Hz 的刷新率,每 16ms 才會(huì)更新一次。
然后判斷是否有 resize或者 scroll,有的話會(huì)去觸發(fā)事件,所以 resize和 scroll事件也是至少 16ms 才會(huì)觸發(fā)一次,并且自帶節(jié)流功能。
判斷是否觸發(fā)了 media query
更新動(dòng)畫(huà)并且發(fā)送事件
判斷是否有全屏操作事件
執(zhí)行 requestAnimationFrame回調(diào)
執(zhí)行 IntersectionObserver回調(diào),該方法用于判斷元素是否可見(jiàn),可以用于懶加載上,但是兼容性不好
更新界面
以上就是一幀中可能會(huì)做的事情。如果在一幀中有空閑時(shí)間,就會(huì)去執(zhí)行 requestIdleCallback回調(diào)。
減少重繪和回流
使用 translate 替代 top
<div class="test"></div>
<style>
.test {
position: absolute;
top: 10px;
width: 100px;
height: 100px;
background: red;
}
</style>
<script>
setTimeout(()=> {
// 引起回流
document.querySelector('.test').style.top='100px'
}, 1000)
</script>
使用 visibility替換 display: none,因?yàn)榍罢咧粫?huì)引起重繪,后者會(huì)引發(fā)回流(改變了布局)
把 DOM 離線后修改,比如:先把 DOM 給 display:none(有一次 Reflow),然后你修改100次,然后再把它顯示出來(lái)
不要把 DOM 結(jié)點(diǎn)的屬性值放在一個(gè)循環(huán)里當(dāng)成循環(huán)里的變量
for(let i=0; i < 1000; i++) {
// 獲取 offsetTop 會(huì)導(dǎo)致回流,因?yàn)樾枰カ@取正確的值
console.log(document.querySelector('.test').style.offsetTop)
}
不要使用 table 布局,可能很小的一個(gè)小改動(dòng)會(huì)造成整個(gè) table 的重新布局
動(dòng)畫(huà)實(shí)現(xiàn)的速度的選擇,動(dòng)畫(huà)速度越快,回流次數(shù)越多,也可以選擇使用 requestAnimationFrame
CSS 選擇符從右往左匹配查找,避免 DOM 深度過(guò)深
將頻繁運(yùn)行的動(dòng)畫(huà)變?yōu)閳D層,圖層能夠阻止該節(jié)點(diǎn)回流影響別的元素。比如對(duì)于 video標(biāo)簽,瀏覽器會(huì)自動(dòng)將該節(jié)點(diǎn)變?yōu)閳D層。
react、Vue
1、寫(xiě) React / Vue 項(xiàng)目時(shí)為什么要在列表組件中寫(xiě) key,其作用是什么?
參考答案
vue和react都是采用diff算法來(lái)對(duì)比新舊虛擬節(jié)點(diǎn),從而更新節(jié)點(diǎn)。在vue的diff函數(shù)中(建議先了解一下diff算法過(guò)程)。在交叉對(duì)比中,當(dāng)新節(jié)點(diǎn)跟舊節(jié)點(diǎn)頭尾交叉對(duì)比沒(méi)有結(jié)果時(shí),會(huì)根據(jù)新節(jié)點(diǎn)的key去對(duì)比舊節(jié)點(diǎn)數(shù)組中的key,從而找到相應(yīng)舊節(jié)點(diǎn)(這里對(duì)應(yīng)的是一個(gè)key=> index 的map映射)。如果沒(méi)找到就認(rèn)為是一個(gè)新增節(jié)點(diǎn)。而如果沒(méi)有key,那么就會(huì)采用遍歷查找的方式去找到對(duì)應(yīng)的舊節(jié)點(diǎn)。一種一個(gè)map映射,另一種是遍歷查找。相比而言。map映射的速度更快。vue部分源碼如下:
// vue項(xiàng)目 src/core/vdom/patch.js -488行
// 以下是為了閱讀性進(jìn)行格式化后的代碼
// oldCh 是一個(gè)舊虛擬節(jié)點(diǎn)數(shù)組
if (isUndef(oldKeyToIdx)) {
oldKeyToIdx=createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
}
if(isDef(newStartVnode.key)) {
// map 方式獲取
idxInOld=oldKeyToIdx[newStartVnode.key]
} else {
// 遍歷方式獲取
idxInOld=findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
}
創(chuàng)建map函數(shù)
function createKeyToOldIdx (children, beginIdx, endIdx) {
let i, key
const map={}
for (i=beginIdx; i <=endIdx; ++i) {
key=children[i].key
if (isDef(key)) map[key]=i
}
return map
}
遍歷尋找
// sameVnode 是對(duì)比新舊節(jié)點(diǎn)是否相同的函數(shù)
function findIdxInOld (node, oldCh, start, end) {
for (let i=start; i < end; i++) {
const c=oldCh[i]
if (isDef(c) && sameVnode(node, c)) return i
}
}
2、React 中 setState 什么時(shí)候是同步的,什么時(shí)候是異步的?
參考答案
在React中,如果是由React引發(fā)的事件處理(比如通過(guò)onClick引發(fā)的事件處理),調(diào)用setState不會(huì)同步更新this.state,除此之外的setState調(diào)用會(huì)同步執(zhí)行this.state。所謂“除此之外”,指的是繞過(guò)React通過(guò)addEventListener直接添加的事件處理函數(shù),還有通過(guò)setTimeout/setInterval產(chǎn)生的異步調(diào)用。
**原因:**在React的setState函數(shù)實(shí)現(xiàn)中,會(huì)根據(jù)一個(gè)變量isBatchingUpdates判斷是直接更新this.state還是放到隊(duì)列中回頭再說(shuō),而isBatchingUpdates默認(rèn)是false,也就表示setState會(huì)同步更新this.state,但是,有一個(gè)函數(shù)batchedUpdates,這個(gè)函數(shù)會(huì)把isBatchingUpdates修改為true,而當(dāng)React在調(diào)用事件處理函數(shù)之前就會(huì)調(diào)用這個(gè)batchedUpdates,造成的后果,就是由React控制的事件處理過(guò)程setState不會(huì)同步更新this.state。
3、下面輸出什么
class Example extends React.Component {
constructor() {
super();
this.state={
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 1 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 2 次 log
setTimeout(()=> {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 3 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 4 次 log
}, 0);
}
render() {
return null;
}
};
1、第一次和第二次都是在 react 自身生命周期內(nèi),觸發(fā)時(shí) isBatchingUpdates 為 true,所以并不會(huì)直接執(zhí)行更新 state,而是加入了 dirtyComponents,所以打印時(shí)獲取的都是更新前的狀態(tài) 0。
2、兩次 setState 時(shí),獲取到 this.state.val 都是 0,所以執(zhí)行時(shí)都是將 0 設(shè)置成 1,在 react 內(nèi)部會(huì)被合并掉,只執(zhí)行一次。設(shè)置完成后 state.val 值為 1。
3、setTimeout 中的代碼,觸發(fā)時(shí) isBatchingUpdates 為 false,所以能夠直接進(jìn)行更新,所以連著輸出 2,3。
輸出: 0 0 2 3
4、為什么虛擬dom會(huì)提高性能?
參考答案
虛擬dom相當(dāng)于在js和真實(shí)dom中間加了一個(gè)緩存,利用dom diff算法避免了沒(méi)有必要的dom操作,從而提高性能。
具體實(shí)現(xiàn)步驟如下:
用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹(shù)的結(jié)構(gòu);然后用這個(gè)樹(shù)構(gòu)建一個(gè)真正的 DOM 樹(shù),插到文檔當(dāng)中
當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹(shù)。然后用新的樹(shù)和舊的樹(shù)進(jìn)行比較,記錄兩棵樹(shù)差異
把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹(shù)上,視圖就更新了。
css
1、分析比較 opacity: 0、visibility: hidden、display: none 優(yōu)劣和適用場(chǎng)景
參考答案
結(jié)構(gòu):display:none: 會(huì)讓元素完全從渲染樹(shù)中消失,渲染的時(shí)候不占據(jù)任何空間, 不能點(diǎn)擊, visibility: hidden:不會(huì)讓元素從渲染樹(shù)消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容不可見(jiàn),不能點(diǎn)擊 opacity: 0: 不會(huì)讓元素從渲染樹(shù)消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容不可見(jiàn),可以點(diǎn)擊
繼承:display: none:是非繼承屬性,子孫節(jié)點(diǎn)消失由于元素從渲染樹(shù)消失造成,通過(guò)修改子孫節(jié)點(diǎn)屬性無(wú)法顯示。visibility: hidden:是繼承屬性,子孫節(jié)點(diǎn)消失由于繼承了hidden,通過(guò)設(shè)置visibility: visible;可以讓子孫節(jié)點(diǎn)顯式。
性能:displaynone : 修改元素會(huì)造成文檔回流,讀屏器不會(huì)讀取display: none元素內(nèi)容,性能消耗較大 visibility:hidden: 修改元素只會(huì)造成本元素的重繪,性能消耗較少讀屏器讀取visibility: hidden元素內(nèi)容 opacity: 0 :修改元素會(huì)造成重繪,性能消耗較少
聯(lián)系:它們都能讓元素不可見(jiàn)
2、清除浮動(dòng)的方式有哪些?比較好的是哪一種?
參考答案
常用的一般為三種.clearfix, clear:both,overflow:hidden;
比較好是 .clearfix,偽元素萬(wàn)金油版本,后兩者有局限性.
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
<!--
為毛沒(méi)有 zoom ,_height 這些,IE6,7這類(lèi)需要 csshack 不再我們考慮之內(nèi)了
.clearfix 還有另外一種寫(xiě)法,
-->
.clearfix:before, .clearfix:after {
content:"";
display:table;
}
.clearfix:after{
clear:both;
overflow:hidden;
}
.clearfix{
zoom:1;
}
<!--
用display:table 是為了避免外邊距margin重疊導(dǎo)致的margin塌陷,
內(nèi)部元素默認(rèn)會(huì)成為 table-cell 單元格的形式
-->
clear:both:若是用在同一個(gè)容器內(nèi)相鄰元素上,那是賊好的,有時(shí)候在容器外就有些問(wèn)題了, 比如相鄰容器的包裹層元素塌陷
overflow:hidden:這種若是用在同個(gè)容器內(nèi),可以形成 BFC避免浮動(dòng)造成的元素塌陷
4、css sprite 是什么,有什么優(yōu)缺點(diǎn)
參考答案
概念:將多個(gè)小圖片拼接到一個(gè)圖片中。通過(guò) background-position 和元素尺寸調(diào)節(jié)需要顯示的背景圖案。
優(yōu)點(diǎn):
減少 HTTP 請(qǐng)求數(shù),極大地提高頁(yè)面加載速度
增加圖片信息重復(fù)度,提高壓縮比,減少圖片大小
更換風(fēng)格方便,只需在一張或幾張圖片上修改顏色或樣式即可實(shí)現(xiàn)
缺點(diǎn):
圖片合并麻煩
維護(hù)麻煩,修改一個(gè)圖片可能需要重新布局整個(gè)圖片,樣式
5、link與@import的區(qū)別
參考答案
link是 HTML 方式, @import是 CSS 方式
link最大限度支持并行下載,@import過(guò)多嵌套導(dǎo)致串行下載,出現(xiàn)FOUC
link可以通過(guò)rel="alternate stylesheet"指定候選樣式
瀏覽器對(duì)link支持早于@import,可以使用@import對(duì)老瀏覽器隱藏樣式
@import必須在樣式規(guī)則之前,可以在 css 文件中引用其他文件
總體來(lái)說(shuō):link 優(yōu)于@import
6、display: block;和display: inline;的區(qū)別
參考答案
block元素特點(diǎn):
1.處于常規(guī)流中時(shí),如果width沒(méi)有設(shè)置,會(huì)自動(dòng)填充滿(mǎn)父容器 2.可以應(yīng)用margin/padding 3.在沒(méi)有設(shè)置高度的情況下會(huì)擴(kuò)展高度以包含常規(guī)流中的子元素 4.處于常規(guī)流中時(shí)布局時(shí)在前后元素位置之間(獨(dú)占一個(gè)水平空間) 5.忽略vertical-align
inline元素特點(diǎn)
1.水平方向上根據(jù)direction依次布局
2.不會(huì)在元素前后進(jìn)行換行
3.受white-space控制
4.margin/padding在豎直方向上無(wú)效,水平方向上有效
5.width/height屬性對(duì)非替換行內(nèi)元素?zé)o效,寬度由元素內(nèi)容決定
6.非替換行內(nèi)元素的行框高由line-height確定,替換行內(nèi)元素的行框高由height,margin,padding,border決定 7.浮動(dòng)或絕對(duì)定位時(shí)會(huì)轉(zhuǎn)換為block8.vertical-align屬性生效
7、容器包含若干浮動(dòng)元素時(shí)如何清理浮動(dòng)
參考答案
容器元素閉合標(biāo)簽前添加額外元素并設(shè)置clear: both
父元素觸發(fā)塊級(jí)格式化上下文(見(jiàn)塊級(jí)可視化上下文部分)
設(shè)置容器元素偽元素進(jìn)行清理推薦的清理浮動(dòng)方法
/**
* 在標(biāo)準(zhǔn)瀏覽器下使用
* 1 content內(nèi)容為空格用于修復(fù)opera下文檔中出現(xiàn)
* contenteditable屬性時(shí)在清理浮動(dòng)元素上下的空白
* 2 使用display使用table而不是block:可以防止容器和
* 子元素top-margin折疊,這樣能使清理效果與BFC,IE6/7
* zoom: 1;一致
**/
.clearfix:before,
.clearfix:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.clearfix:after {
clear: both;
}
/**
* IE 6/7下使用
* 通過(guò)觸發(fā)hasLayout實(shí)現(xiàn)包含浮動(dòng)
**/
.clearfix {
*zoom: 1;
}
8、PNG,GIF,JPG 的區(qū)別及如何選
參考答案
GIF:
8 位像素,256 色
無(wú)損壓縮
支持簡(jiǎn)單動(dòng)畫(huà)
支持 boolean 透明
適合簡(jiǎn)單動(dòng)畫(huà)
JPEG:
顏色限于 256
有損壓縮
可控制壓縮質(zhì)量
不支持透明
適合照片
PNG:
有 PNG8 和 truecolor PNG
PNG8 類(lèi)似 GIF 顏色上限為 256,文件小,支持 alpha 透明度,無(wú)動(dòng)畫(huà)
適合圖標(biāo)、背景、按鈕
9、display,float,position 的關(guān)系
參考答案
如果display為 none,那么 position 和 float 都不起作用,這種情況下元素不產(chǎn)生框
否則,如果 position 值為 absolute 或者 fixed,框就是絕對(duì)定位的,float 的計(jì)算值為 none,display 根據(jù)下面的表格進(jìn)行調(diào)整。
否則,如果 float 不是 none,框是浮動(dòng)的,display 根據(jù)下表進(jìn)行調(diào)整
否則,如果元素是根元素,display 根據(jù)下表進(jìn)行調(diào)整
其他情況下 display 的值為指定值 總結(jié)起來(lái):絕對(duì)定位、浮動(dòng)、根元素都需要調(diào)整display
10、如何水平居中一個(gè)元素
參考答案
如果需要居中的元素為常規(guī)流中 inline 元素,為父元素設(shè)置text-align: center;即可實(shí)現(xiàn)
如果需要居中的元素為常規(guī)流中 block 元素,1)為元素設(shè)置寬度,2)設(shè)置左右 margin 為 auto。3)IE6 下需在父元素上設(shè)置text-align: center;,再給子元素恢復(fù)需要的值
<body>
<div class="content">
aaaaaa aaaaaa a a a a a a a a
</div>
</body>
<style>
body {
background: #DDD;
text-align: center; /* 3 */
}
.content {
width: 500px; /* 1 */
text-align: left; /* 3 */
margin: 0 auto; /* 2 */
background: purple;
}
</style>
如果需要居中的元素為浮動(dòng)元素,1)為元素設(shè)置寬度,2)position: relative;,3)浮動(dòng)方向偏移量(left 或者 right)設(shè)置為 50%,4)浮動(dòng)方向上的 margin 設(shè)置為元素寬度一半乘以-1
<body>
<div class="content">
aaaaaa aaaaaa a a a a a a a a
</div>
</body>
<style>
body {
background: #DDD;
}
.content {
width: 500px; /* 1 */
float: left;
position: relative; /* 2 */
left: 50%; /* 3 */
margin-left: -250px; /* 4 */
background-color: purple;
}
</style>
如果需要居中的元素為絕對(duì)定位元素,1)為元素設(shè)置寬度,2)偏移量設(shè)置為 50%,3)偏移方向外邊距設(shè)置為元素寬度一半乘以-1
<body>
<div class="content">
aaaaaa aaaaaa a a a a a a a a
</div>
</body>
<style>
body {
background: #DDD;
position: relative;
}
.content {
width: 800px;
position: absolute;
left: 50%;
margin-left: -400px;
background-color: purple;
}
</style>
如果需要居中的元素為絕對(duì)定位元素,1)為元素設(shè)置寬度,2)設(shè)置左右偏移量都為 0,3)設(shè)置左右外邊距都為 auto
<body>
<div class="content">
aaaaaa aaaaaa a a a a a a a a
</div>
</body>
<style>
body {
background: #DDD;
position: relative;
}
.content {
width: 800px;
position: absolute;
margin: 0 auto;
left: 0;
right: 0;
background-color: purple;
}
</style>
JavaScript
1、JS有幾種數(shù)據(jù)類(lèi)型,其中基本數(shù)據(jù)類(lèi)型有哪些?
參考答案
七種數(shù)據(jù)類(lèi)型
Boolean
Null
Undefined
Number
String
Symbol (ECMAScript 6 新定義)
Object
(ES6之前)其中5種為基本類(lèi)型:string,number,boolean,null,undefined,
ES6出來(lái)的Symbol也是原始數(shù)據(jù)類(lèi)型 ,表示獨(dú)一無(wú)二的值
Object為引用類(lèi)型(范圍挺大),也包括數(shù)組、函數(shù),
2、Promise 構(gòu)造函數(shù)是同步執(zhí)行還是異步執(zhí)行,那么 then 方法呢?
參考答案
const promise=new Promise((resolve, reject)=> {
console.log(1)
resolve()
console.log(2)
})
promise.then(()=> {
console.log(3)
})
console.log(4)
輸出結(jié)果是:
1
2
4
3
promise構(gòu)造函數(shù)是同步執(zhí)行的,then方法是異步執(zhí)行的
Promise new的時(shí)候會(huì)立即執(zhí)行里面的代碼 then是微任務(wù) 會(huì)在本次任務(wù)執(zhí)行完的時(shí)候執(zhí)行 setTimeout是宏任務(wù) 會(huì)在下次任務(wù)執(zhí)行的時(shí)候執(zhí)行
文章轉(zhuǎn)載:樂(lè)字節(jié)
端開(kāi)發(fā)經(jīng)典面試題及答案——CSS篇
一、CSS選擇器的優(yōu)先級(jí)排序,怎么計(jì)算權(quán)值?
二、display:none和visibility:hidden的區(qū)別
三、CSS的引用方式有哪些?它們的區(qū)別?
四、CSS有哪些選擇符?可繼承的屬性有哪些?
CSS選擇符:
可繼承和不可繼承的屬性:
五、fixed和absolute的區(qū)別?
六、如何實(shí)現(xiàn)水平、垂直居中?
1、利用定位+margin:auto
2、利用定位+margin:負(fù)值
3、利用定位+transform
4、table布局
5、flex布局
6、gird布局
七、如何實(shí)現(xiàn)左側(cè)邊欄固定,其他內(nèi)容自適應(yīng)?
1、左側(cè)固定寬度,右側(cè)flex自適應(yīng) flex:1,占據(jù)剩余空間;
2、左側(cè)固定寬度,右側(cè)flex自適應(yīng) flex:1, 占據(jù)剩余空間;
3、左側(cè)固定寬度左浮動(dòng),右側(cè)設(shè)margin-left等于左側(cè)寬度;
4、左側(cè)固定寬度、固定定位,右側(cè)寬度100%;
5、左側(cè)寬度固定、固定定位,右側(cè)左邊距等于左側(cè)寬度;
6、雙左浮動(dòng),右側(cè)計(jì)算屬性計(jì)算寬度;
7、左側(cè)左浮,右側(cè)右浮動(dòng),右側(cè)計(jì)算寬度;
8、左側(cè)固定寬度,display:inline-block,右側(cè)右浮動(dòng),計(jì)算寬度。
八、css3的新特性
1、CSS3新特性之選擇器
2、CSS3新特性之樣式
3、CSS3新特性之transition 過(guò)渡
4、CSS3新特性之transform 轉(zhuǎn)換
5、CSS3新特性之a(chǎn)nimation 動(dòng)畫(huà)
6、CSS3新特性之漸變
九、了解過(guò)哪些頁(yè)面布局?
十、Sass寫(xiě)一個(gè)數(shù)組?
十一、什么時(shí)候用less
1、函數(shù)式編程css
2、自定義變量用于整體主題調(diào)整
3、嵌套語(yǔ)法簡(jiǎn)化開(kāi)發(fā)復(fù)雜度
4、頁(yè)面層級(jí)結(jié)構(gòu)多,重復(fù)使用的css代碼較多時(shí)
十二、animation和transition
十三、盒子模型概念
十四、px、em、rem、%、vm、vh
十五、display的值和作用
十六、列舉兩種清除浮動(dòng)的方法
1、父元素添加overflow:hidden
??通過(guò)觸發(fā)BFC方式,實(shí)現(xiàn)清除浮動(dòng)
??優(yōu)點(diǎn):代碼簡(jiǎn)潔
??缺點(diǎn):內(nèi)容增多的時(shí)候容易造成不會(huì)自動(dòng)換行導(dǎo)致內(nèi)容被隱藏掉,無(wú)法顯示要溢出的元素。
2、使用after偽元素清除浮動(dòng)
??優(yōu)點(diǎn):符合閉合浮動(dòng)思想,結(jié)構(gòu)語(yǔ)義化正確。
??缺點(diǎn):ie6-7不支持偽元素:after,使用zoom:1觸發(fā)hasLayout。
以上就是霸哥今日整理的前端經(jīng)典面試題及答案CSS篇,如有疑問(wèn),歡迎私信霸哥!
、HTML5有哪些新特性?
2、HTML 中的塊級(jí)元素和行內(nèi)元素有什么區(qū)別?
3、解釋一下HTML中的塊級(jí)元素、行內(nèi)元素、行內(nèi)塊元素
4、簡(jiǎn)述一下你對(duì)HTML語(yǔ)義化的理解?
5、解釋一下 瀏覽器的標(biāo)準(zhǔn)模式和怪異模式 (混雜模式)
6、請(qǐng)簡(jiǎn)述前端需要注意哪些SEO相關(guān)的問(wèn)題
7、請(qǐng)解釋一下 HTML 中的 doctype 是什么?
8、websocket 如何兼容低版本瀏覽器?
9、如何禁止input展示輸入的歷史記錄
10、簡(jiǎn)述從輸入網(wǎng)址到頁(yè)面顯示的整個(gè)過(guò)程
11、前端如何選擇圖片的格式?
12、HTML的優(yōu)雅降級(jí)和漸進(jìn)增強(qiáng)的區(qū)別?
13、iframe 是什么?有哪些優(yōu)缺點(diǎn)?
14、請(qǐng)簡(jiǎn)述Canvas和Svg的區(qū)別
15、請(qǐng)?jiān)敿?xì)說(shuō)明meta中viewport的作用
16、HTML的作用
17、HTML5的文件離線儲(chǔ)存怎么使用,工作原理是什么?
答案:
保存圖片,掃
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。