2017年9月15號百度前端一面
筆試其實做得蠻不好的,收到面試通知有點出乎意料。自覺以自己現(xiàn)在的知識深度和廣度還不足以通過大廠的層層面試,于是抱著學習的心態(tài)去了。個人感覺是一次蠻好的查漏補缺,總共一個小時的時間,基本每個知識點都問到了,從HTML到CSS,從JS到WEB安全和性能優(yōu)化。常考的知識點在這次面試中都有體現(xiàn),也沒有什么偏題怪題。面試官也很和善,問到的知識點我大概30%沒答上吧,基本都會耐心地解釋一下。
好了廢話不多話,整理一下這次面試問到的問題(有些死活也想不起來了),老規(guī)矩的分為JS和CSS+HTML以及其他三大類,順便把答案也附上,也小伙伴們一個參考。
CSS+HTML
-
內(nèi)聯(lián)元素與塊級元素的區(qū)別
塊級元素獨占一行;
內(nèi)聯(lián)元素不換行,內(nèi)聯(lián)元素不能設(shè)置寬高,可以設(shè)置padding,不能設(shè)置margin-top、margin-bottom。
補充:若設(shè)置
display:inline-block
,表現(xiàn)為同行顯示,但可以設(shè)置width、height、padding、margintext-indent
屬性只對塊級元素起作用。 -
常見的內(nèi)聯(lián)元素與塊級元素(這里只寫了我自己日常常用的,若想知道全部的內(nèi)聯(lián)和塊級有些什么的可以自行搜索)
內(nèi)聯(lián)元素:
<span><a><img>
(<img>
內(nèi)聯(lián)塊狀元素,可以設(shè)置寬高)塊級元素:
<div><p><h1-6><ol><ul><pre>
補充: 替換元素是瀏覽器根據(jù)標簽的元素與屬性來判斷具體的內(nèi)容。如
<input>
-
說一下標準盒模型和IE盒模型
當你看到這一行的時候,請按F12,換到element這一欄,就會看到一個四四方方的盒子,中間有一塊數(shù)字X數(shù)字的藍色區(qū)域,這叫content,剩下的區(qū)域在上面都寫上名字了(僅針對Chrome),這就是標準盒模型。
至于什么是IE盒模型,在標準盒模型中,width指的就是content的寬,而IE中,width指的是content+padding+border,即是說IE把content定義為了content+padding+border(其實我覺得這種定義方式還挺利于理解的)。
-
box-sizing:border-box是什么效果
在上一題盒模型的基礎(chǔ)上,border-box就類似于IE的盒模型,如果你設(shè)置了一個width,同時設(shè)置了
box-sizing:border-box
,這時候瀏覽器就會幫你把border和padding計算到width中去。 -
寫一個左邊固定寬度,右邊自適應的兩欄布局
<div id="left"></div> <div id="right"></div>
#left{ float:left; width:200px; } #right { width:100%; margin-right:-200px; }
-
上題的基礎(chǔ)上如何清除浮動
第一種方法答
clear:both
,問clear:both
放在哪,于是畫了一個在左右兩個div之下的div說在這里設(shè)置clear:both
。然后又引申出來,如果用一個div元素將左右的兩個元素包裹起來,可以在容器div中設(shè)置
:after
偽類。CSS如下(其實我一直對偽類有點困惑,照著碼從來沒想過是啥,今天面試官給我一指瞬間就get 了):.container::after { content: " "; clear:both; }
第二種方法
(這題我問面試官,他邊說我邊記,記完我問還有嗎,他愣了一下,然后反問是我面你還是你面我(⊙﹏⊙))
第二種清除浮動的辦法就是下一題的BFC,包裹兩個div的父容器生成一個塊級格式上下文,與外面隔絕開來獨立的一塊,也不管什么浮動不浮動了。具體BFC什么樣寫在下一題。
-
BFC(清除浮動)
Block Formatting Context
BFC大概就是上面說的,一個獨立的塊級上下文,怎么才能形成BFC找了一下標準說法:
- float的值不為none
- overflow的值不為visible
- display的值為inline-block、table-cell、table-caption
- position的值為absolute或fixed
這里的四個條件都是針對父元素即上面設(shè)置的
.container
的,滿足其中一個就可以生成一個BFC,自然也能做到清除浮動了。(這里面試官主要跟我說的是設(shè)置overflow:hidden)
-
垂直margin的合并
垂直margin合并就是上下相鄰的兩個塊級元素,如果剛好,上面設(shè)置
margin-bottom
,下面設(shè)置margin-top
,這倆外邊距相遇了,那兩個就合并了,本來可能上面margin-bottom
設(shè)置20px
,margin-top
設(shè)置10px
,合并之后兩個元素上下的距離就變?yōu)?code>20px,即兩個屬性中較大的值。這里補充的一點就是垂直margin合并的條件時在同一個BFC中才會發(fā)生的,如果兩個BFC就算它倆的margin相遇了,也不會融合的。
-
水平居中,垂直水平居中(position)
水平居中:
margin:0 auto
這里上下的外邊距隨便設(shè)置,不一定是0,左右要自適應即auto
。行內(nèi)元素如何居中:水平
text-align:center
,垂直設(shè)置line-height
與height
一樣高。垂直水平居中就合并一下。垂直水平居中: ①利用flex布局,很簡單的三行代碼,在父容器里設(shè)置。
.container { display:flex; justify-content:center; align-items:center; }
②利用position:這里就不是設(shè)置父容器了,而是元素本身
div{ position:absolute; margin:auto; bottom:0; top:0; left:0; right:0; }
在我說完flex之后,面試官就問利用position怎么做,然后我就說了上下左右都為0,把margin自適應給忘了。
補充:還有利用css3里的
transform
,主要是針對不定寬高(即寬高為百分比的情況),定寬高的話可以用負的margin值來做到,都是差不多的思想。transform實現(xiàn)垂直水平居中:
div{ position: absolute; top: 50%; left: 50%; width:50%;//注意這里的寬高都為百分比 height:30%; transform: translate(-50%, -50%); }
?
-
用過哪些選擇器,選擇器的優(yōu)先級(同樣的這里選擇器列舉的也是我自己用過比較熟悉的)
(這里的分類參考MDN中對選擇器的分類)
簡單選擇器:元素選擇器、類選擇器、ID選擇器、(*)通配選擇器;通配選擇器匹配所有的元素,慎用,對性能有影響。
屬性選擇器:
[attr][attr="val"][attr~="val"]
依次是元素中包含該屬性、元素中包含該屬性且屬性值為val
、元素中包含該屬性且屬性值中包含val
。其他還有|^$
等,含義類似正則。偽類和偽元素: 偽類 前 一個冒號,常用的
:link :visited :hover :active(love hate)
,針對鏈接;以及nth-child nth-of-type
。偽元素前兩個冒號,常用的
::after ::before
(前面清除浮動就是用到了::after
偽元素)組合選擇器和多用選擇器:①A,B:滿足A或B(A和B也行)②A B:B是A的后代節(jié)點③A>B:B是A的直接子節(jié)點④A+B:AB有相同的父結(jié)點,并且B緊跟在A的后面⑤A~B:AB有相同的父節(jié)點,B在A之后,但不一定是緊挨著A(即④是⑤ 的子集)
-
元素和元素的偽類的優(yōu)先級
屬性選擇器,偽類選擇器和class類選擇器優(yōu)先級一樣,偽元素選擇器和元素選擇器一樣
-
HTML5新增了哪些
具體可以看MDN中的介紹:點我
語義化方面:
<header><footer><nav><section><article><section><hgroup><aside>
視頻和音頻:
<audio><video>
圖像方面:
<canvas>、WebGL(通過canvas.getContext('webgl')獲得對象)、<SVG>
數(shù)據(jù)存儲:
sessionStorage、localStorage
-
講一下localStorage和sessionStorage
sessionStorage存儲一個會話中的數(shù)據(jù),會話結(jié)束后數(shù)據(jù)就會被銷毀。
localStorage的數(shù)據(jù)是永久存儲在客戶端的,除非主動刪除,否則不會過期。
一般設(shè)置大小為5M以下。
API:(localStorage和sessionStorage的API都是一樣的,這里以sessionStorage為示例)
sessionStorage.key(0) //0位索引,返回第0位數(shù)據(jù)的鍵值 sessionStorage.getItem("key") //鍵值為key的屬性值 sessionStorage.setItem("key","value") //存儲名為key,值為value sessionStorage.removeItem("key") //刪除鍵值為key的屬性 sessionStorage.clear(); //刪除所有sessionStorage中的屬性
?
JS
-
事件代理的原理
事件冒泡
-
怎么判斷一個數(shù)組
var arr = [1,2,3]; Object.prototype.toString.call(arr);//[object Array] //還可以用instanceof arr instanceof Array; // true
-
原型、原型鏈
原型:原型是一個對象,其他對象可以通過它實現(xiàn)屬性繼承。JS中每個函數(shù)都有一個prototype屬性,它指向了函數(shù)的原型對象。
原型鏈:這里先給ECMA中的定義
Every object created by a constructor has an implicit reference (called the object's prototype) to the value of its constructor's "prototype" property. Furthermore, a prototype may have a non?null implicit reference to its prototype, and so on; this is called the prototype chain.
翻譯過來大概是這么個意思:
每個由構(gòu)造函數(shù)創(chuàng)建的對象都有一個隱式原型,指向構(gòu)造函數(shù)的
prototype
屬性。 此外,這個原型也可能會有一個非空的隱式原型指向它的原型,它的原型再指向一個原型等等等;這就叫做原型鏈。死記硬背肯定要不得。一般我就畫個例子,類似什么person,student之類的,然后再解釋,student的原型是person,person也有一個原型指向上一級的原型,這樣一直向上找到
Object.prototype
,這是原型鏈最后一層了,再往上找Object.prototype.__proto__
的話,就是null
了。這里再補充一下
prototype和__proto__
的區(qū)別。顯示原型(
prototype
):顯示原型實現(xiàn)基于原型的繼承和屬性的共享。隱式原型(
[[prototype]]
):隱式原型是的作用就是構(gòu)成原型鏈,通過隱式原型可以一層層往上查找對象的原型。__proto__
是個不標準的屬性,是瀏覽器為了實現(xiàn)對[[prototype]]
的訪問所提供的一個方法。常理來說[[prototype]]
即隱式原型是不可訪問的。ES5里提供了Object.getPrototypeOf()
這個方法來獲得[[prototype]]
。 -
寫了一個表達式讓我說元素的原型是什么
首先是寫了一個
var dog = new Animal()
,我說是Animal.prototype
;然后是var arr = [1,2,3]
,我說是Array.prototype
;最后是問Object
的原型,Object
是個構(gòu)造函數(shù)嘛,那就是Function.prototype
。 -
閉包
(這里的定義來自于紅寶書)閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。
死記硬背肯定累,我一般都記這段代碼
function outer(){ var x = "我是來自outer的x"; return function inner(){ console.log(x); } } var a = outer(); a(); //我是來自outer的x
反正對我而言代碼比定義印象深刻多了,然后再自己用語言把這段代碼描述一下,基本就能解釋閉包了。
-
作用域、作用域鏈
作用域怎么解釋,這個看了很多地方,都覺得不滿意。還是引用高程里面這段話吧。
執(zhí)行環(huán)境(execution context)定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。
為什么拿出來卻是執(zhí)行環(huán)境,是因為看了一篇文章,感覺里面的說法還蠻有趣的。作用域大致也是這么個意思,但作用域是靜態(tài)的,執(zhí)行環(huán)境是動態(tài)的,也就是說執(zhí)行環(huán)境是你執(zhí)行的時候才確認的,而作用域是定義的時候確認的。
作用域鏈:保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。
這里我個人理解加上看高程里面的說法,感覺就是類似棧的結(jié)構(gòu),全局執(zhí)行環(huán)境在棧底,進入一個函數(shù),一個執(zhí)行環(huán)境就被壓入棧中。在當前這個函數(shù),即棧頂?shù)膱?zhí)行環(huán)境,若是沒找到需要變量,則往下找。
當執(zhí)行完這個函數(shù)后,這個函數(shù)的執(zhí)行環(huán)境就出棧,進入之前的執(zhí)行環(huán)境中,一直到最后棧里只剩下了全局執(zhí)行環(huán)境。
-
變量對象
每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
活動對象(activation object):當函數(shù)被調(diào)用時,活動對象就被激活了。除了包含arguments這個特殊參數(shù)外,還包含了與變量對象一樣的,當前執(zhí)行環(huán)境中的所有變量和函數(shù)等等等。(我個人理解,活動對象就是arguments+被激活的變量對象)。
-
實現(xiàn)
sub/pub(on,off,triger,triger(*,{"name":"Alex"}))
*表示所有(大概知道是怎么個思路但是讓我寫就蒙蔽了,跟面試官說了之后他跟我講說因為以后公司里面寫框架的話基本都會用到觀察者模式,所以了解如何實現(xiàn)還是很有必要的)
大概題目就是一個Emitter的類,其中有
on,off,trigger
三個函數(shù)。on
傳入注冊的事件名和相應的回調(diào)函數(shù);off
傳入事件名刪除對于這個事件的監(jiān)聽;trigger
觸發(fā)事件,參數(shù)為觸發(fā)的事件及傳入回調(diào)函數(shù)中的參數(shù)。//創(chuàng)建一個對象用于保存注冊的事件 var eventObj = {}; Emitter.prototype.on = function(event,fn){ if(!eventObj[event]){ //若不存在這個事件,則在對象中創(chuàng)建一個屬性,值為一個空的數(shù)組 eventObj[event] = []; } //將傳入回調(diào)函數(shù)添加到事件的回調(diào)函數(shù)數(shù)組中 eventObj[event].push(fn); } Emitter.prototypr.off = function(event){ if(!eventObj[event]){ //不存在該事件,直接返回false return false; } //若存在則刪除 delete eventObj[event]; } Emitter.prototype.trigger = function(event,args){ //若傳入星號,則遍歷事件對象中的所有屬性,執(zhí)行對應數(shù)組中的回調(diào)函數(shù) if(event === "*"){ for(events in eventObj){ for(let i = 0;i<events.length;i++){ events[i](args); } } //若傳入是event名,則遍歷執(zhí)行屬性對應數(shù)組中的所有回調(diào)函數(shù) } else if(eventObj[event]){ for(let i = 0;i<eventObj[event].length;i++){ eventObj[event][i](args); } } }
這一段代碼沒測試,只大概寫了下簡單思路,有什么錯誤歡迎指出。至于什么是觀察者模式這里就不贅述了。
-
給一段英文,讓每個單詞的首字母大寫
(這是最后一個問題吧,面試官說那最后做一個小的算法吧,我一聽算法全身毛都豎起來了,結(jié)果沒想到拿出來是這么道題。。。。)
看了一眼就打算說怎么做,結(jié)果面試官說想想再說……嚇的我還以為有什么陷阱。仔細看了兩眼,就很普通的一段英文嘛。
然后就說用正則去匹配英文中的空格逗號句號括號等等分隔符,然后
split
成數(shù)組,遍歷數(shù)組,對每個元素的首字母都toUpperCase
。面試官點點頭,然后我又問還有什么更有效率的辦法嗎(
怎么好像真的我在面他),他說也可以不用split
,直接正則匹配每個單詞然后替換首字母。?
其他
-
性能優(yōu)化
這個問題太寬泛了,而且面試中基本都會問到。這次面試回答這個問題的時候我就感覺自己說得不夠有條理,基本是在腦袋里抓到什么說什么,這樣純靠記憶力去說,也容易說不完整。(當然性能優(yōu)化想說全面說詳細那恐怕一個小時都不夠面的了)
在這個面經(jīng)里就不詳細說了,要找文章的話網(wǎng)上一大堆。打算等校招季閑下來一點后再慢慢按自己思路整理一篇文章出來。
-
Web安全了解哪些
這里我就說了兩個,XSS(Cross Site Scripting)和CRSF(Cross Site Request Forgery)。
是什么:XSS是跨站腳本攻擊,在所有可輸入的地方,沒有對輸入數(shù)據(jù)進行處理的話,都會存在XSS漏洞;CRSF是跨站請求偽造,攻擊者盜用用戶身份,發(fā)送惡意請求。
如何防范:
XSS:對輸入進行轉(zhuǎn)義,例如
<>
轉(zhuǎn)換為HTML字符實體< >
CRSF:增加驗證流程(驗證碼,指紋驗證等)。
-
用過什么構(gòu)建工具,介紹一下
Webpack:把你的項目當做一個整體,通過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到你的項目的所有依賴文件,使用loaders處理它們,最后打包為一個(或多個)瀏覽器可識別的JavaScript文件。
這里我認為webpack的關(guān)鍵字就是壓縮和打包。接下來的就看自己實際應用中用到了什么就再具體說一說。