胡哥面试视频手录
胡哥面試視頻手錄
- 胡哥面試手錄
- 1. 如何提高工作效率?
- 2. 面試的時(shí)候怎么自我介紹比較好?
- 3. 面試官問:“你還有什么想問的嗎?”,這個(gè)時(shí)候該怎么回答?
- 4. 面試的簡歷,應(yīng)該從這五大方面去寫:
- 5. 你的近期和長期的職業(yè)規(guī)劃是怎樣的?
- 6. 前端工作中該如何與同事相處、溝通?
- 7. 面試官問,入職之后將如何開展工作,應(yīng)該怎么回答?
- 8. 面試官:對(duì)于加班你怎么看?
- 9. 請(qǐng)描述一下,你以前公司的開發(fā)流程是怎么樣的?
- 10. Web 前端崗位工資的基本構(gòu)成和發(fā)放。
- 11. 公司面臨一些問題,我們?cè)摵稳ズ螐?#xff1f;
- 12. 前端找工作,被公司工資壓價(jià)怎么辦?
- 13. async 和 await 的區(qū)別
- 1. 區(qū)別
- 2. 優(yōu)點(diǎn)
- 3. 補(bǔ)充
- 14. 打包之后 dist 目錄過大,該如何解決
- 15. 接口安全該如何回答
- aes加密工具:crypto.js 對(duì)稱加密
- rsa加密工具:jsencrypt 算法
- 對(duì)稱加密與非對(duì)稱加密的區(qū)別是什么
- 16. keep-alive
- 17. vuex 如何回答?
- 18. 防抖節(jié)流
- 19. 時(shí)間復(fù)雜度和空間復(fù)雜度(非胡哥)
- 20. webpack的工作原理(打包原理)
- webpack的核心概念(天禹+熊鍵)
- 21. 數(shù)組扁平化算法
- 22. setTimeout時(shí)間為0_,程序發(fā)生了什么?
- 23. setTimeout時(shí)間誤差的解決辦法
- 24. js面向?qū)ο蟮南嚓P(guān)總結(jié)
- es5:
- es6:
- 25. 高階函數(shù)
- 26. 瀏覽器引擎Chrome(v8)
- 27. 瀏覽器是如何渲染頁面的
- 28. js程序的執(zhí)行順序是怎樣的?
- 29. vue-loader的作用
- 30. node可以通過哪些方法可以防止程序奔潰
- 31. http 和 https的區(qū)別
- 32. XSS攻擊是什么?如何避免?
- 33. csrf 攻擊(非胡哥)
- 34. css hack
- 35. src和href的區(qū)別
- 36. link和@import的區(qū)別?(非胡哥)
- 37. 胡哥快排
- 38. 邊界塌陷(外邊距重合)
- 未完待續(xù)。。。
胡哥面試手錄
1. 如何提高工作效率?
我是做前端工作的,我會(huì)把工作分為三個(gè)部分。
比如說:項(xiàng)目前、項(xiàng)目中期和項(xiàng)目后期。
這樣的話,我們?cè)谇啊⒅小⒑笃谌齻€(gè)節(jié)點(diǎn)上面的效率就會(huì)得到最大的提升。
2. 面試的時(shí)候怎么自我介紹比較好?
注:你做自我介紹的時(shí)候,興趣愛好、學(xué)歷啥的簡歷上都有,不用拿來介紹。
我叫xxx,我掌握的技能有哪些?如:H5、C3、js、element-plus、node、vue等等。
在工作中我的打包工具用的是什么?如:webpack、vite。
我的版本控制工具(分布式)用的是什么?如:git
說完這些之后,最好加一些,在以前的工作當(dāng)中,我們前端經(jīng)常遇到的是什么問題?比如說接口安全的問題、常見的一些攻擊的問題、適配的問題等等。
3. 面試官問:“你還有什么想問的嗎?”,這個(gè)時(shí)候該怎么回答?
在這個(gè)時(shí)候,對(duì)于成熟的前端人員來說的話,想問的相對(duì)來說多一些:
4. 面試的簡歷,應(yīng)該從這五大方面去寫:
個(gè)人信息:以簡潔明了為主。姓名、學(xué)歷、畢業(yè)院校、電話、郵箱,不要超過6項(xiàng)。
專業(yè)技能:以充實(shí)為主。把會(huì)的技能多寫上一些。
過往的經(jīng)歷:過往的公司和時(shí)間要搭配,不要有空窗。
項(xiàng)目介紹:一到兩年(包裝2-3個(gè)項(xiàng)目)、三年(3-4個(gè)項(xiàng)目)。你工作3年就只有這3個(gè)項(xiàng)目嗎?回答:我放到簡歷上的項(xiàng)目,是我認(rèn)為比較好的,其實(shí)其他的一些小的項(xiàng)目,有一些雷同的地方,我沒有往上寫,所以從中挑選了基本較好的項(xiàng)目。
注意點(diǎn):
自我評(píng)價(jià):本人比較善于溝通,團(tuán)隊(duì)協(xié)作能力比較強(qiáng),能夠完成領(lǐng)導(dǎo)交待前端相關(guān)的工作任務(wù)。
5. 你的近期和長期的職業(yè)規(guī)劃是怎樣的?
注意:聊的時(shí)候,一定不要跟人家談年限,最近兩年要干什么。。。
回答:我作為一個(gè)前端來說,我近期的職業(yè)規(guī)劃是把咱們公司的項(xiàng)目做好,另外呢,學(xué)無止境,把我的技術(shù)得以提升。多學(xué)一些組件、插件,多學(xué)一到兩款框架。
對(duì)于中長期的規(guī)劃來說的話,我打算呢將來我再研究一門后臺(tái)語言,比如說像Java、PHP、Python這些我研究一門,爭取研究一門之后,可以更加方便咱們前端跟后端去溝通,為咱們公司更好的去服務(wù)。另外呢,我也相信,咱們公司有合理的晉升機(jī)制和制度。所以呢,如果將來公司有這樣的機(jī)會(huì),這種機(jī)會(huì)放在我跟前,我也是會(huì)毛遂自薦,服務(wù)好公司。
這就是我近期、中期和長期的一個(gè)職業(yè)規(guī)劃。
6. 前端工作中該如何與同事相處、溝通?
7. 面試官問,入職之后將如何開展工作,應(yīng)該怎么回答?
如果公司錄用我了,我將會(huì)帶著我以前的技術(shù)和經(jīng)驗(yàn),把這些東西帶到咱們的項(xiàng)目中,讓咱們的項(xiàng)目更好,更人性化。
我會(huì)快速的掌握咱們現(xiàn)在所寫的項(xiàng)目。包括它的路由是怎么架構(gòu)的,接口的請(qǐng)求是怎么來處理的,還有它里面的一些難點(diǎn)重點(diǎn)的技術(shù),我以前有沒有處理過。
這些都是我們前端人員在剛?cè)肼毜臅r(shí)候要做的事情。以避免后邊在開展工作中遇到這些問題,再去處理就比較難處理了。
要考慮我是不是需要后臺(tái)或者其他的技術(shù)人員去配合,這個(gè)也要有一個(gè)正確的評(píng)估。為啥要評(píng)估這個(gè)呢?如果問題到了跟前再去跟后臺(tái)溝通,這樣的話,很可能會(huì)打亂后臺(tái)的工作計(jì)劃。
進(jìn)入公司以后,我打算基于以上三個(gè)方面開展工作。
8. 面試官:對(duì)于加班你怎么看?
注意點(diǎn):
回答:
我可以接受加班,不管是自己的原因還是其他的一些什么原因,都是可以免費(fèi)接受的。
9. 請(qǐng)描述一下,你以前公司的開發(fā)流程是怎么樣的?
在我們公司以前技術(shù)部分這么幾個(gè)角色:
產(chǎn)品經(jīng)理、UI、前端人員、后臺(tái)(后臺(tái)是一個(gè)統(tǒng)稱:Java、PHP、Android、iOS都是在寫后臺(tái)的業(yè)務(wù)邏輯),以上這些角色去進(jìn)行項(xiàng)目開發(fā)。
前端在項(xiàng)目中的地位和工作流程:
產(chǎn)品經(jīng)理: 當(dāng)一個(gè)項(xiàng)目進(jìn)來,最先跟這個(gè)項(xiàng)目客戶去接觸的一般是產(chǎn)品經(jīng)理,產(chǎn)品經(jīng)理的作用是:和客戶進(jìn)行聊天,聊天的過程中,他會(huì)做一個(gè)產(chǎn)品需求文檔(說白了,就是客戶想要什么?),在這里面有一個(gè)重要的職責(zé),有時(shí)候客戶很盲目,他不知道自己的需求到底是什么(比如說他想做一個(gè)賣菜的網(wǎng)站,他可能不知道什么是APP,但是他們會(huì)使用),這個(gè)時(shí)候產(chǎn)品經(jīng)理要做的就是正確引導(dǎo)客戶需求。然后,產(chǎn)品經(jīng)理需要把這些需求跟UI、前端等技術(shù)人員去講明白。
UI: 出了需求文檔之后,產(chǎn)品經(jīng)理會(huì)把文檔給到UI、前端、后臺(tái)各一份。UI 把需求文檔做成原型圖(黑白的,像黑白照片)和設(shè)計(jì)圖,UI在整個(gè)工期里面大概要占到三分之一。當(dāng)設(shè)計(jì)稿出來后,同時(shí)交給前端和后臺(tái),因?yàn)榛旧锨岸撕秃蠖烁苫钍遣⑿械摹?/p>
前端: 開始根據(jù)頁面去制作各種各樣的效果。或者是DIA(diagram 圖表)或者是小程序。在這個(gè)過程中后臺(tái)也在干活。
后臺(tái): 后臺(tái)就要開發(fā)它對(duì)應(yīng)的數(shù)據(jù)管理部分。除此之外,后臺(tái)還需要去做 API 接口的東西,這個(gè)接口是為前端去開發(fā)的。
等到前端的頁面布局完了,后臺(tái)的接口也寫完了,剩下的就是前端去渲染數(shù)據(jù),調(diào)用接口里面相對(duì)應(yīng)的數(shù)據(jù)就可以了。這些完了之后,就是一個(gè)測試階段。
測試階段: 測試階段是 UI、前端、后臺(tái)都需要參與的,如果有專業(yè)的測試,他們的工作量就稍微會(huì)少一點(diǎn)。都參與可以保證出現(xiàn)問題可以及時(shí)得到處理。
部署: 測試完成之后,再把這個(gè)項(xiàng)目部署到客戶的服務(wù)器上去。
基本上整個(gè)工作流程就是這樣子的。
10. Web 前端崗位工資的基本構(gòu)成和發(fā)放。
如:10k為例,我上家公司是這樣發(fā)放的:
基本工資:5000
崗位工資:如前端 3000
績效工資:2000左右(總工資的15%-20% )
績效工資是一個(gè)考核標(biāo)準(zhǔn),干得好才有,你負(fù)責(zé)的部分出了問題會(huì)扣一部分或者扣除全部。
補(bǔ)貼補(bǔ)助:1000以內(nèi)(話補(bǔ)、餐補(bǔ)、車補(bǔ)等等)。
社保公積金:一般情況下公積金+社保占 10%左右。
扣稅:5000以上需要交稅
真正到手的大概是九千左右的一個(gè)范圍
11. 公司面臨一些問題,我們?cè)摵稳ズ螐?#xff1f;
如果這個(gè)時(shí)候我走了,我會(huì)得到什么,我會(huì)失去什么?
我得到了:我得到的肯定是一份新工作,需要吃飯穿衣嘛這個(gè)很正常。
我失去了:我會(huì)失去老板和領(lǐng)導(dǎo)對(duì)我的信任,俗話說:“患難見真情”,如果我跟他們共渡難關(guān),在工作中共同努力克服了困難,挺過這一關(guān),那我在這個(gè)公司的價(jià)值會(huì)大大提升。而且我的口碑也會(huì)好很多。
每一個(gè)員工應(yīng)該各司其職,盡職盡責(zé)把自己的工作做好,做好之后,才能夠讓公司踏踏實(shí)實(shí),放心去解決問題。當(dāng)然在自己的事情完成得很好的情況下,在力所能及的范圍之內(nèi)去幫助其他的同事。如果一個(gè)團(tuán)隊(duì)、一個(gè)公司的人都有這樣的想法,我覺得老板和領(lǐng)導(dǎo)一定會(huì)想盡辦法去解決公司的困難。
12. 前端找工作,被公司工資壓價(jià)怎么辦?
注:我說15000,HR壓榨成9000
做兩手準(zhǔn)備:
這個(gè)時(shí)候跟 HR 去較勁,很大概率是會(huì)談崩的。
13. async 和 await 的區(qū)別
1. 區(qū)別
Async:
async 用來定義函數(shù)的,異步函數(shù),打印函數(shù)名會(huì)得到一個(gè)promise對(duì)象。可以使用函數(shù)名稱來調(diào)用.then方法,如:函數(shù)名稱.then
async 內(nèi)部實(shí)現(xiàn),有返回值。其實(shí)是內(nèi)部調(diào)用了 promise.resolve(),然后把它轉(zhuǎn)換成一個(gè)promise對(duì)象。如果出錯(cuò)的話,調(diào)用的是promise.reject()。它用catch捕獲了一下
Await:
await 理論上來說后面可以跟任意的表達(dá)式。但是一般是跟promise的表達(dá)式
async function add() {const res = await 123console.log(res) // 123return res } console.log(add()) // 成功的promise,值是123await 等待后邊的promise對(duì)象執(zhí)行完畢,拿到了promise.resolve()的返回值之后,在往后繼續(xù)去執(zhí)行后邊的代碼,所以await有一個(gè)等待的意思。
await關(guān)鍵字只能寫在async的函數(shù)里。
await 后邊的表達(dá)式可能是失敗的,await 只能拿到成功的結(jié)果,如果失敗會(huì)向?yàn)g覽器控制臺(tái)拋出錯(cuò)誤。所以建議把a(bǔ)wait的代碼放到try…catch語句中捕獲錯(cuò)誤會(huì)比較好。
async function test() {const res = await Promise.reject(123)return res } console.log(test()) // Uncaught (in promise) 123 async function test() {try {const res = await Promise.reject(123)} catch (error) {console.log('error', error) // 2. error 123} } console.log(test()) console.log(111) // 1. 1112. 優(yōu)點(diǎn)
- async和await屬于ES2016(ES7)的語法。
- async和await是異步執(zhí)行的,但是寫代碼的時(shí)候是同步的
- async和await方式更容易讓開發(fā)人員維護(hù)
3. 補(bǔ)充
promise 和 async await 區(qū)別:
- promise 屬于es6的語法,promise是鏈?zhǔn)秸{(diào)用的
- promise中包含了catch,而async和await是在函數(shù)內(nèi)自己定義catch
- promise 提供方法要多一些。如:all, race, any, finally(原型方法), then(原型方法), catch(原型方法)
?
14. 打包之后 dist 目錄過大,該如何解決
命令:npm run build
需要在vue.config.js中配置 entry, output
處理方案:
打包后,會(huì)在dist下生成.map文件,那么這個(gè)文件其實(shí)是不必要的
解決:在vue.config.js中配置文件中:productionSourceMap: false。這樣就不會(huì)生成.map文件了。
使用組件和路由懶加載
組件和路由懶加載是按需加載的,這樣會(huì)降低一些文件的大小。
對(duì)于文件和圖片,最好壓縮一下。可以使用這個(gè)組件(此組件需要安裝):compression-webpack-plugin
導(dǎo)入組件:compression-webpack-plugin
配置:
- 最小化代碼配置 minisize(true)
- 分割代碼 splitChunks
- 超過限定值的文件進(jìn)行壓縮 threshold: 文件大小(字節(jié)為單位)
15. 接口安全該如何回答
安全問題是一個(gè)很寬泛的問題,如:xss和csrf攻擊等等。
這里主要談?wù)摰氖墙涌诘陌踩珕栴}。
接口安全:防止傳輸過程中,數(shù)據(jù)被抓包。我們會(huì)在數(shù)據(jù)傳輸?shù)臅r(shí)候(前臺(tái)傳給后臺(tái),后臺(tái)傳給前臺(tái))進(jìn)行加密和解密。
常用的加密算法:
aes rsa SHA1 SHA256 md5 … 有很多的算法
胡哥用過的有 aes rsa
aes加密工具:crypto.js 對(duì)稱加密
aes加密工具的使用:
安裝:npm i crypto-js –save -dev
在utils工具文件夾下創(chuàng)建crypto.js文件
crypto.js中寫入
import cryptojs from 'crypto-js' export default {encrypto(str) { // 加密// 生成秘鑰// 秘鑰是前端和后端都知道的,但是網(wǎng)絡(luò)上是不知道的,所以他們截取去了也沒有用。比如說我們前端生成秘鑰是11111,那么后端也要用11111去解密let key = crytojs.enc.utf8.parse('11111') // 生成偏移量 --- 一般都是傳進(jìn)來的字符串// 生成偏移量作用:如果字符串內(nèi)容長度不夠,會(huì)自動(dòng)補(bǔ)齊let srcs = cryptojs.enc.utf8.parse(str)// 加密 --- 參數(shù):偏移量,秘鑰,配置加密的參數(shù)let encrypted = cryptojs.AES.encrypt(str,key,{mode: cryptojs.mode.ECB, // 加密模式// ECB 表示等量加密,就是說長度跟你的str相同padding: crytojs.pad.pkcs7 // 加密、解密的標(biāo)準(zhǔn)})return encrypted.toString()},decrypto(str) { // 解密let key = crytojs.enc.utf8.parse('11111') // 解密不需要偏移量// 加密 --- 參數(shù):偏移量,秘鑰,配置加密的參數(shù)let decrypted = cryptojs.AES.decrypt(str,key,{mode: cryptojs.mode.ECB, // 加密模式// ECB 表示等量加密,就是說長度跟你的str相同padding: crytojs.pad.pkcs7 // 加密、解密的標(biāo)準(zhǔn)})return decrypted.toString()} }注意:
rsa加密工具:jsencrypt 算法
jsencrypt 算法是一種非對(duì)稱加密算法,它得生成一對(duì)秘鑰,即公鑰和私鑰。前后端一樣的,加密的時(shí)候使用公鑰,解密的時(shí)候使用私鑰。
長度可以能是1024也可能是2048。已知破解的密碼長度為:768位。
rsa加密工具的使用:
安裝:npm i jsencrypt
在utils工具文件夾下創(chuàng)建jsencrypt.js文件
jsencrypt.js文件中寫入:
這里是生成公鑰 - 加密
function enjsencrypt(str) {var jsObj = new jsencrypt()var pubkey = ""jsObj.setPublicKey(pubkey)return jsObj.encrypt(str) }這里是生成私鑰 - 解密
function denjsencrypt(str) {var jsObj = new jsencrypt()var prikey = ""jsObj.setPublicKey(prikey)return jsObj.dencrypt(str) }詳解博客地址
對(duì)稱加密與非對(duì)稱加密的區(qū)別是什么
16. keep-alive
keep-alive 組件緩存,刷新的時(shí)候保持狀態(tài)。
keep-alive 緩存組件,避免組件內(nèi)的數(shù)據(jù)重復(fù)渲染,直接可以在頁面中調(diào)用。
注意看描述:我有一個(gè)導(dǎo)航欄,一級(jí)導(dǎo)航欄新聞、房產(chǎn)兩個(gè)。二級(jí)導(dǎo)航欄,新聞下有體育、財(cái)經(jīng)。我給整個(gè)一級(jí)導(dǎo)航欄新聞做了組件緩存。如:<keep-alive includes="News"></keep-alive>。
問題:我先點(diǎn)擊新聞,然后點(diǎn)擊體育,我再點(diǎn)擊房產(chǎn)。當(dāng)我點(diǎn)擊新聞的時(shí)候,我希望它能回到上一次的狀態(tài)體育。但是它不會(huì)。直接停留到新聞頁面了。
需求:點(diǎn)擊新聞–》點(diǎn)擊體育–》點(diǎn)擊社會(huì)–》回到新聞下的體育頁面
解決:
當(dāng)點(diǎn)擊新聞的時(shí)候,有兩個(gè)方法會(huì)觸發(fā):activated 和 deactivated
在新聞組件中寫:
let url; beforeRouteLeave() {url = this.$route.path } activated() {this.$router.push(url) }胡哥當(dāng)前視頻地址
17. vuex 如何回答?
vuex存放數(shù)據(jù)的狀態(tài)
需要安裝:npm i vuex
state 公共數(shù)據(jù) 組件中this.$store.state.變量名
mutations 同步方法 更新state中的數(shù)據(jù)
actions 異步方法,組件通過this.$store.dispatch(‘方法名’, 參數(shù))
getters 讀取state中的數(shù)據(jù)
commit 狀態(tài)提交,對(duì)mutation進(jìn)行提交
vuex頁面刷新,數(shù)據(jù)會(huì)重置。這里涉及到持久化的問題
解決:
把vuex中的數(shù)據(jù)放到localStorage中
插件vuex-persistedstate 這個(gè)插件需要安裝,然后在vuex中添加配置。
plugins: [createPersistedState({storage: window.sessionStorage })]persistedstate 本質(zhì)是使用了localStorage
18. 防抖節(jié)流
返回頂部:到達(dá)一定距離才會(huì)出現(xiàn)。
監(jiān)聽瀏覽器的滾動(dòng)時(shí)間,返回當(dāng)前滾動(dòng)條與頂部的距離。
<div>里面的內(nèi)容足夠多,讓其有滾動(dòng)條出現(xiàn)</div> <script> function showTop() { // 兼容獲取滾動(dòng)條位置var scrollTop = document.body.scrollTop || document.documentElement.scrollTopconsole.log('滾動(dòng)條位置', scrollTop) }window.onscroll = showTop <script>問題:滾動(dòng)條滾動(dòng)時(shí),方法觸發(fā)太頻繁
防抖
第一次觸發(fā)事件,不要立即執(zhí)行,給出一個(gè)事件間隔,比如200ms
<= 200ms 大于等于200毫秒,沒有觸發(fā),那就執(zhí)行函數(shù)
<= 200ms 大于等于200毫秒,再次觸發(fā)滾動(dòng),當(dāng)前的計(jì)時(shí)取消,重新計(jì)時(shí)
思路:如果短時(shí)間內(nèi),大量執(zhí)行事件,那就執(zhí)行一次
實(shí)現(xiàn):setTimeout + 閉包
<div>里面的內(nèi)容足夠多,讓其有滾動(dòng)條出現(xiàn)</div> <script>function showTop() {// 兼容獲取滾動(dòng)條位置var scrollTop = document.body.scrollTop || document.documentElement.scrollTopconsole.log('滾動(dòng)條位置', scrollTop)}function debounce(fnName, delay) { // 實(shí)現(xiàn)間隔調(diào)用showToplet timer = nullreturn function() {// 1000毫秒以內(nèi),這個(gè)timer存在了,那么就清除timerif(timer) {clearTimeout(timer)}// 1000毫秒以內(nèi),這個(gè)timer不存在。setTimeout 返回的是一個(gè)ID號(hào),從1開始timer = setTimeout(fnName, delay) // setTimeout(showTop, 1000)} }window.onscroll = debounce(showTop, 1000) </script>節(jié)流
個(gè)人感覺這里用節(jié)流會(huì)更好(沛華的代碼)
原理:在一定時(shí)間內(nèi)只執(zhí)行一次,降低觸發(fā)頻率
實(shí)現(xiàn):閉包
<div>里面的內(nèi)容足夠多,讓其有滾動(dòng)條出現(xiàn)</div> <script>function showTop() {// 兼容獲取滾動(dòng)條位置var scrollTop = document.body.scrollTop || document.documentElement.scrollTopconsole.log('滾動(dòng)條位置', scrollTop)} function throttle(fnName, delay) { // 實(shí)現(xiàn)間隔調(diào)用showToplet lastTime = 0return function() {// 獲取當(dāng)前時(shí)間let nowTime = Date.now()// 如果當(dāng)前時(shí)間 - 上一次的時(shí)間 < 傳進(jìn)來的時(shí)間 // 如:100 - 0 < 1000 嗎?如果小于1000,那就直接return了if(nowTime - lastTime < time) {return}// 大于傳進(jìn)來的時(shí)間就會(huì)執(zhí)行下面的代碼fnName.call(this)lastTime = nowTime} }window.onscroll = throttle(showTop, 1000) <script>19. 時(shí)間復(fù)雜度和空間復(fù)雜度(非胡哥)
定義:
20. webpack的工作原理(打包原理)
從入口文件開始出發(fā),根據(jù)入口文件的依賴關(guān)系找到所有的模塊
調(diào)用各種loader進(jìn)行處理,如果遇到處理不了的調(diào)用babel進(jìn)行語法轉(zhuǎn)換。(babel-loader core preset)
如果一些功能性的,如壓縮等這個(gè)時(shí)候就要調(diào)用plugins中相應(yīng)的插件來進(jìn)行處理
編輯階段 —》根據(jù)出口的路徑,打包多個(gè)chunk,如果把css和html等都摘出去了,那么就會(huì)打包多個(gè)chunk,最后統(tǒng)一生成一個(gè)bundle
loader plugin babel 的區(qū)別
- loader用于處理各種類型文件的
- plugin是用于loader處理不了的,一些功能性的插件
- babel 是一個(gè) JavaScript 編譯器。將es6+的語法轉(zhuǎn)換成瀏覽器所認(rèn)識(shí)的js代碼。babel是一個(gè)獨(dú)立的工具,可以不在webpack中使用。
工程化:
狹義上的理解: 將開發(fā)階段的代碼發(fā)布到生產(chǎn)環(huán)境,包含:構(gòu)建,分支管理,自動(dòng)化測試,部署
廣義上理解: 前端工程化應(yīng)該包含從編碼開始到發(fā)布,運(yùn)行和維護(hù)階段
webpack的核心概念(天禹+熊鍵)
什么是 webpack(熊鍵)
- Webpack 是一個(gè)模塊打包器(bundler)。
- 在 Webpack 看來, 前端的所有資源文件(js/json/css/img/less/…)都會(huì)作為模塊處理。
- 它將根據(jù)模塊的依賴關(guān)系進(jìn)行靜態(tài)分析,生成對(duì)應(yīng)的靜態(tài)資源。
五大“護(hù)法”(熊鍵)
- Entry:入口起點(diǎn)(entry point)指示 webpack 應(yīng)該使用哪個(gè)模塊,來作為構(gòu)建其內(nèi)部依賴圖的開始。
- Output: output 屬性告訴 webpack 在哪里輸出它所創(chuàng)建的 bundles,以及如何命名這些文件,默認(rèn)值為 ./dist。
- Loader: loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只能解析 JavaScript)。
- Plugins:插件則可以用于執(zhí)行范圍更廣的任務(wù)。插件的范圍包括,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量等。
- Mode:模式,有生產(chǎn)模式 production 和開發(fā)模式 development。
理解 Loader
- Webpack 本身只能加載 JS/JSON 模塊,如果要加載其他類型的文件(模塊),就需要使用對(duì)應(yīng)的 loader 進(jìn)行轉(zhuǎn)換/加載。
- Loader 本身也是運(yùn)行在 node.js 環(huán)境中的 JavaScript 模塊。
- 它本身是一個(gè)函數(shù),接受源文件作為參數(shù),返回轉(zhuǎn)換的結(jié)果。
- loader 一般以 xxx-loader 的方式命名,xxx 代表了這個(gè) loader 要做的轉(zhuǎn)換功能,比如 json-loader。
loader常處理的文件類型(天禹)
- 【file-loader】:提取源代碼圖片資源,到指定位置,可修改文件名等操作。
- 【url-loader】:與file-loader功能幾乎一致,優(yōu)勢是可以對(duì)圖片進(jìn)行動(dòng)態(tài)轉(zhuǎn)換base64編碼(控制limit屬性值可以控制閾值)。
備注:上述兩個(gè)loader中url-loader應(yīng)用比file-loader廣泛。 - 【eslint-loader】:對(duì)項(xiàng)目中的js語法進(jìn)行檢查。
- 【babel-loader】:將es6語法轉(zhuǎn)換為es5語法
備注1:直接使用只能處理簡單的語法,Promise等無法處理。
備注2:借助polyfill完成高級(jí)es6語法的轉(zhuǎn)換,缺點(diǎn):所有都轉(zhuǎn)換,無法按需轉(zhuǎn)換,生成的js體積大。
備注3:使用core-js配合polyfill完成按需轉(zhuǎn)換。
常用的 loader 有(熊鍵):
- eslint-loader:審查代碼是否存在語法錯(cuò)誤。
- babel-loader:將 es6 以上的語法編譯成 es5 及以下的語法。
- style-loader:是將 css-loader 打包好的 css 代碼以<style>標(biāo)簽的形式插入到 html 文件中。
- css-loader:用于解釋 @import 和 url(),并通過 import 后進(jìn)行解析,通常和 style-loader 結(jié)合使用。
- less-loader:將 less 語法編譯成 css 語法。
問題:
eslint-loader 配置:“0” “1” "2"代表什么?
- eslint 要想工作,必須定義配置文件,配置文件有兩種寫法
- .eslintrc.*
- package.json 文件中 eslintConfig
- 我們以第一種為例,項(xiàng)目根目錄新建.eslintrc.js
plugin常用插件
-
【extract-text-webpack-plugin】:用于提取項(xiàng)目中的css, 最終合并為一個(gè)單獨(dú)的文件。
備注:上述插件需要配合:css-loader、less-loader兩個(gè)loader使用,css-loader、less-loader處理之后,交給extract-text-webpack-plugin處理。
-
【html-webpack-plugin】:自動(dòng)創(chuàng)建html文件,且自動(dòng)引入外部資源。配置項(xiàng)如下:
-
【clean-webpack-plugin】:清空webpack的輸出目錄,防止其他文件“亂入”。
-
【MiniCssExtractPlugin 】:用于提取css為單獨(dú)文件
21. 數(shù)組扁平化算法
如:let arr = [1, [2], [3], [4]]
多維數(shù)組轉(zhuǎn)成一維數(shù)組,遞歸:逐層遍歷數(shù)組,數(shù)組的每個(gè)元素取出,拼接成新數(shù)組
// 數(shù)組扁平化 let arr = [1, [2, [3, [4]]]] // 方法一:使用es6的flat() // console.log(arr.flat(Infinity))// 方法二:使用遞歸 function flat(arr) { let result = [] // 判斷是否傳進(jìn)來是數(shù)組 if (!Array.isArray(arr)) {// 不是數(shù)組,就把數(shù)據(jù)壓入result中result.push(arr) } else {for (let i = 0; i < arr.length; i++) {// console.log(arr[i])// 第一次進(jìn)來這樣寫:result = result.concat(arr[0])// 第二次進(jìn)來,又是一個(gè)數(shù)組,那又得調(diào)用flat(),重新從上往下執(zhí)行函數(shù):result = result.concat(arr[1])result = result.concat(flat(arr[i]))} } return result } console.log(flat(arr))視頻鏈接
22. setTimeout時(shí)間為0_,程序發(fā)生了什么?
// setTimeout(fun, 時(shí)間) setTimeout(() => {console.log(11) }, 0) console.log(22)分析:
- 代碼從上往下執(zhí)行,當(dāng)執(zhí)行到setTimeout的時(shí)候,setTimeout是同步代碼,setTimeout里面的回調(diào)是異步代碼。
- 此時(shí)會(huì)把setTimeout里面的回到函數(shù)放入到計(jì)時(shí)器管理模塊中。
- 同步代碼執(zhí)行完成后,當(dāng)過了0秒(馬上),會(huì)把當(dāng)前的回調(diào)放入到宏隊(duì)列中,如果微隊(duì)列的代碼執(zhí)行完成后,會(huì)執(zhí)行宏隊(duì)列中的代碼,然后依次執(zhí)行宏隊(duì)列中的定時(shí)器回調(diào)。
事件輪詢中有個(gè)重要模塊:郎金杰
- 事件管理模塊
- 定時(shí)器管理模塊。
- dom 時(shí)間管理模塊。
- ajax 管理模塊。
- MutationsObserver 管理模塊。
- 回調(diào)對(duì)列:
- 宏任務(wù):
- setTimeout,setInterval,ajax,dom事件監(jiān)聽等。
- 微任務(wù)
- promise中的.then函數(shù),async/await,mutationsobserver等。
- 宏任務(wù):
23. setTimeout時(shí)間誤差的解決辦法
setTimeout(fun, 1000) 間隔1000毫秒執(zhí)行
代碼的執(zhí)行:
同步代碼執(zhí)行時(shí)間:會(huì)先等待同步代碼執(zhí)行完成,開始執(zhí)行異步代碼。
異步代碼執(zhí)行時(shí)間:在執(zhí)行異步代碼的時(shí)候,會(huì)有等待的時(shí)間,因?yàn)橐惹懊骊?duì)列中的代碼都執(zhí)行完成之后,才會(huì)執(zhí)行這個(gè)setTimeout中的回調(diào)。
響應(yīng)時(shí)間:比如你在美國訪問了京東setTimeout的倒計(jì)時(shí),那么美國看到的京東倒計(jì)時(shí)一定有問題,響應(yīng)過去都得3秒至少,setTimeout沒法1秒就執(zhí)行。
在現(xiàn)實(shí)中setTimeout在執(zhí)行的時(shí)候:等待時(shí)間 + 執(zhí)行時(shí)間 + 響應(yīng)時(shí)間。所以在現(xiàn)實(shí)中執(zhí)行基本是大于1000毫秒的。
統(tǒng)計(jì)誤差時(shí)間:
/* 獲取時(shí)間戳的四種方式let start = new Date().valueOf()let start = new Date().getTime()let start = Date.now()let start = +new Date() */ setInterval(() => {let n = 0while (n++ <= 1000000) {} }, 1000) // 統(tǒng)計(jì)誤差 // 開始時(shí)間 let start = new Date().getTime() // 程序執(zhí)行的秒數(shù) let count = 0 // 間隔時(shí)間 let inits = 1000 let timer = setTimeout(fun, inits)function fun() {count++// 誤差時(shí)間 = 現(xiàn)在的時(shí)間 - (開始時(shí)間 + count * 1000)// 如果 誤差時(shí)間 = 計(jì)算出來的時(shí)間,那就沒有誤差。let errorTime = new Date().getTime() - (start + count * 1000) + 'ms'console.log(errorTime)// 解決思路:誤差時(shí)間累加(當(dāng)誤差達(dá)到1000ms之后,不要count++,而是+2)。 }24. js面向?qū)ο蟮南嚓P(guān)總結(jié)
面向?qū)ο?Object Oriented Programming, OOP),是一種編程思想
es5:
創(chuàng)建對(duì)象:
function 函數(shù)名(){} ==》new 函數(shù)名 ==》得到對(duì)象(類的實(shí)例對(duì)象)
字面量 {}
new Object()
面型對(duì)象的三大特征:
封裝:將對(duì)數(shù)據(jù)的操作細(xì)節(jié)隱藏起來,只暴露對(duì)外的接口。外界調(diào)用不需要(也不可能)知道細(xì)節(jié),就能通過對(duì)外提供的接口來訪問該對(duì)象,同時(shí)也保證了外界無法任意更改對(duì)象內(nèi)部的數(shù)據(jù)
繼承:子類可以繼承父類的屬性和方法
多態(tài):同一個(gè)方法,在子類和父類中都可以定義,只是內(nèi)容不同。
由繼承而產(chǎn)生了相關(guān)的不同的類,對(duì)同一個(gè)方法可以有不同的響應(yīng)。比如 Cat 和 Dog 都繼承自 Animal,但是分別實(shí)現(xiàn)了自己的 eat 方法。此時(shí)針對(duì)某一個(gè)實(shí)例,我們無需了解它是 Cat 還是 Dog,就可以直接調(diào)用 eat 方法,程序會(huì)自動(dòng)判斷出來應(yīng)該如何執(zhí)行 eat
OOP的優(yōu)勢:
**遍歷對(duì)象:**for … in
對(duì)象轉(zhuǎn)化成字符串:
-
{} ==> string 使用 JSON.stringify()
-
string ==> {} 使用 JSON.parse()
繼承:
構(gòu)造函數(shù)繼承(屬性繼承)
/* 屬性繼承:在子類調(diào)用父類函數(shù),用call改變this指向 */function Father(uname, age){this.uname = uname;this.age = age;console.log('Father-this',this); }// var o = new Father('張三豐', 22); // 這里的this是Father // console.log('o', o);// 繼承 function Son(uname, age, score){// Father(uname, age);這樣寫的this指向不同,此時(shí)Father里面的this指向的是window// Father(uname, age);// 如果調(diào)用Father函數(shù),并且能夠把Father里面的this指向兒子的實(shí)例對(duì)象,此時(shí)Father中的this指向的是SonFather.call(this, uname, age);this.score = score; }var obj = new Son('erzi', 19, 66); console.log('obj', obj);原型鏈繼承(方法繼承)
/*原型鏈:Son.prototype -> Father.prototype -> Object.prorotype -> nullES6中的extends關(guān)鍵字實(shí)現(xiàn)繼承,底層仍然用的是原型 */// 方法繼承 -- 就是原型繼承 function Father() {Father.prototype.say = function () {console.log('say方法');} }// 繼承 function Son() { } Son.prototype = new Father(); Son.prototype.eat = function () {console.log('吃飯'); }// 如果繼承下來父類的方法,那么要把父類實(shí)例對(duì)象賦值給子類的原型對(duì)象,指回構(gòu)造函數(shù)本身 Son.prototype.constructor = Son;console.log(Son.prototype); console.log(Father.prototype);var obj = new Son(); obj.say(); obj.eat();組合繼承
/*1. 原型繼承:繼承屬性和方法,屬性值會(huì)重復(fù)2. 借用構(gòu)造函數(shù)繼承:繼承屬性,解決屬性值重復(fù)的問題,但是父類的方法不會(huì)被繼承3. 組合繼承:原型繼承 + 借用構(gòu)造函數(shù)繼承 */function Person(name, age, sex) {this.name = name;this.age = age;this.sex = sex; }; Person.prototype.sayHi = function () {console.log('啊捏哈賽有'); }; function Student(name, age, sex, score) {// 借用構(gòu)造函數(shù)Person.call(this, name, age, sex);this.score = score; }; // 改變?cè)椭赶?--- 實(shí)現(xiàn)繼承 Student.prototype = new Person(); // 不傳值 Student.prototype.eat = function () {console.log('吃東西'); };// 如果繼承下來父類的方法,那么要把父類實(shí)例對(duì)象賦值給子類的原型對(duì)象,指回構(gòu)造函數(shù)本身 Student.prototype.constructor = Student;var stu = new Student('小黑', 20, '男', 100); console.log(stu.name, stu.age, stu.sex, stu.score); stu.sayHi(); stu.eat();var stu2 = new Student('小黑2', 20, '女', 1010); console.log(stu2.name, stu2.age, stu2.sex, stu2.score); stu.sayHi(); stu.eat();// 這樣就做到了屬性和方法都被繼承了設(shè)計(jì)模式:
沿用了java中的設(shè)計(jì)模式,一共有23種。
es6:
用class作為類名稱。主要是js向后臺(tái)語言靠近。
static 定義靜態(tài)屬性
constructor 構(gòu)造函數(shù)
super 父類構(gòu)造函數(shù),super必須寫在子類的屬性前面
extends 繼承關(guān)鍵字
25. 高階函數(shù)
定義:指一個(gè)函數(shù)的參數(shù)是函數(shù)或者返回值是函數(shù),滿足其中一種情況就算是高階函數(shù)。
funA可以接受funB為參數(shù),那么funA就是一個(gè)高階函數(shù)。
// add() 就是一個(gè)高階函數(shù) function add(x, y, fun) {return fun(x) + fun(y) }function fun(x) {return Math.abs(x) }console.log(add(-2, 3, fun))常見的高階函數(shù):map, reduce, filter, sort
還有一個(gè)函數(shù)柯里化的問題:
定義:柯里化是把接收多個(gè)參數(shù)的函數(shù)轉(zhuǎn)換成多個(gè)只接收一個(gè)參數(shù)的函數(shù)。
作用:參數(shù)復(fù)用
function add(a, b) {return a + b; } add(1, 2) // 3 普通做法 一次傳入兩個(gè)參數(shù)// 假設(shè)有一個(gè) curring 函數(shù)可以做到柯里化 function curring(){} curring(1)(2) // 我們通過這樣的方式來接受參數(shù),這樣就實(shí)現(xiàn)了柯里化 function curring(x) {return y => x + y // 返回一個(gè)函數(shù),然后函數(shù)的x+y作為最終的返回值 } curring(1)(2) // => 3參數(shù)復(fù)用:
// 我們平時(shí)的寫法 --- 非參數(shù)復(fù)用的寫法 function myInfo(inf, name, age) {return `${inf}:${name}${age}` } const myInfo1 = myInfo('個(gè)人信息', 'ljc', '19') console.log(myInfo1); // 個(gè)人信息:ljc19 // 函數(shù)柯里化的寫法 --- 參數(shù)復(fù)用的寫法 復(fù)用了inf function myInfoCurry(inf) {return (name, age) => {return `${inf}:${name}${age}`} } let myInfoName = myInfoCurry('個(gè)人信息') const myInfo1 = myInfoName('ljc', '19') const myInfo2 = myInfoName('ljcc','19') console.log(myInfo2); // 個(gè)人信息:ljcc119 console.log(myInfo1); // 個(gè)人信息:ljc19博客地址
26. 瀏覽器引擎Chrome(v8)
v8引擎對(duì)內(nèi)存有限制:
nodejs中對(duì)v8引擎的內(nèi)存限制
- 64位的操作系統(tǒng)是1.4G
- 32位操作系統(tǒng)是0.7G
拿官方的一個(gè)案例為例,官方是以1.5G內(nèi)存來進(jìn)行參考的,1.5G如果要進(jìn)行垃圾回收,大概是時(shí)間是50ms。
如果node要進(jìn)行一些大內(nèi)存對(duì)象的操作,可以使用buffer來緩沖對(duì)象的內(nèi)存。因?yàn)閎uffer不受限制,因?yàn)閎uffer基于的邏輯是c++的,c++的內(nèi)存是不受v8引擎限制的。
v8 如何來劃分內(nèi)存和垃圾回收的?
分代回收機(jī)制,新生代和老生代
| 32位 | 內(nèi)存大小限制是16M | 內(nèi)存大小限制是700M |
| 64位 | 內(nèi)存大小限制是32M | 內(nèi)存大小限制是1.4G |
| 適合 | 周期短的對(duì)象(如:操作某個(gè)DOM對(duì)象)。一般短期對(duì)象較多,占用80%以上 | 周期長的對(duì)象(如:new Vue() , document, window等,它就一直存在) |
| 垃圾回收 | 采用了Scavenge算法進(jìn)行操作的。在算法實(shí)現(xiàn)時(shí)主要采用Cheney算法。Scavenge的缺點(diǎn):可用內(nèi)存只有一半,另一半永遠(yuǎn)是等待的。Scavenge的優(yōu)點(diǎn):只保留活躍的對(duì)象,不活躍的就消滅了。就是部分清空。 | 先用Mark-Sweep(標(biāo)記清除,就是現(xiàn)在不清楚,等下一次進(jìn)行掃描的時(shí)候發(fā)現(xiàn)還在,就會(huì)被清除掉,內(nèi)容清除掉后,會(huì)留下一個(gè)空間),后用Mark-Compact(標(biāo)記整理,就是把標(biāo)記清楚后的空間合并起來。) |
27. 瀏覽器是如何渲染頁面的
cssom: Css Object Model 采用css代碼,并將每個(gè)選擇器呈現(xiàn)為樹狀結(jié)構(gòu),是對(duì)css樣式表的對(duì)象化表示。同時(shí)還提供了api來操作css。
w3c標(biāo)準(zhǔn)中:
cssom 包括兩個(gè)部分
下面是熊鍵的筆記
- 作用:將域名地址解析為 ip 地址
- 過程:
- 讀取 4 個(gè)緩存
- 瀏覽器 DNS 緩存
- 計(jì)算機(jī) DNS 緩存
- 路由器 DNS 緩存
- 網(wǎng)絡(luò)運(yùn)營商 DNS 緩存
- 1 個(gè)遞歸查詢
- 13 個(gè)根域名服務(wù)器
- 讀取 4 個(gè)緩存
-
第一次握手:客戶端發(fā)起,我將要發(fā)送請(qǐng)求了,你準(zhǔn)備一下
-
第二次握手:服務(wù)端發(fā)起,我知道了,準(zhǔn)備好了,放馬過來
-
第三次握手:客戶端發(fā)起,我也知道了,等著
-
為什么要三次握手?
- 目的:確保客戶端和服務(wù)端收、發(fā)能力都是正常的
- 第一次握手:服務(wù)端知道客戶端發(fā)送能力是正常的
- 第二次握手:客戶端知道服務(wù)端發(fā)送和接受能力是正常的
- 第三次握手:服務(wù)端知道客戶端接受能力是正常的
-
客戶端發(fā)送請(qǐng)求給服務(wù)器
-
請(qǐng)求報(bào)文
- 請(qǐng)求首行
- 請(qǐng)求地址
- 請(qǐng)求方式
- 查詢字符串參數(shù)
- 請(qǐng)求頭
- 攜帶 cookie(cookie)
- 攜帶 token(authorization)
- 空行
- 請(qǐng)求主體
- 請(qǐng)求體參數(shù)(POST)
- 請(qǐng)求首行
-
服務(wù)端返回響應(yīng)給客戶端
-
響應(yīng)報(bào)文
- 響應(yīng)首行
- 響應(yīng)狀態(tài)碼
- 1xx
- 2xx
- 3xx
- 4xx
- 5xx
- 響應(yīng)狀態(tài)碼
- 響應(yīng)頭
- set-cookie 設(shè)置 cookie
- 緩存 cache-control
- 空行
- 響應(yīng)主體
- 響應(yīng)數(shù)據(jù)
- 響應(yīng)首行
- 最開始返回 index.html 頁面,瀏覽器解析 html 文件
- 遇到 DOM 標(biāo)記,調(diào)用 HTML 解析器,將元素解析 DOM 樹
- 遇到 css 標(biāo)記,調(diào)用 css 解析器,解析成 CSSOM 樹
- style 不阻塞
- link 阻塞(防止閃屏)
- 遇到 js 標(biāo)記(script 阻塞),調(diào)用 js 引擎,解析 js 代碼
- 可能會(huì)操作 DOM,重新調(diào)用 HTML 解析器,將元素解析 DOM 樹
- 可能會(huì)操作 CSS,重新調(diào)用 css 解析器,解析成 CSSOM 樹
- 這個(gè)過程就會(huì)導(dǎo)致頁面重排重繪
- 將 DOM 樹和 CSSOM 樹組合生成 render 樹
- 布局 layout
- 渲染 render
- 斷開 TCP 連接需要 4 次:客戶端發(fā)送請(qǐng)求斷開兩次,服務(wù)端返回響應(yīng)斷開兩次
- 第一次揮手:客戶端發(fā)起,客戶端數(shù)據(jù)發(fā)送完畢了,準(zhǔn)備斷開了
- 第二次揮手:服務(wù)端發(fā)起,服務(wù)端數(shù)據(jù)接收完畢了,可以斷開了
- 第三次揮手:服務(wù)端發(fā)起,服務(wù)端數(shù)據(jù)發(fā)送完畢了,準(zhǔn)備斷開了
- 第四次揮手: 客戶端發(fā)起,客戶端數(shù)據(jù)接收完畢了,可以斷開了
28. js程序的執(zhí)行順序是怎樣的?
外部js文件先加載還是window.onload先加載?
外部js文件與body的位置有關(guān)
-
如果js是放在body里,是按照body的先后順序進(jìn)行加載的。
-
如果js在body外(一般指head中),是在body加載完畢后,才加載js。
外部js文件不論是在head中還是在body中,都要優(yōu)先于window.onload = function(){}執(zhí)行。如果外部js有定時(shí)器等異步代碼,就會(huì)滯后執(zhí)行。
29. vue-loader的作用
vue-loader的用法:用來解析和轉(zhuǎn)換vue文件,提取出其中的script、style、template,把他們交給對(duì)應(yīng)的loader去處理。
vue-loader的特性:
熱重載:"熱重載"不是當(dāng)你修改文件的時(shí)候簡單重新加載頁面。啟用熱重載后,當(dāng)你修改 .vue 文件時(shí),所有該組件的實(shí)例會(huì)被替換,并且不需要刷新頁面。它甚至保持應(yīng)用程序和被替換組件的當(dāng)前狀態(tài)!當(dāng)你調(diào)整模版或者修改樣式時(shí),這極大的提高了開發(fā)體驗(yàn)。
使用場景:
30. node可以通過哪些方法可以防止程序奔潰
node 速度比較快,node是單線程的,不穩(wěn)定,不適合處理復(fù)雜業(yè)務(wù)。
單線程,產(chǎn)生未處理異常,會(huì)捯飭程序奔潰。
問題:
調(diào)用了req.params
let http = require('http') let server = http.creawteServer(function(req, res){let ok = req.params.ok; // params 是undefined。如果是未定義就會(huì)導(dǎo)致程序奔潰res.writeHead(200,{'content-type': 'text/plain'})res.end('hello world') }).listen(8080, '127.0.0.1')解決方案1:
uncaughtException 來全局捕獲Error,捕獲之后,可以防止node奔潰 process.on(‘uncaughtException’, function(err){打印錯(cuò)誤 })解決方案2:加上try-catch
let http = require('http') let server = http.creawteServer(function(req, res){// let ok = req.params.ok; // 把這個(gè)未定義的代碼拿到外面去try {handler(req, res)} catch(e) {console.log(e)}res.writeHead(200,{'content-type': 'text/plain'})res.end('hello world') }).listen(8080, '127.0.0.1')let handler = function(req, res) {let ok = req.params.ok; // 同樣是未定義,會(huì)報(bào)錯(cuò) }31. http 和 https的區(qū)別
http:
http(Hyper Text Transfer Protocol) 超文本傳輸協(xié)議,用于在瀏覽器和服務(wù)器之間傳遞信息的,http協(xié)議以明文的形式傳輸內(nèi)容的,數(shù)據(jù)是不加密的。不適合傳輸敏感信息。比如:身份證、賬號(hào)、密碼等。
https:
https:(Hyper Text Transfer Protocol over Secure Socket Layer) 即基于SSL的HTTP協(xié)議,簡單地說就是HTTP的安全版。https是在http的基礎(chǔ)上加上了SSL協(xié)議。SSL是依靠證書來驗(yàn)證服務(wù)器的身份的,它對(duì)瀏覽器和服務(wù)器之間通信是加密的。
https協(xié)議是由SSL+ http構(gòu)成的,是可加密的,身份認(rèn)證的網(wǎng)絡(luò)安全,比http更安全。
區(qū)別:
32. XSS攻擊是什么?如何避免?
定義:
XSS攻擊又叫CSS(Cross Site Script)跨站腳本攻擊。惡意攻擊者往web頁面中插入html代碼,用戶請(qǐng)求該頁面,嵌入其中的該代碼將會(huì)被執(zhí)行,從而達(dá)到攻擊用戶的目的。
一般有三種攻擊類型:
解決:
博客地址
33. csrf 攻擊(非胡哥)
CSRF概念:CSRF跨站點(diǎn)請(qǐng)求偽造(Cross—Site Request Forgery),跟XSS攻擊一樣,存在巨大的危害性,你可以這樣來理解:
攻擊者盜用了你的身份,以你的名義發(fā)送惡意請(qǐng)求,對(duì)服務(wù)器來說這個(gè)請(qǐng)求是完全合法的,但是卻完成了攻擊者所期望的一個(gè)操作,比如以你的名義發(fā)送郵件、發(fā)消息,盜取你的賬號(hào),添加系統(tǒng)管理員,甚至于購買商品、虛擬貨幣轉(zhuǎn)賬等。如下:其中Web A為存在CSRF漏洞的網(wǎng)站,Web B為攻擊者構(gòu)建的惡意網(wǎng)站,User C為Web A網(wǎng)站的合法用戶。
解決:
為了防止CSRF攻擊,Token要求不能重復(fù),需要含有時(shí)間戳信息、簽名信息。
如:token = base64(msg)格式化…base64(sha256(“密鎖”, msg))
token產(chǎn)生:
- token解包
- 比對(duì)簽名
- 判斷時(shí)間是否過期
博客地址
34. css hack
條件Hack:用來調(diào)整頁面的兼容性的。css hack 這個(gè)兼容性主要是針對(duì)IE來說的,因?yàn)镮E一開始沒有遵循W3C的標(biāo)準(zhǔn)。
// 條件Hack的寫法 // if條件共包含6種選擇方式:是否、大于、大于或等于、小于、小于或等于、非指定版本 <!--[if <keywords>? IE <version>?]> HTML代碼塊 <![endif]-->兼容性:瀏覽器品牌不同,在解釋css的時(shí)候,解釋方式不一樣,所以樣式不兼容的問題。
注意:盡可能減少對(duì)CSS Hack的使用。Hack有風(fēng)險(xiǎn),使用需謹(jǐn)慎
博客地址
35. src和href的區(qū)別
請(qǐng)求資源類型不同
作用結(jié)果不同
瀏覽器解析方式不同
36. link和@import的區(qū)別?(非胡哥)
37. 胡哥快排
function quickSort(arr) {if (arr.length < 1) {return arr} // 基準(zhǔn)值(得到一個(gè)整數(shù)) --- 使用Math.floor是為了處理除不盡的情況 let provotIndex = Math.floor(arr.length / 2) // 求得基準(zhǔn)值對(duì)應(yīng)的元素 --- 從基準(zhǔn)下標(biāo)開始截取,截取一個(gè) var provot = arr.splice(provotIndex, 1)[0]// 遍歷數(shù)組和基準(zhǔn)數(shù)進(jìn)行對(duì)比 let left = [] let right = [] for (let i = 0; i < arr.length; i++) {if (arr[i] < provot) {left.push(arr[i])} else {right.push(arr[i])} } // console.log(left, right)return quickSort(left).concat([provot], quickSort(right)) } let arr = [2, 3, 4, 5, 3, 2, 1, 5] const result = quickSort(arr) console.log(result)38. 邊界塌陷(外邊距重合)
同時(shí)給兄弟/父子設(shè)置上下邊距,理論上是兩者之和,實(shí)際上只有一半,這種現(xiàn)象叫作邊界塌陷。
如:給box1的margin-bottom: 20px,給box2的margin-top: 20px; 理論上應(yīng)該是40的邊距,實(shí)際上只有20px的邊距。
<head><style>.box1 {width: 100px;height: 100px;border: 1px solid red;margin-bottom: 20px;}.box2 {width: 100px;height: 100px;border: 1px solid green;margin-top: 20px;}</style> </head> <body><div class="box1"></div><div class="box2"></div> </body>注意:
浮動(dòng)元素和定位元素是不會(huì)發(fā)生邊界塌陷的。
這種現(xiàn)象一般發(fā)生在塊級(jí)元素的垂直方向。
解決方案:
-
margin 同為正數(shù)或者同為負(fù)數(shù)的時(shí)候,取的是絕對(duì)值大的數(shù)。
-
如果一正一負(fù)的時(shí)候,求的是和,如給box1的margin-bottom: 20px,給box2的margin-top: -20px; 那么最終邊界值為0。
2022年8月24日10: 17: 30
未完待續(xù)。。。
總結(jié)
- 上一篇: “百度首页人物”首期人物:《士兵突击》许
- 下一篇: Linux下的lds链接脚本二