2018阿里巴巴前端面試總結(jié)(題目+答案)
使用css實(shí)現(xiàn)一個(gè)持續(xù)的動(dòng)畫(huà)效果
12345 |
animation:mymove 5s infinite;@keyframes mymove {from {top:0px;}to {top:200px;}} |
主要考:animation
用法
值 | 描述 |
---|---|
animation-name |
規(guī)定需要綁定到選擇器的 keyframe 名稱(chēng)。 |
animation-duration |
規(guī)定完成動(dòng)畫(huà)所花費(fèi)的時(shí)間,以秒或毫秒計(jì)。 |
animation-timing-function |
規(guī)定動(dòng)畫(huà)的速度曲線。 |
animation-delay |
規(guī)定在動(dòng)畫(huà)開(kāi)始之前的延遲。 |
animation-iteration-count |
規(guī)定動(dòng)畫(huà)應(yīng)該播放的次數(shù)。 |
animation-direction |
規(guī)定是否應(yīng)該輪流反向播放動(dòng)畫(huà)。 |
使用js實(shí)現(xiàn)一個(gè)持續(xù)的動(dòng)畫(huà)效果
最開(kāi)始的思路是用定時(shí)器實(shí)現(xiàn),***沒(méi)有想的太完整,面試官給出的答案是用requestAnimationFrame
。
- 定時(shí)器思路
1234567 |
var e = document.getElementById('e')var flag = true;var left = 0;setInterval(() => { left == 0 ? flag = true : left == 100 ? flag = false : '' flag ? e.style.left = ` ${left++}px` : e.style.left = ` ${left--}px`}, 1000 / 60) |
requestAnimationFrame
由于之前沒(méi)有用過(guò)這個(gè) API
所以是現(xiàn)學(xué)的。
123456789101112131415161718192021222324 |
//兼容性處理window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); };})();var e = document.getElementById("e");var flag = true;var left = 0;function render() { left == 0 ? flag = true : left == 100 ? flag = false : ''; flag ? e.style.left = ` ${left++}px` : e.style.left = ` ${left--}px`;}(function animloop() { render(); requestAnimFrame(animloop);})(); |
不足之處請(qǐng)指正(畢竟是現(xiàn)學(xué)的)順便查了一下優(yōu)勢(shì):
- 瀏覽器可以?xún)?yōu)化并行的動(dòng)畫(huà)動(dòng)作,更合理的重新排列動(dòng)作序列,并把能夠合并的動(dòng)作放在一個(gè)渲染周期內(nèi)完成,從而呈現(xiàn)出更流暢的動(dòng)畫(huà)效果
- 解決毫秒的不精確性
- 避免過(guò)度渲染(渲染頻率太高、
tab
不可見(jiàn)暫停等等)
注:requestAnimFrame
和 定時(shí)器一樣也頭一個(gè)類(lèi)似的清除方法 cancelAnimationFrame
。
右邊寬度固定,左邊自適應(yīng)
***種:
12345678910111213141516171819 |
<style>body{ display: flex;}.left{ background-color: rebeccapurple; height: 200px; flex: 1;}.right{ background-color: red; height: 200px; width: 100px;}</style><body> <div class="left"></div> <div class="right"></div></body> |
第二種
123456789101112131415161718 |
<style> div { height: 200px; } .left { float: right; width: 200px; background-color: rebeccapurple; } .right { margin-right: 200px; background-color: red; }</style><body> <div class="left"></div> <div class="right"></div></body> |
暫時(shí)想到了兩種。
水平垂直居中
***種
123456789101112 |
#container{ position:relative;}#center{ width:100px; height:100px; position:absolute; top:50%; left:50%; transform: translate(-50%,-50%);} |
第二種
123456789101112 |
#container{ position:relative;}#center{ width:100px; height:100px; position:absolute; top:50%; left:50%; margin:-50px 0 0 -50px;} |
第三種
123456789101112 |
#container{ position:relative;}#center{ position:absolute; margin:auto; top:0; bottom:0; left:0; right:0;} |
第四種 flex
12345 |
#container{ display:flex; justify-content:center; align-items: center;} |
四種定位的區(qū)別
static
是默認(rèn)值relative
相對(duì)定位 相對(duì)于自身原有位置進(jìn)行偏移,仍處于標(biāo)準(zhǔn)文檔流中absolute
絕對(duì)定位 相對(duì)于最近的已定位的祖先元素, 有已定位(指position
不是static
的元素)祖先元素, 以最近的祖先元素為參考標(biāo)準(zhǔn)。如果無(wú)已定位祖先元素, 以body
元素為偏移參照基準(zhǔn), 完全脫離了標(biāo)準(zhǔn)文檔流。fixed
固定定位的元素會(huì)相對(duì)于視窗來(lái)定位,這意味著即便頁(yè)面滾動(dòng),它還是會(huì)停留在相同的位置。一個(gè)固定定位元素不會(huì)保留它原本在頁(yè)面應(yīng)有的空隙。
Flex布局用的多嗎?
因?yàn)轫?xiàng)目考慮兼容 IE9
所以直接說(shuō)用的不多
移動(dòng)端適配怎么做的?
使用媒體查詢(xún)做的響應(yīng)式布局,根據(jù)不同屏幕寬度加載不同css
.
let與var的區(qū)別?
let
為 ES6
新添加申明變量的命令,它類(lèi)似于 var
,但是有以下不同:
var
聲明的變量,其作用域?yàn)樵撜Z(yǔ)句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象let
聲明的變量,其作用域?yàn)樵撜Z(yǔ)句所在的代碼塊內(nèi),不存在變量提升let
不允許重復(fù)聲明.
為什么 var 可以重復(fù)聲明?(這個(gè)就不知道了)
當(dāng)我們執(zhí)行代碼時(shí),我們可以簡(jiǎn)單的理解為新變量分配一塊兒內(nèi)存,命名為a
,并賦值為2
,但在運(yùn)行的時(shí)候編譯器與引擎還會(huì)進(jìn)行兩項(xiàng)額外的操作:判斷變量是否已經(jīng)聲明:
-
首先編譯器對(duì)代碼進(jìn)行分析拆解,從左至右遇見(jiàn)
var a
,則編譯器會(huì)詢(xún)問(wèn)作用域是否已經(jīng)存在叫a
的變量了,如果不存在,則招呼作用域聲明一個(gè)新的變量a
,若已經(jīng)存在,則忽略var
繼續(xù)向下編譯,這時(shí)a = 2
被編譯成可執(zhí)行的代碼供引擎使用。 -
引擎遇見(jiàn)
a=2
時(shí)同樣會(huì)詢(xún)問(wèn)在當(dāng)前的作用域下是否有變量a
,若存在,則將a
賦值為2
(由于***步編譯器忽略了重復(fù)聲明的var
,且作用域中已經(jīng)有a
,所以重復(fù)聲明會(huì)發(fā)生值得覆蓋而并不會(huì)報(bào)錯(cuò))。若不存在,則順著作用域鏈向上查找,若最終找到了變量a
則將其賦值2
,若沒(méi)有找到,則招呼作用域聲明一個(gè)變量a
并賦值為2
。
參考鏈接
封裝一個(gè)函數(shù),參數(shù)是定時(shí)器的時(shí)間,.then執(zhí)行回調(diào)函數(shù)。
123 |
function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time));} |
一個(gè)關(guān)于 this 指向的問(wèn)題
差不多應(yīng)該是這樣,記不太清了
123456789101112 |
obj = { name: 'a', getName : function () { console.log(this.name); }}var fn = obj.getNameobj.getName()var fn2 = obj.getName()fn()fn2() |
CommonJS 中的 require/exports 和 ES6 中的 import/export 區(qū)別?
-
CommonJS
模塊的重要特性是加載時(shí)執(zhí)行,即腳本代碼在require
的時(shí)候,就會(huì)全部執(zhí)行。一旦出現(xiàn)某個(gè)模塊被”循環(huán)加載”,就只輸出已經(jīng)執(zhí)行的部分,還未執(zhí)行的部分不會(huì)輸出。 -
ES6
模塊是動(dòng)態(tài)引用,如果使用import
從一個(gè)模塊加載變量,那些變量不會(huì)被緩存,而是成為一個(gè)指向被加載模塊的引用,需要開(kāi)發(fā)者自己保證,真正取值的時(shí)候能夠取到值。 -
import/export
最終都是編譯為require/exports
來(lái)執(zhí)行的。 -
CommonJS
規(guī)范規(guī)定,每個(gè)模塊內(nèi)部,module
變量代表當(dāng)前模塊。這個(gè)變量是一個(gè)對(duì)象,它的exports
屬性(即module.exports
)是對(duì)外的接口。加載某個(gè)模塊,其實(shí)是加載該模塊的module.exports
屬性。 -
export
命令規(guī)定的是對(duì)外的接口,必須與模塊內(nèi)部的變量建立一一對(duì)應(yīng)關(guān)系。
一行代碼實(shí)現(xiàn)數(shù)組去重?
1 |
[...new Set([1,2,3,1,'a',1,'a'])] |
使用addEventListener點(diǎn)擊li彈出內(nèi)容,并且動(dòng)態(tài)添加li之后有效
123456 |
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li></ul> |
這個(gè)題沒(méi)答出來(lái)
123456 |
var ulNode = document.getElementById("ul"); ulNode.addEventListener('click', function (e) { if (e.target && e.target.nodeName.toUpperCase() == "LI") { alert(e.target.innerHTML); } }, false); |
怎么判斷兩個(gè)對(duì)象相等?
1234567891011121314 |
obj={ a:1, b:2}obj2={ a:1, b:2}obj3={ a:1, b:'2'} |
最開(kāi)始的思路是遍歷來(lái)判斷,但是***好像沒(méi)有說(shuō)清楚,查了下,好像可以轉(zhuǎn)換為字符串來(lái)判斷。
12 |
JSON.stringify(obj)==JSON.stringify(obj2);//trueJSON.stringify(obj)==JSON.stringify(obj3);//false |
項(xiàng)目做過(guò)哪些性能優(yōu)化?
- 減少
HTTP
請(qǐng)求數(shù) - 減少
DNS
查詢(xún) - 使用
CDN
- 避免重定向
- 圖片懶加載
- 減少
DOM
元素?cái)?shù)量 - 減少
DOM
操作 - 使用外部
JavaScript
和CSS
- 壓縮
JavaScript
、CSS
、字體、圖片等 - 優(yōu)化
CSS Sprite
- 使用
iconfont
- 字體裁剪
- 多域名分發(fā)劃分內(nèi)容到不同域名
- 盡量減少
iframe
使用 - 避免圖片
src
為空 - 把樣式表放在 中
- 把腳本放在頁(yè)面底部
- 歡迎補(bǔ)充。。。
模塊化開(kāi)發(fā)是怎么做的?
使用命名空間。
有沒(méi)有使用過(guò)webpack?
我說(shuō)Vue項(xiàng)目中使用了,然后就沒(méi)問(wèn)了。
gulp自己寫(xiě)過(guò)任務(wù)嗎?還是都用的模塊?
不知道怎么怎么回答,不都是使用模塊來(lái)寫(xiě)的么,然后就說(shuō)是使用模塊。
Vue router 除了 router-link 怎么實(shí)現(xiàn)跳轉(zhuǎn)?
12 |
router.go(1)router.push('/') |
Vue router 跳轉(zhuǎn)和 location.href 有什么區(qū)別?
router
是 hash
改變
location.href
是頁(yè)面跳轉(zhuǎn),刷新頁(yè)面
Vue 雙向綁定實(shí)現(xiàn)原理?
通過(guò) Object.defineProperty
實(shí)現(xiàn)的
你能實(shí)現(xiàn)一下雙向綁定嗎?
123456789101112131415161718192021 |
<body> <div id="app"> <input type="text" id="txt"> <p id="show-txt"></p> </div> <script> var obj = {} Object.defineProperty(obj, 'txt', { get: function () { return obj }, set: function (newValue) { document.getElementById('txt').value = newValue document.getElementById('show-txt').innerHTML = newValue } }) document.addEventListener('keyup', function (e) { obj.txt = e.target.value })</script></body> |
React 和 Vue 有什么區(qū)別?
Set 和 Map 數(shù)據(jù)結(jié)構(gòu)()
ES6
提供了新的數(shù)據(jù)結(jié)構(gòu)Set
它類(lèi)似于數(shù)組,但是成員的值都是唯一的,沒(méi)有重復(fù)的值。ES6
提供了Map
數(shù)據(jù)結(jié)構(gòu)。它類(lèi)似于對(duì)象,也是鍵值對(duì)的集合,但是“鍵”的范圍不限于字符串,各種類(lèi)型的值(包括對(duì)象)都可以當(dāng)作鍵。也就是說(shuō),Object
結(jié)構(gòu)提供了“字符串—值”的對(duì)應(yīng),Map
結(jié)構(gòu)提供了“值—值”的對(duì)應(yīng),是一種更完善的Hash
結(jié)構(gòu)實(shí)現(xiàn)。
WeakMap 和 Map 的區(qū)別?
-
WeakMap
結(jié)構(gòu)與Map
結(jié)構(gòu)基本類(lèi)似,唯一的區(qū)別是它只接受對(duì)象作為鍵名(null
除外),不接受其他類(lèi)型的值作為鍵名,而且鍵名所指向的對(duì)象,不計(jì)入垃圾回收機(jī)制。 -
WeakMap
***的好處是可以避免內(nèi)存泄漏。一個(gè)僅被WeakMap
作為key
而引用的對(duì)象,會(huì)被垃圾回收器回收掉。 -
WeakMap
擁有和Map
類(lèi)似的set(key, value)
、get(key)、has(key)
、delete(key)
~~ 和clear()
~~方法, 沒(méi)有任何與迭代有關(guān)的屬性和方法。
clear
已經(jīng)廢棄了.
重排和重繪
-
部分渲染樹(shù)(或者整個(gè)渲染樹(shù))需要重新分析并且節(jié)點(diǎn)尺寸需要重新計(jì)算。這被稱(chēng)為重排。注意這里至少會(huì)有一次重排-初始化頁(yè)面布局。
-
由于節(jié)點(diǎn)的幾何屬性發(fā)生改變或者由于樣式發(fā)生改變,例如改變?cè)乇尘吧珪r(shí),屏幕上的部分內(nèi)容需要更新。這樣的更新被稱(chēng)為重繪。
什么情況會(huì)觸發(fā)重排和重繪?
-
添加、刪除、更新
DOM
節(jié)點(diǎn) -
通過(guò)
display: none
隱藏一個(gè)DOM
節(jié)點(diǎn)-觸發(fā)重排和重繪 -
通過(guò)
visibility: hidden
隱藏一個(gè)DOM
節(jié)點(diǎn)-只觸發(fā)重繪,因?yàn)闆](méi)有幾何變化 -
移動(dòng)或者給頁(yè)面中的
DOM
節(jié)點(diǎn)添加動(dòng)畫(huà) -
添加一個(gè)樣式表,調(diào)整樣式屬性
-
用戶(hù)行為,例如調(diào)整窗口大小,改變字號(hào),或者滾動(dòng)。
瀏覽器緩存
瀏覽器緩存分為強(qiáng)緩存和協(xié)商緩存。當(dāng)客戶(hù)端請(qǐng)求某個(gè)資源時(shí),獲取緩存的流程如下:
-
先根據(jù)這個(gè)資源的一些
http header
判斷它是否***強(qiáng)緩存,如果***,則直接從本地獲取緩存資源,不會(huì)發(fā)請(qǐng)求到服務(wù)器; -
當(dāng)強(qiáng)緩存沒(méi)有***時(shí),客戶(hù)端會(huì)發(fā)送請(qǐng)求到服務(wù)器,服務(wù)器通過(guò)另一些
request header
驗(yàn)證這個(gè)資源是否***協(xié)商緩存,稱(chēng)為http
再驗(yàn)證,如果***,服務(wù)器將請(qǐng)求返回,但不返回資源,而是告訴客戶(hù)端直接從緩存中獲取,客戶(hù)端收到返回后就會(huì)從緩存中獲取資源; -
強(qiáng)緩存和協(xié)商緩存共同之處在于,如果***緩存,服務(wù)器都不會(huì)返回資源;
-
區(qū)別是,強(qiáng)緩存不對(duì)發(fā)送請(qǐng)求到服務(wù)器,但協(xié)商緩存會(huì)。
-
當(dāng)協(xié)商緩存也沒(méi)***時(shí),服務(wù)器就會(huì)將資源發(fā)送回客戶(hù)端。
-
當(dāng)
ctrl+f5
強(qiáng)制刷新網(wǎng)頁(yè)時(shí),直接從服務(wù)器加載,跳過(guò)強(qiáng)緩存和協(xié)商緩存; -
當(dāng)
f5
刷新網(wǎng)頁(yè)時(shí),跳過(guò)強(qiáng)緩存,但是會(huì)檢查協(xié)商緩存;
強(qiáng)緩存
-
Expires(該字段是
http1.0
時(shí)的規(guī)范,值為一個(gè)絕對(duì)時(shí)間的GMT
格式的時(shí)間字符串,代表緩存資源的過(guò)期時(shí)間) -
Cache-Control:max-age(該字段是
http1.1
的規(guī)范,強(qiáng)緩存利用其max-age
值來(lái)判斷緩存資源的***生命周期,它的值單位為秒)
協(xié)商緩存
-
Last-Modified(值為資源***更新時(shí)間,隨服務(wù)器response返回)
-
If-Modified-Since(通過(guò)比較兩個(gè)時(shí)間來(lái)判斷資源在兩次請(qǐng)求期間是否有過(guò)修改,如果沒(méi)有修改,則***協(xié)商緩存)
-
ETag(表示資源內(nèi)容的唯一標(biāo)識(shí),隨服務(wù)器response返回)
-
If-None-Match(服務(wù)器通過(guò)比較請(qǐng)求頭部的If-None-Match與當(dāng)前資源的ETag是否一致來(lái)判斷資源是否在兩次請(qǐng)求之間有過(guò)修改,如果沒(méi)有修改,則***協(xié)商緩存)