Create by jsliang on 2019-2-11 15:30:34
Recently revised in 2019-3-17 21:30:36
Hello 小伙伴們,如果覺得本文還不錯,記得給個 star , 小伙伴們的 star 是我持續(xù)更新的動力!GitHub 地址
并不是只有特定的季節(jié)才能跑路,只因為人跑得多了,這條路就定下來了。
金三銀四跳槽季,jsliang 于 2019年2月11日 寫下了這篇文章,開始準(zhǔn)備自己的面試之旅。
至 2019年3月17日 為止,jsliang 搭建出個人的面試知識體系,海量地翻閱了一些前輩留下的資料,結(jié)合個人需求進行了幾場面試,從而進一步完善該文章并進行了發(fā)表,希望對準(zhǔn)備跳槽或者正在跳槽中的小伙伴有所幫助。
不折騰的前端,和咸魚有什么區(qū)別
請時刻準(zhǔn)備好自己的簡歷,不管是互聯(lián)網(wǎng)經(jīng)濟不佳面臨裁員,還是因為公司內(nèi)部斗爭嚴(yán)重心亂如麻,還是因為厭倦了目前的一切……只有隨時更新自己,把自己的簡歷準(zhǔn)備好,你才知道哪一刻跑路是最佳選擇。
Hello 小伙伴們好,我叫梁峻榮,網(wǎng)名叫 jsliang,由于崇拜前端大佬 技術(shù)胖(jspang)的原因,又因為自己學(xué)的是前端(JavaScript),所以給自己取了個 jsliang(JavaScriptLiang) 的網(wǎng)名,希望自己能通過建立自己的前端知識體系,從而在前端路上走得更遠。并將自己的經(jīng)驗分享給小伙伴,攜手小伙伴們一起前行。
下面是講講個人故事:
首先,jsliang 高考后的暑期就聽大學(xué)師兄的建議,開始學(xué)習(xí)編程,那時候?qū)W習(xí)了 C 語言,覺得世界上最神奇的事情不過如此,敲兩下鍵盤,按下回車,電腦就會一閃一閃地響應(yīng)我們!于是在大學(xué)的時候,陸陸續(xù)續(xù)學(xué)過 C、C#、.Net 等……。
-_-|| 由于學(xué)得都是基礎(chǔ),又都還給老師了,在這里就不多累述了。
然后,在大二就開始接觸 HTML,那時候選修了個《網(wǎng)頁設(shè)計基礎(chǔ)》,跟著老師做了個只有幾個頁面的靜態(tài)網(wǎng)站。在大三的時候,參加了學(xué)校的特訓(xùn)班,分角色按流程從頭到尾做了個包含角色管理、購物等功能的網(wǎng)站。同時,由于在特訓(xùn)班的時候,看到后端使用 ThinkPHP(簡稱 TP),覺得蠻不錯的,于是自己搗鼓,使用 TP 3.2.3 + Bootstrap 3 + MySQL 打造了自己的博客(已下線)。
接著,由于選修了門 Node.js 的課,所以也跟著大佬的步伐接觸了下 Vue、Koa 這些,那時候?qū)?npm 等諸多不懂,為了折騰這個,我的前端世界自此打開了個大門。
最后,我在自己的畢業(yè)設(shè)計中使用 Node.js + Vue + ElementUI + MongoDB 打造了個校園外賣、快遞代拿等功能的社區(qū)單頁應(yīng)用。
在 2018 年 5 月的時候,家里催促,于是直接出來面試。不像其他大佬的畢業(yè)等于失業(yè),很幸運地 jsliang 面試第一家就給了 offer,于是就進了這家公司,那時候感覺自己前面的大學(xué)生活白過了,只懂 ES5、jQuery、HTML/HTML5、CSS/CSS3 的皮毛。
在熟悉了三個月的業(yè)務(wù),公司給的任務(wù)能順利完成后,我覺得自己不夠努力:外面的前端翻天覆地,我的技術(shù)卻只是 jQuery is all!
于是 2018 年 8 月,jsliang 開始寫 Markdown,將 5 月份到 8 月份記錄到 Word 文檔上的筆記整理成了 jsliang 的文檔庫,并在 jsliang 的掘金 上發(fā)表了第一篇文章。
18 年 8 月至今,jsliang 大致經(jīng)歷了以下這些:
以上,就是 jsliang 的編程生涯。
今兒,在這里寫寫 jsliang 為了跳槽,根據(jù)個人想法進行的一些前端面試資料整理,小伙伴們覺得不錯的點個贊或者去 GitHub 點個 star,覺得有誤請指出,謝謝~
馬老板曾經(jīng)說過,跳槽有兩個原因:
首先,如果非要給 jsliang 我自己的跳槽定個位,那肯定是錢沒給到位,勞動與產(chǎn)出不成正比。在我 2018 年 5 月入職前,與人事的交談中了解到每年的 8 月和 2 月可以提薪,當(dāng)初的技術(shù)棧是:HTML、CSS、ES5。
然后,2018 年 6 月到 2019 年 1 月,學(xué)習(xí)并應(yīng)用到工作中的技術(shù)有:
其中 2018 年 8 月剛轉(zhuǎn)正,也不敢說自己技術(shù)進步很大,也不敢說自己項目貢獻很大,為公司謀了多大利益,所以沒有提薪想法。
2019 年 1 月底感覺自己項目也做了,凌晨 4/5/6 點的體育西路也看過了,技術(shù)也提升了,于是跟人事交談,期望 2 月能加薪,人事表示年終述職演講得好的給提薪,2 月開工的時候表示提薪名單沒我份……
你沒看錯,提薪全靠 PPT。PPT 里提高了不給,沒提就是沒有。
當(dāng)初想法很簡單,你隨便加個 5/600 我也滿足了。
最后,jsliang 曾跟項目總監(jiān)私下談話,建議可以發(fā)展一些新產(chǎn)品,這樣公司或許能獲取一些新收入,我也可以進一步挑戰(zhàn)我的技術(shù)。但是,由于我司是個老牌子公司,并且大部分依賴于接手電信項目進行擴張……
enm...所以心也委屈了。
在 2018 的努力下,GitHub 破 600 近 700 star,掘金破 10 萬閱讀量,3000 粉絲:
GitHub 見證:點擊查看
掘金見證:點擊查看
1. 熟悉 HTML/HTML5、CSS/CSS3、ES5/ES6。2. 了解 OOP 概念,并嘗試在工作中使用過 OOP 技巧。3. 對 MVC/MVVM 架構(gòu)有一定了解,如有 Vue/React/Angular 或者 微信小程序開發(fā)經(jīng)驗更佳。4. 使用過 Bootstrap 或者 ElementUI 等 UI 庫,并對前端 UI 庫有一定的個人理解。5. 了解 Git、Webpack 等工具。6. 對 Java、Node.js 等后端編程有一定了解。7. 一年及以上工作經(jīng)驗。復(fù)制代碼
該分析數(shù)據(jù)來自 Boss 直聘
本文的知識點將涉及 HTML、CSS、JS、HTTP、Vue、Webpack、打包工具、性能優(yōu)化等,沒有前置條件,看得懂可以瞅瞅復(fù)習(xí)下,看不懂可以瞅瞅?qū)W習(xí)下。
關(guān)于面試,在這記下慕課網(wǎng)視頻看到的,個人非常認(rèn)同的三個問答:
然后在復(fù)習(xí)面試題的過程中,個人有些小看法:
當(dāng)編寫業(yè)務(wù)代碼中,碰到某個業(yè)務(wù) bug 時,我會習(xí)慣性地百度這個業(yè)務(wù) bug,看看網(wǎng)友是怎么解決的。但是,學(xué)霸級的程序猿,會多走一步,他們會思考產(chǎn)生這個業(yè)務(wù) bug 的底層原因是什么,下次碰到類似的是如何應(yīng)用該技術(shù)解決。所以,日積月累,我的確比不上人家了。
way 1:面試成功,跟自己公司遞辭呈,走流程,同時跟對面 hr 申請一個月后入職。
way 2:面試成功,跟自己公司遞辭呈,詢問能不能快速離職,收到回復(fù)跟對面 hr 確認(rèn)時間?!就扑]】
way 3:先遞辭呈,同時面試,面試成功的,一律申請走完原公司一個月的流程之后的日子入職。
jsliang 于 2 月底拿到 offer 并遞交辭呈,3 月 - 4 月進入一個月倒計時,4 月第一周才能拿到離職證明。
最后在這里祝各位小伙伴能找到稱心如意的工作~
HTML 屬于結(jié)構(gòu)層,負責(zé)描繪出內(nèi)容的結(jié)構(gòu)。
CSS 屬于表示層,負責(zé)如何顯示有關(guān)內(nèi)容。
JavaScript 屬于行為層,負責(zé)內(nèi)容應(yīng)如何對事件做出反應(yīng)。
語義化的含義就是用正確的標(biāo)簽做正確的事情,HTML 語義化就是讓頁面的內(nèi)容結(jié)構(gòu)化,它有如下優(yōu)點:
簡單來說,能用 <header>
、<footer>
等 H5 新標(biāo)簽的就不用 <div class='header'>
,不要使用 <div>
來存放段落等……
HTML5 中新增標(biāo)簽大致有:<header>
、<footer>
、<aside>
、<nav>
、<video>
、<audio>
、<canvas>
等等。
Chrome | Firefox | Safari | IE | Opera | |
---|---|---|---|---|---|
排版引擎 | Blink | Gecko | Webkit | Trident | Blink |
JS 引擎 | V8 | SpiderMonkey | Nitro | Chakra | V8 |
國內(nèi)一些瀏覽器使用較多的是 Webkit 內(nèi)核。
<!--[if IE]><![endif]-->
<!--[if !IE]><![endif]-->
/* 設(shè)置文字不可選取 */* { -moz-user-select: none; /* 火狐 瀏覽器 */ -webkit-user-select: none; /* Webkit 瀏覽器 */ -o-user-select: none; /* Opera 瀏覽器 */ -ms-user-select: none; /* IE10 瀏覽器 */ -khtml-user-select: none; /* 早期瀏覽器 */ user-select: none; /* 默認(rèn) */}復(fù)制代碼
cookies:存儲于瀏覽器端的數(shù)據(jù)??梢栽O(shè)置 cookies 的到期時間,如果不設(shè)置時間,則在瀏覽器關(guān)閉窗口的時候會消失。
session:存儲于服務(wù)器端的數(shù)據(jù)。session 存儲特定用戶會話所需的屬性和配置信息。
cookies 和 session 的區(qū)別在于:
sessionStorage:生命周期存在于標(biāo)簽頁或窗口,用于本地存儲一個會話(session)中的數(shù)據(jù),這些數(shù)據(jù)會隨著窗口或者標(biāo)簽頁的關(guān)閉而被清空。
localStorage:生命周期是永久的,除非用戶主動清除瀏覽器上存儲的 localStorage 信息,否則它將會永久存在。
sessionStorage 和 localStorage 操作方法:setItem
、getItem
以及 removeItem
。
以 localStorage 為例:
localStorage.getItem('name'); // 獲取 name 的值localStorage.setItem('name', 'jsliang'); // 設(shè)置 name 的值為 jslianglocalStorage.removeItem('name'); // 刪除 name 的值復(fù)制代碼
參考 1:《前端分享之cookie的使用及單點登錄》
參考 2:《Cookie、session和localStorage、以及sessionStorage之間的區(qū)別》
HTML 屬于結(jié)構(gòu)層,負責(zé)描繪出內(nèi)容的結(jié)構(gòu)。
CSS 屬于表示層,負責(zé)如何顯示有關(guān)內(nèi)容。
JavaScript 屬于行為層,負責(zé)內(nèi)容應(yīng)如何對事件做出反應(yīng)。
在工作的過程中,會發(fā)現(xiàn)各式各樣的瀏覽器對某個標(biāo)簽有自己獨特的樣式。
但是在前端開發(fā)中,如果不采用統(tǒng)一標(biāo)準(zhǔn),那么會產(chǎn)生千奇百怪的 bug。所以為了減少后期 bug 的出現(xiàn),前端開發(fā)人員會重置一遍 CSS 樣式,盡可能地使開發(fā)的網(wǎng)頁在各個瀏覽器相差不大。
下面是 jsliang 在使用的樣式重置,當(dāng)然如果小伙伴有不同的想法,可以去 百度/必應(yīng)/google 搜索并使用其他版本的樣式重置:
在工作的過程中,也許小伙伴需要 div 塊的總寬度為 100px,然后發(fā)現(xiàn)總是被 margin 撐高,這是因為盒模型定義的問題:
CSS 中有個屬性叫 box-sizing
。
box-sizing: border-boxbox-sizing: content-box復(fù)制代碼
border-box
中,整個 div
的寬、高,包括 margin
、padding
、border
。content-box
中,整個 div
的寬、高,則不包括上面元素。如上圖,如果一個 div
,你的代碼如下:
div { box-sizing: border-box; margin: 10px; width: 100px; height: 100px; padding: 10px;}復(fù)制代碼
那么,你的整個寬高還是 100px
。
但是,如果你的代碼如下:
div { box-sizing: content-box; margin: 10px; width: 100px; height: 100px; padding: 10px;}復(fù)制代碼
那么,你的整個盒子寬高是 120px
。
如果你在設(shè)計頁面中,發(fā)現(xiàn)內(nèi)容區(qū)被撐爆了,那么,請檢查下現(xiàn)在的 border-box
是什么,最好在引用 reset.css
的時候,就對 border-box
進行統(tǒng)一設(shè)置,方便管理。
在 CSS 中,除了我們常用的 px
,還有其他單位小伙伴們可以了解一下:
單位 | 描述 |
---|---|
% | 百分比 |
px | 像素。計算機屏幕上的一個點為 1px 。 |
em | 相對單位。相對于父元素計算,假如某個 p 元素為 font-size: 12px ,在它內(nèi)部有個 span 標(biāo)簽,設(shè)置 font-size: 2em ,那么,這時候的 span 字體大小為:12 * 2 = 24px |
rem | 相對單位。相對于根元素 html 的 font-size ,假如 html 為 font-size: 12px ,那么,在其當(dāng)中的 div 設(shè)置為 font-size: 2rem ,就是當(dāng)中的 div 為 24px 。 |
rpx | 微信小程序相對單位。1rpx = 屏幕寬度 / 750 px。在 750px 的設(shè)計稿上,1rpx = 1px。 |
除此之外還有 pt、ex 等單位,但由于不太好換算,故在此不提。
選擇器是匹配元素的一種模式。
HTML 經(jīng)過解析生成 DOM Tree;而在 CSS 解析完畢后,需要將解析的結(jié)果與 DOM Tree 的內(nèi)容一起進行分析建立一棵 Render Tree,最終用來進行繪圖。
Render Tree 中的元素與 DOM 元素相對應(yīng),但非一一對應(yīng):一個 DOM 元素可能會對應(yīng)多個 renderer,如文本折行后,不同的「行」會成為 render tree 種不同的 renderer。也有的 DOM 元素被 Render Tree 完全無視,比如 display:none 的元素。
在建立 Render Tree 時,瀏覽器就要為每個 DOM Tree 中的元素根據(jù) CSS 的解析結(jié)果來確定生成怎樣的 renderer。對于每個 DOM 元素,必須在所有 Style Rules 中找到符合的 selector 并將對應(yīng)的規(guī)則進行合并。選擇器的「解析」實際是在這里執(zhí)行的,在遍歷 DOM Tree 時,從 Style Rules 中去尋找對應(yīng)的 selector。
在 CSS 的選擇器中,它會按照優(yōu)先級 從右向左解析,因為這樣匹配元素的時候,能盡量少地查找,所以選擇器最好寫地簡潔一點。
*
#ID
.class
p
、a
等……p span
、div a
等……a:hover
等……input[type='text']
等……li:firth-child
、p:nth-child(1)
等……!important -> 行內(nèi)樣式 -> #id -> .class -> 元素和偽元素 -> * -> 繼承 -> 默認(rèn)
<!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <meta name='viewport' content='width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no'> <meta http-equiv='X-UA-Compatible' content='ie=edge'> <title>Two Column Layout</title> <style> .container { display: flex; } .child-one { width: 300px; height: 300px; background: red; } .child-two { width: 100%; height: 300px; background: deepskyblue; } </style></head><body> <div class='container'> <div class='child-one'></div> <div class='child-two'></div> </div></body></html>復(fù)制代碼
<div>
塊而已。當(dāng)然,小伙伴們可能會說:jsliang 你要考慮 flex
的兼容性啊!enm...支持所有最新版本的瀏覽器!請更新你的瀏覽器哦親~避免被寄刀片,附上
float
布局:《css常見布局》
經(jīng)典:CSS3 相關(guān)屬性你了解嗎,說說都有哪些?能說說你工作中常用的一些 CSS3 屬性嗎?
那么,CSS3 新特性都有哪些呢?
為了方便記憶,咱將它們?nèi)拥酵粋€ HTML 文件上,小伙伴拷貝到本地上打開,可以看到一個擁有漸變的小球,做著橫向運動,如果你鼠標(biāo)移動到它上面,它的寬度會放大,并且進行傾斜。
<!DOCTYPE html><html><head><meta charset='utf-8'> <title>CSS3 新特性</title><style> div { width: 100px; height: 100px; border-radius: 50px; background: linear-gradient(red, orange); box-shadow: 10px 10px 5px #888888; position: relative; transition: width 2s; animation: mymove 5s infinite; } div:hover { width:300px; transform: rotate(7deg); } @keyframes mymove { from { left: 0px; } to { left: 200px; } }</style></head><body> <div></div></body></html>復(fù)制代碼
參考 1:《CSS3 圓角》
參考 2:《CSS3 漸變(Gradients)》
參考 3:《CSS3 transition 屬性》
參考 4:《CSS3 transform 屬性》
參考 5:《CSS3 animation(動畫) 屬性》
參考 6:《CSS3 box-shadow 屬性》
參考 7:《個人總結(jié)(css3新特性)》
BFC 就是 塊級格式上下文,它是一個獨立的渲染區(qū)域,讓處于 BFC 內(nèi)部的元素和外部的元素相互隔離,使內(nèi)外元素的定位不會相互影響。
一定的 CSS 聲明可以生成 BFC,瀏覽器對生成的 BFC 有一系列的渲染規(guī)則,利用這些渲染規(guī)則可以達到一定的布局效果。
參考文獻:《我對BFC的理解》
行內(nèi)元素:寬度和高度由內(nèi)容決定,與其他元素共占一行的元素,我們將其叫行內(nèi)元素。例如:<span>
、<i>
、<a>
等……
塊級元素:默認(rèn)寬度由父容器決定,默認(rèn)高度由內(nèi)容決定,獨占一行并且可以設(shè)置寬高的元素,我們將其叫做塊級元素。例如:<p>
、<div>
、<ul>
等……
在日常開發(fā)中,我們經(jīng)常使用 CSS 的 display
屬性來打破兩者的壁壘:display: inline-block
,使它們擁有更多的狀態(tài)。
在引用 CSS 上,分為四種形式:行內(nèi)樣式、內(nèi)嵌式、鏈接式以及導(dǎo)入式,下面介紹這四種模式。
直接對 HTML 的標(biāo)記使用 style 屬性,然后將 CSS 代碼直接寫進去:
<p style='color: #fff; backgournd: deepskyblue;'></p>復(fù)制代碼
將 CSS 寫 <head>
與 </head>
之間,并且用 <style>
和 </style>
標(biāo)記進行聲明:
<head> <style> p { color: #fff; background: deepskyblue; } </style></head>復(fù)制代碼
通過將 <style>
上的 CSS 提起到指定的 CSS 文件上,然后通過 <link>
的方式在 HTML 上鏈接起來。
<head> <link href='reset.css' type='text/css' rel='stylesheet'></head>復(fù)制代碼
<head> <style> @import url(reset.css); </style></head>復(fù)制代碼
在優(yōu)先級上,行內(nèi)樣式 > 鏈接式 > 內(nèi)嵌式 > @import 導(dǎo)入式。
Flex 是 Flexible Box 的縮寫,意為”彈性布局”,用來為盒狀模型提供最大的靈活性。
/* 設(shè)置 Flex 模式 */display: flex;/* 決定元素是橫排還是豎著排,要不要倒序 */flex-direction: column;/* 決定元素換行格式,一行排不下的時候如何排 */flex-wrap: wrap;/* flex-flow = flex-direction + flex-wrap */flex-flow: column wrap;/* 同一排下對齊方式,空格如何隔開各個元素 */justify-content: space-between;/* 同一排下元素如何對齊,頂部對齊、中部對齊還是其他 */align-items: center;/* 多行對齊方式 */align-content: space-between;復(fù)制代碼
HTML
<div class='container'> <div class='child'></div></div>復(fù)制代碼
CSS
.container { margin: 0 auto; width: 300px; height: 200px; background: deepskyblue; display: flex; /* 實現(xiàn)元素水平居中 */ justify-content: center; /* 實現(xiàn)元素垂直居中 */ align-items: center;}.child { width: 100px; height: 100px; background: #fff;}復(fù)制代碼
HTML
<div class='container'> <div class='child'></div></div>復(fù)制代碼
CSS
.container { position: relative; width: 300px; height: 200px; background: pink; margin: 0 auto;}.child { position: absolute; width: 100px; height: 100px; top: 50%; left: 50%; /* 下面兩種方式均可 */ /* margin-top: -50px; margin-left: -50px; */ transform: translate(-50%, -50%); background: #fff;}復(fù)制代碼
水平居中:
display: inline-block; text-align: center;
margin: 0 auto;
display: flex; justify-content: center;
垂直居中:
line-height: height
display: flex; align-items: center;
參考文獻:
① 《CSS實現(xiàn)垂直居中的常用方法》
② 《CSS 用 position: absolute 與 transform 來居中塊級元素的問題》
HTML 屬于結(jié)構(gòu)層,負責(zé)描繪出內(nèi)容的結(jié)構(gòu)。
CSS 屬于表示層,負責(zé)如何顯示有關(guān)內(nèi)容。
JavaScript 屬于行為層,負責(zé)內(nèi)容應(yīng)如何對事件做出反應(yīng)。
<body> <input type='button' onclick='alert('行內(nèi)引入')' value='按鈕'/> <button onclick='alert(123)'>點擊我</button></body>復(fù)制代碼
<script> window.onload = function() { alert('js 內(nèi)部引入!'); }</script>復(fù)制代碼
<body> <div></div> <script type='text/javascript' src='./js/index.js'></script></body>復(fù)制代碼
注意:
<script>
,因為瀏覽器解析順序緣故,如果解析到死循環(huán)之類的 JS 代碼,會卡住頁面。關(guān)于 prototype
、__proto__
、new
、call()
、apply()
、bind()
、this
這些的知識點,由于篇幅太長,jsliang 已經(jīng)抽離了出來,并做了簡潔詳細講解,詳見:
下面放出相關(guān)知識點:
__proto__
屬性(原型)等于其構(gòu)造函數(shù)的 prototype
屬性。在 JS 中,最容易混淆的就是作用域的情況。
在傳統(tǒng)的后端語言(例如 C 語言)中,一對花括號 {}
就是一個塊級作用域,作用域內(nèi)變量不會相互影響,但是在 JS 中,像 if 條件語句的 {}
就不算一個獨立的作用域:
var x = 1;console.log(x); // 1if(true) { var x = 2; console.log(x); // 2}console.log(x); // 2復(fù)制代碼
所以有時候我們就需要變通,通過自執(zhí)行函數(shù)創(chuàng)建臨時作用域:
function foo() { var x = 1; console.log(x); // 1 if(x) { (function(x) { console.log(x); // 1 var x = 2; console.log(x); // 2 })(x) } console.log(x); // 1}foo();復(fù)制代碼
說到創(chuàng)建臨時作用域,我們就不得不談一下閉包。
那么,什么是閉包呢?
閉包簡單定義:函數(shù) A 里面包含了 函數(shù) B,而 函數(shù) B 里面使用了 函數(shù) A 的變量,那么 函數(shù) B 被稱為閉包。
又或者:閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
function A() { var a = 1; function B() { console.log(a); } return B();}復(fù)制代碼
for(var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 1000);}復(fù)制代碼
請問這段代碼輸出什么?
答案:3 個 3。
解析:首先,for
循環(huán)是同步代碼,先執(zhí)行三遍for
,i 變成了 3;然后,再執(zhí)行異步代碼setTimeout
,這時候輸出的 i,只能是 3 個 3 了。
for(let i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 1000);}復(fù)制代碼
在這里,每個 let 和代碼塊結(jié)合起來形成塊級作用域,當(dāng) setTimeout() 打印時,會尋找最近的塊級作用域中的 i,所以依次打印出 0 1 2。
如果這樣講不明白,我們可以執(zhí)行下下面這段代碼:
for(let i = 0; i < 3; i++) { console.log('定時器外部:' + i); setTimeout(function() { console.log(i); }, 1000);}復(fù)制代碼
此時瀏覽器依次輸出的是:
定時器外部:0定時器外部:1定時器外部:2012復(fù)制代碼
即代碼還是先執(zhí)行 for
循環(huán),但是當(dāng) for
結(jié)束執(zhí)行到了 setTimeout
的時候,它會做個標(biāo)記,這樣到了 console.log(i)
中,i 就能找到這個塊中最近的變量定義。
for(let i = 0; i < 3; i++) { (function(i){ setTimeout(function() { console.log(i); }, 1000); })(i)}復(fù)制代碼
以上,我們就講解完了閉包及解決閉包的方式。
觀點 1:有些資料表示閉包中產(chǎn)生的大量局部變量,會造成內(nèi)存消耗過大,從而造成網(wǎng)頁的性能問題。
觀點 2:有些資料表示目前瀏覽器引擎都基于 V8,而 V8 引擎有個 gc 回收機制,不用太過擔(dān)心變量不會被回收。
提示:所以,如果你覺得不夠保險,那就在退出函數(shù)之前,將不使用的局部變量全部刪除。
簡單來說,有兩個對象 A 和 B,B = A,當(dāng)你修改 A 時,B 的值也跟著發(fā)生了變化,這時候就叫淺拷貝。如果不發(fā)生變化,就叫深拷貝。
let a = 1; let b = a; a = 2; console.log(b)
。當(dāng)我們嘗試這樣子寫時,b 在棧內(nèi)存中開辟了一個新內(nèi)存,所以 b 的值不會改變,仍是 1.let a = [1, 2, 3], b = a; a[0] = 3; console.log(b)
。當(dāng)我們嘗試這樣子寫時,b 會偷懶,引用跟 a 同一塊的內(nèi)存地址,從而 a 的修改會影響 b,使得 b 變成 [3, 1, 3]。function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if(obj && typeof obj === 'object') { for(key in obj) { if(obj.hasOwnProperty(key)) { // 判斷 obj 子元素是否為對象,如果是,遞歸復(fù)制 if(obj[key] && typeof obj[key] === 'object') { objClone[key] = deepClone(obj[key]); } else { // 如果不是,簡單復(fù)制 objClone[key] = obj[key]; } } } } return objClone;}let a = [1, 2, 3, 4];let b = deepClone(a);a[0] = 2;console.log(a, b);// Console// a = [2, 2, 3, 4];// b = [1, 2, 3, 4];復(fù)制代碼
注意:采用 JSON 進行的深拷貝,無法拷貝到 undefined、function、symbol 這類數(shù)據(jù),它是有小 bug 的深拷貝。
function deepClone(obj) { let _obj = JSON.stringify(obj); let objClone = JSON.parse(_obj); return objClone}let a = [0, 1, [2, 3], 4];let b = deepClone(a);a[0] = 1;a[2][0] = 1;console.log(a, b);// Console// a = [1, 1, [1, 3], 4];// b = [0, 1, [2, 3], 4];復(fù)制代碼
在前端發(fā)展中,隨著前后端分離,前端社區(qū)的不斷壯大,前端能做的事情越來越多,承受的任務(wù)越來越重,代碼也就越來越長了。就好比 jsliang 個人使用 jQuery 開發(fā)的時候,動不動就上千行代碼,這在一個編輯器上看起來就有點亂了。如果碰上沒有代碼折疊的編輯器,你就更加難受了。
有的小伙伴的編輯器不是 VS Code,也不能進行代碼折疊
所以,面對越來越多的代碼,我們就急需將這些代碼分門別類,將代碼按功能劃分,將同一功能的代碼整合在一起,于是就有了模塊化開發(fā):一個文件就是一個模塊,當(dāng)我們需要某個文件的時候,我們只需要引用這個模塊即可……
首先,是 CommonJS 的提出,在 Node.js 以及 Webpack 都支持 CommonJS,它規(guī)定了一個文件就是一個模塊,文件內(nèi)部定義的變量屬于這個模塊,不會對外暴露從而污染全局變量的規(guī)則。在 CommonJS 中,通過 exports 或者 module.exports 進行導(dǎo)出,通過 require 進行 同步加載 所需要依賴的模塊。由于它是同步加載模塊的形式,所以比較通用于服務(wù)器端。
然后,根據(jù) CommonJS 只能同步加載的問題,AMD 根據(jù)瀏覽器的特性,進行了非同步加載模塊的提出。同時,AMD 有個問題,就是在使用 require.js 的時候,必須提前加載所有模塊。
接著,根據(jù) AMD 的問題,CMD 提出來了:通過按需加載的形式,哪里需要就調(diào)用哪里,而不用等到所有的模塊都加載了再解析。
最后,ECMA 國際推出了 ES6 的 modules。在 ES6 中,通過 export 關(guān)鍵字導(dǎo)出模塊,通過 import 關(guān)鍵字引用代碼。當(dāng)然,由于瀏覽器廠商諸多,ES6 在瀏覽器的尚不支持,目前主流做法是先將 ES6 通過 babel 編譯成 require。
當(dāng)然,JS 都進行模塊化了,jsliang 想起自己項目中的那一坨 CSS,真心沒有回顧的想法!所以我們還需要知道為了方便管理 CSS,大佬們還是有做事兒的:Less 以及 Sass,這兩者使 CSS 的編寫更有組織性和目的性了。
說起模塊化,我們又可以順帶提及組件化了,一開始為了區(qū)分這兩者,jsliang 也是百度了大量文章,最后成功把自己整蒙了,還是說說感覺可以的解釋:
組件化更關(guān)注的是 UI 部分:彈出框、頭部,內(nèi)容區(qū)、按鈕等,都可以編寫成組件,然后在適用的地方進行引用。而模塊化更側(cè)重于功能或者數(shù)據(jù)的封裝,比如全局的 JSON 配置文件,比如通用的驗證方法,比如規(guī)范時間戳等。
所以,說到這里,我們就可以提到前端工程化:將整個開發(fā)流程就行工程規(guī)劃,從而提高整個團隊的開發(fā)效率。
在前端工程化中,最重要的就是提高整個團隊在 編碼 -> 測試 -> 維護 這三個階段的生產(chǎn)效率。團隊的協(xié)調(diào)至關(guān)重要,將每個任務(wù)細分給各個成員,從而獲取極致的工作效率,是管理者最喜歡看到的。而在上面的模塊化和組件化的應(yīng)用,就屬于前端工程化中的一部分,其目的就是在一些復(fù)雜的項目中,方便團隊進行合作開發(fā),提高生產(chǎn)效率。
參考文獻:
① 《到底什么是前端工程化、模塊化、組件化》
② 《【前端工程化系列】簡談前端模塊化開發(fā)與開發(fā)規(guī)范》
③ 《個人關(guān)于模塊化的理解》
④ 《組件化開發(fā)和模塊化開發(fā)概念辨析》
⑤ 《JavaScript模塊化 --- Commonjs、AMD、CMD、es6 modules》
⑥ 《淺談什么是前端工程化》
簡單來說,就是增加代碼的可復(fù)用性,減少咱們的工作,使代碼更加流暢。
function Person(name, phone) { this.name = name; this.phone = phone; this.eat = function() { console.log(name + ' 吃飯'); } return this;}let p1 = new Person('jsliang', '18818881888');console.log(p1.name); // jsliangp1.eat(); // jsliang 吃飯復(fù)制代碼
當(dāng)然,jsliang 只能寫到這里了,再寫下去就是設(shè)計模式等知識點了。
所以希望小伙伴們還是了解下面向?qū)ο笏枷?,有助于進一步提升自己。
關(guān)于 防抖與節(jié)流,jsliang 特意將資料結(jié)合起來:
小伙伴們可以前往 《面試知識點 - JS 防抖與節(jié)流》 查看。
ES6 是個大知識點,如果你面試的公司不是 “飽經(jīng)滄桑” 的那種,那么一定會出點 ES6 問題,例如:
因為 jsliang 感覺自己連 ES6 的門還沒進,所以在這里就不 自作聰明,推薦下阮一峰大佬的教程:
希望小伙伴們看完能有所收獲,并在工作中大量使用。
在 JavaScript 中,用得較多的之一無疑是數(shù)組操作,這里過一遍數(shù)組的一些用法:
map
: 遍歷數(shù)組,返回回調(diào)返回值組成的新數(shù)組forEach
: 無法break,可以用try/catch中throw new Error來停止filter
: 過濾some
: 有一項返回true,則整體為trueevery
: 有一項返回false,則整體為falsejoin
: 通過指定連接符生成字符串push / pop
: 末尾推入和彈出,改變原數(shù)組, 返回推入/彈出項【有誤】unshift / shift
: 頭部推入和彈出,改變原數(shù)組,返回操作項【有誤】sort(fn) / reverse
: 排序與反轉(zhuǎn),改變原數(shù)組concat
: 連接數(shù)組,不影響原數(shù)組, 淺拷貝slice(start, end)
: 返回截斷后的新數(shù)組,不改變原數(shù)組splice(start, number, value...)
: 返回刪除元素組成的數(shù)組,value 為插入項,改變原數(shù)組indexOf / lastIndexOf(value, fromIndex)
: 查找數(shù)組項,返回對應(yīng)的下標(biāo)reduce / reduceRight(fn(prev, cur), defaultPrev)
: 兩兩執(zhí)行,prev 為上次化簡函數(shù)的return值,cur 為當(dāng)前值(從第二項開始)相信小伙伴在工作中耍的已經(jīng)是一套一套的了,或者像 jsliang 一樣只會簡單的使用 push
、map
這幾個,感興趣的小伙伴可以 百度/bing/google 找找一些 奇技淫巧,說不定對工作效率有很大提升~
推薦:
在 MVVM 架構(gòu)下,View 和 Model 之間并沒有直接的聯(lián)系,而是通過 ViewModel 進行交互,Model 和 ViewModel 之間的交互時雙向的,因此 View 數(shù)據(jù)會同步到 Model 中,而 Model 數(shù)據(jù)的變化也會立即反應(yīng)到 View 上。
ViewModel 通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來,而 View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發(fā)者只需要關(guān)注業(yè)務(wù)邏輯,不需要手動操作 DOM,不需要關(guān)注數(shù)據(jù)狀態(tài)的同步問題,復(fù)雜的數(shù)據(jù)狀態(tài)維護完全由 MVVM 來統(tǒng)一管理。
$el
和數(shù)據(jù)對象 data 以及事件還未初始化。在 created 階段,Vue 實例的數(shù)據(jù)對象 data 以及方法的運算有了,$el
還沒有。render
函數(shù)首次被調(diào)用,Vue 實例的 $el 和 data 都初始化了,但還是掛載在虛擬的 DOM 節(jié)點上。在 mounted 階段,Vue 實例掛載到實際的 DOM 操作完成,一般在該過程進行 Ajax 交互。Vue 實例從創(chuàng)建到銷毀的過程,就是生命周期。從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載 DOM -> 渲染、更新 -> 渲染、銷毀等一系列過程,稱之為 Vue 的生命周期。
8 個,創(chuàng)建前/創(chuàng)建后、掛載前/掛載后、更新前/更新后、銷毀前/銷毀后。Vue 生命周期的作用是方便我們通過它的生命周期,在業(yè)務(wù)代碼中更好地操作數(shù)據(jù),實現(xiàn)相關(guān)功能。
會觸發(fā) 4 個生命鉤子:創(chuàng)建前/創(chuàng)建后、掛載前/掛載后
在 beforeMounted
時它執(zhí)行了 render
函數(shù),對 $el 和 data 進行了初始化,但此時還是掛載到虛擬的 DOM 節(jié)點,然后它在 mounted
時就完成了 DOM 渲染,這時候我們一般還進行 Ajax 交互。
Vue 采用 數(shù)據(jù)劫持 結(jié)合 發(fā)布者-訂閱者 模式的方式,通過 Object.defineProperty()
來劫持各個屬性的 setter 以及 getter,在數(shù)據(jù)變動時發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。
dep.notice()
通知時,能調(diào)用自身的 update()
方法,并觸發(fā) Compile 中綁定的回調(diào),則功成身退。js 實現(xiàn)簡單的雙向綁定
<body> <div id='app'> <input type='text' id='txt'> <p id='show'></p> </div> <script> window.onload = function() { let obj = {}; Object.defineProperty(obj, 'txt', { get: function() { return obj; }, set: function(newValue) { document.getElementById('txt').value = newValue; document.getElementById('show').innerHTML = newValue; } }) document.addEventListener('keyup', function(e) { obj.txt = e.target.value; }) } </script></body>復(fù)制代碼
Object.defineProperty 接收三個參數(shù):對象,屬性名,配置對象
這里使用的是 Object.defineProperty,這是 Vue 2.0 進行雙向數(shù)據(jù)綁定的寫法。在 Vue 3.0 中,它使用 Proxy 進行數(shù)據(jù)劫持。
Vue 在 render
中 createElement
的時候,并不是產(chǎn)生真實的 DOM 元素,實際上 createElement
描述為 createNodeDescription
,因為它所包含的信息會告訴 Vue 頁面上需要渲染什么樣的節(jié)點。
因此,我們將這樣的節(jié)點描述為 “虛擬節(jié)點”(Virtual Node),簡稱 VNode?!疤摂M DOM” 是我們對由 Vue 組件樹建立的整個 VNode 樹的稱呼。
作為一枚切圖仔,很榮幸地跟小伙伴說:“其實我也不懂 Virtual DOM!”
但是,總會有些面試場合會提到的,所以這里找了幾篇資料,小伙伴們可以進一步學(xué)習(xí):
其他的就需要小伙伴自己尋找了,如果覺得有不錯的解析 Virtual DOM 的文檔/視頻,小伙伴也可以推薦過來哈~
Vue 中 template 就是先轉(zhuǎn)化成 AST 樹,再得到 render 函數(shù)返回 VNode(Vue 的虛擬 DOM 節(jié)點)。
key 的作用就是在更新組件時判斷兩個節(jié)點是否相同。相同就復(fù)用,不相同就刪除舊的創(chuàng)建新的。
對于 diff 過程來說 key 是起不到提速作用的,詳見:key 的作用
用法:Vue.nextTick( [callback, context] )
參數(shù):
{Function} [callback]
{Object} [context]
說明:在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的 DOM。
案例:
// 修改數(shù)據(jù)vm.msg = 'Hello'// DOM 還沒有更新Vue.nextTick(function () { // DOM 更新了})// 作為一個 Promise 使用 (2.1.0 起新增,詳見接下來的提示)Vue.nextTick().then(function () { // DOM 更新了})復(fù)制代碼
關(guān)于 nextTick 的更多理解,jsliang 就不獻丑了,需要學(xué)習(xí)的小伙伴可以查看:
或者自行查找更優(yōu)秀的資源。
關(guān)于 Vue 中的父子組件通訊,相信經(jīng)常開發(fā) Vue 的小伙伴比 jsliang 知道的多很多。
沒怎么使用 Vue 的小伙伴可以看下下面的文章,并嘗試自己寫一寫:
下面咱講下使用 bus.js 實現(xiàn)非父子組件通訊:
假設(shè)在工作中,有三個 .vue 文件:A.vue、B.vue、C.vue。A.vue 是主頁面,B.vue 和 C.vue 類似于頭部導(dǎo)航條和底部導(dǎo)航欄?,F(xiàn)在,B.vue 點擊會切換路由,C.vue 需要獲取 B.vue 傳遞的信息。
A.vue
<template> <div> <top-nav></top-nav> <div class='container'> <router-view></router-view> </div> <bottom-nav></bottom-nav> </div></template>復(fù)制代碼
bus.js
import Vue from 'vue';// 使用 Event Busconst bus = new Vue();export default bus;復(fù)制代碼
B.vue
<template> <div class='bottom-nav'> <div class='nav-one' @click='goToPage({path: '/HomeIndex', meta:'首頁'})'> <i class='icon-home'></i> <span>首頁</span> </div> </div></template><script> import bus from '../utils/bus' export default { methods: { goToPage(route) { this.$router.push(route.path); bus.$emit('meta', route.meta); } } }</script>復(fù)制代碼
C.vue
<template> <div class='top-nav'> <span class='title'>{{title}}</span> </div></template><script> import bus from '../utils/bus' export default { data() { return { title: '' } }, created() { bus.$on('meta', msg=> { this.title = msg; }) } }</script>復(fù)制代碼
微信小程序,簡稱小程序,英文名 Mini Program,是一種不需要下載安裝即可使用的應(yīng)用,它實現(xiàn)了應(yīng)用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應(yīng)用。
- component —————————————————— 組件文件夾 - navBar —— 底部組件 - navBar.js —— 底部組件的 JS 代碼 - navBar.json —— 底部組件的配置文件 - navBar.wxml —— 底部組件的 HTML 代碼 - navBar.wxss —— 底部組件的 CSS 代碼- pages ————————————————————— 頁面文件夾 - index —— 首頁 - index.js —— 首頁的 JS 代碼 - index.json —— 首頁的配置文件 - index.wxml —— 首頁的 HTML 代碼 - index.wxss —— 首頁的 CSS 代碼- public ————————————————————— 圖片文件夾- utils —————————————————————— 工具文件夾 - api.js —— 控制 API 的文件 - md5.js —— 工具 - MD5 加密文件 - timestamp.js —— 工具 - 時間戳文件- app.json ——————————————————— 設(shè)置全局的基礎(chǔ)數(shù)據(jù)等- app.wxss ——————————————————— 公共樣式,可通過 import 導(dǎo)入更多- project.config.json ———————— 項目配置文件復(fù)制代碼
onLoad()
:頁面加載時觸發(fā)。onShow()
:頁面顯示/切入前臺時觸發(fā)。onReady()
:頁面初次渲染完成時觸發(fā)。onHide()
:頁面隱藏/切入后臺時觸發(fā)。onUnload()
:頁面卸載時觸發(fā)。項目/utils/api.js
// 將請求進行 Promise 封裝const fetch = ({url, data}) => { // 打印接口請求的信息 console.log(`【step 1】API 接口:${url}`); console.log('【step 2】data 傳參:'); console.log(data); // 返回 Promise return new Promise((resolve, reject) => { wx.request({ url: getApp().globalData.api + url, data: data, success: res => { // 成功時的處理 if (res.data.code == 0) { console.log('【step 3】請求成功:'); console.log(res.data); return resolve(res.data); } else { wx.showModal({ title: '請求失敗', content: res.data.message, showCancel: false }); } }, fail: err => { // 失敗時的處理 console.log(err); return reject(err); } }) })}/** * code 換取 openId * @data { * jsCode - wx.login() 返回的 code * } */export const wxLogin = data => { return fetch({ url: 'tbcUser/getWechatOpenId', data: data })}復(fù)制代碼
項目/pages/login/login.js
import { wxLogin,} from '../../utils/api.js'復(fù)制代碼
項目/pages/login/login.js
wxLogin({ jsCode: this.data.code}).then( res => { console.log('【step 4】返回成功處理:'); console.log(res.data); }, err => { console.log('【step 4】返回失敗處理:'); console.log(err); })復(fù)制代碼
onLoad()
中通過 options
獲取 url 上的參數(shù):代碼演示
<navigator url='../index/index?userId={{userId}}'></navigator><!-- 這兩段是分別在 HTML 和 JS 中的代碼 -->onLoad: function(options) { console.log(options.userId);}復(fù)制代碼
wx.setStorageSync('userId', 'jsliang');wx.getStorageSync('userId');復(fù)制代碼
login.wxml
<text bindtap='clickText' data-labelId='{{userId}}'>點擊傳遞數(shù)據(jù)到 JS</text>復(fù)制代碼
login.js
clickText(e) { console.log(e.currentTarget.labelid)}復(fù)制代碼
組件接收數(shù)據(jù):component-tag-name
Component({ properties: { // 這里定義了innerText屬性,屬性值可以在組件使用時指定 innerText: { type: String, value: 'default value', } }})復(fù)制代碼
使用組件的頁面定義 json
{ 'usingComponents': { 'component-tag-name': '../component/component' }}復(fù)制代碼
使用組件的頁面 HTML 代碼
<view> <!-- 以下是對一個自定義組件的引用 --> <component-tag-name inner-text='Some text'></component-tag-name></view>復(fù)制代碼
this.$preload()
預(yù)加載用戶可能點擊的第二個頁面。優(yōu)勢:
劣勢:
微信小程序有著低開發(fā)成本、低獲客成本、無需下載的優(yōu)勢。
微信小程序看似就是閹割版的 Vue。
關(guān)于 瀏覽器解析 URL,jsliang 特意將資料結(jié)合起來:
小伙伴們可以前往 《面試知識點 - JS 防抖與節(jié)流》 查看。
關(guān)于 重繪與回流,jsliang 特意將資料結(jié)合起來:
小伙伴們可以前往 《面試知識點 - JS 防抖與節(jié)流》 查看。
V8 將內(nèi)存分為兩類:新生代內(nèi)存空間和老生代內(nèi)存空間。
這兩者通過不同的算法,對內(nèi)存進行管理操作。
意外的全局變量:無法被回收。
定時器:未被正確關(guān)閉,導(dǎo)致所引用的外部變量無法被釋放。
事件監(jiān)聽:沒有正確銷毀(低版本瀏覽器可能出現(xiàn))。
閉包:會導(dǎo)致父級中的變量無法被釋放。
DOM 引用:DOM 被刪除時,內(nèi)存中的引用未被正確清空。
如何查看內(nèi)存變化情況?
使用 Chrome 的 Timeline(新版本 Performance)進行內(nèi)存標(biāo)記,可視化查看內(nèi)存的變化情況,找出異常點。
目前網(wǎng)絡(luò)分層可分為兩種:OSI 模型和 TCP/IP 模型。
更多詳情可以查看下面這篇文章,里面講得非常詳細:
首先,我們大致區(qū)分下狀態(tài)碼:
然后,常見的狀態(tài)碼:
最后,小伙伴們?nèi)绻胍私飧啵€是需要自行查找資料的。
關(guān)于 TCP 三次握手與四次揮手,jsliang 特意將資料結(jié)合起來:
小伙伴們可以前往 《面試知識點 - JS 防抖與節(jié)流》 查看。
通過優(yōu)化從而提高頁面的加載速度。
.c {}
而不是 .a .b .c {}
。padding-left: 10px
而不是 padding: 0 0 0 10px
。.a .b * {}
這樣的選擇器,根據(jù)從右到左的解析順序在解析過程中遇到通配符 * {}
會遍歷整個 DOM,性能大大損耗。float
在渲染時計算量比較大,可以使用 flex 布局。<script>
標(biāo)簽放在 body
之后,避免 JS 的執(zhí)行卡住 DOM 的渲染,最大程度保證頁面盡快地展示出來。display: none
來隱藏,按需顯示。在算法這塊,jsliang 覺得自己還是比較薄弱的,如果小伙伴們跟 jsliang 一樣,也想豐富下這方面知識,歡迎一起刷 LeetCode 共同進步:
在 【其他】 這章,原本 jsliang 想談?wù)劽嬖囍械囊恍┬〖记?,例如談薪;或者講講 HR 面需要詢問的問題,例如工作時長、加班機制、調(diào)薪機制等……
但是,最終看來,jsliang 的經(jīng)歷還是有所欠缺,所經(jīng)歷的面試不夠 “盛大”,所以說出的話可能就是 “胡言亂語”、“誤導(dǎo)觀眾”,故在此就不獻丑了,如果小伙伴們想知道更多,可以通過 QQ 群:798961601
找到我。
☆ 目前 jsliang 通過 3 天的請假,去了 5 場面試,收獲了 3 份 offer。
☆ 如果小伙伴不知道簡歷該怎么寫、面試總是鎮(zhèn)靜不下來、總感覺面試沒譜,可以先找 jsliang 聊聊,我會講講個人的面試經(jīng)歷,以及聽到的其他小伙伴的經(jīng)歷~
在觀看這篇文章的過程中,小伙伴可能會有這些疑問:
回答:
系列套餐你值得擁有!
回答:
每個人的學(xué)習(xí)經(jīng)歷是不同的,所擁有的技術(shù)、知識點以及工作經(jīng)驗等都是不同的。
所以 jsliang 的目的是通過這篇文章充實自己的同時,順帶挖掘自己的不足,例如面向?qū)ο笤燧喿?、算法問題等讓 jsliang 想進一步折騰,并應(yīng)用到工作中。
因此,小伙伴應(yīng)該根據(jù)自己實際去擴展補充屬于自己的知識點。
畢竟了解自己的,只有自己!
回答:
每個人的目的都是不同的,不可能一篇文章寫完所有知識點,同時有些知識點可能 jsliang 也不感興趣、或者 jsliang 的層次不夠,接觸不到。
并且每個面試官都可能有自己的一套面試題,如果 jsliang 能將所有的面試題都寫出來,那還需要面試官做啥,大家都像考國家證書一樣直接電腦考試吧~(我也期待?。。。?/p>
如果小伙伴對文章存有疑問,想快速得到回復(fù)。
或者小伙伴對 jsliang 個人的前端文檔庫感興趣,也想將自己的前端知識整理出來。
或者小伙伴對文章后續(xù)的更新感興趣,掌握更多的面試技巧。
歡迎加 QQ 群一起探討:798961601
。
本文中的許多內(nèi)容,也許小伙伴看了會覺得眼熟,因為它們大部分是 jsliang 參考大量文獻,再經(jīng)過刷選整理,最后根據(jù)自己理解后的一些闡述。
下面是個人覺得非常優(yōu)秀的文章。
查看了下掘金評論區(qū),感謝各位大大的反饋,由于本人將于 2019年4月1日 入職,故將一些個人覺得不錯的自己沒有察覺的知識點記錄下來,區(qū)分于原文,更為了猴年馬月后的下一次跳槽進一步完善。
意思就是,jsliang 這貨懶得改原文了,小伙伴們看著這里進行知識點補充
函數(shù) A 里面包含了 函數(shù) B,而 函數(shù) B 里面使用了 函數(shù) A 的變量,函數(shù) B 被 return 了出去,那么 函數(shù) B 被稱為閉包。
box-sizing
屬性:當(dāng)值為 border-box
時,寬度 width = content + padding + border
,包含內(nèi)邊距與邊框。
當(dāng)值為 content-box
時,寬度 width = content
,不包含內(nèi)邊距與邊框。
em
是一個相對的大小,這里的相對于元素父元素的 font-size
。
Side Project 對應(yīng)的中文就是副業(yè)、業(yè)余項目或者小項目。
感興趣的小伙伴可以去了解一下。
push
與 shift
系列:這里原文已備注是有誤的,只是一時沒空,沒有修改。
原文:!important -> 行內(nèi)樣式 -> #id -> .class -> 元素和偽元素 -> * -> 繼承 -> 默認(rèn)
網(wǎng)友:“應(yīng)該是最后的優(yōu)先級最高?!?/p>
這里最后的優(yōu)先級最高應(yīng)該是指同等級優(yōu)先級覆蓋。瀏覽器通過 CSSParser 將 CSS 解析成 CSS Rule Tree 的時候,沒錯的話應(yīng)該是按照原文中的排序先加載,然后同等級的時候,后面的屬性覆蓋前面的屬性。
對于 HTML5 的語義化,ARIA 的意思是 Accessible Rich Internet Application,aria-*
的作用就是描述這個 Tag 在可視化的情境中的具體信息。例如:
aria-label
:為組件指定內(nèi)置的文本標(biāo)簽,用來替代開發(fā)者沒有使用 <label>
標(biāo)簽aria-labelledby
:會讀取與此具有相同的 id
名的值詳情可參考張鑫旭的 《WAI-ARIA無障礙網(wǎng)頁應(yīng)用屬性完全展示》
文章描述不夠詳細。
child-tow
中設(shè)置 width: 100%
的時候 child-one
的寬度會隨機而變,設(shè)置 flex: 1
就不會。所以看個人需求進行設(shè)置。float
進行相關(guān)的布局。可參考文章:《深拷貝的終極探索(90%的人不知道)》
Promise
與 async
/await
:文章描述不夠詳細。
本來打算寫的,后面沒時間,給我刪了這塊,評論區(qū)有篇文獻參考:
以上,即為目前評論區(qū)的補充,感謝各位小伙伴的點贊支持。
jsliang 廣告推送:
也許小伙伴想了解下云服務(wù)器
或者小伙伴想買一臺云服務(wù)器
或者小伙伴需要續(xù)費云服務(wù)器
歡迎點擊 云服務(wù)器推廣 查看!
jsliang 的文檔庫 由 梁峻榮 采用 知識共享 署名-非商業(yè)性使用-相同方式共享 4.0 國際 許可協(xié)議進行許可。
基于github.com/LiangJunron…上的作品創(chuàng)作。
本許可協(xié)議授權(quán)之外的使用權(quán)限可以從 creativecommons.org/licenses/by… 處獲得。