前段時間去阿里面試的一次經歷,分享給大家吧!
腦子混了記得不多了,記得多少就記錄多少吧。。。。
使用css實現一個持續的動畫效果
animation:mymove 5s infinite;
@keyframes mymove {
from {top:0px;}
to {top:200px;}
}
複製程式碼
主要考:animation
用法
值 | 描述 |
---|---|
animation-name |
規定需要繫結到選擇器的 keyframe 名稱。 |
animation-duration |
規定完成動畫所花費的時間,以秒或毫秒計。 |
animation-timing-function |
規定動畫的速度曲線。 |
animation-delay |
規定在動畫開始之前的延遲。 |
animation-iteration-count |
規定動畫應該播放的次數。 |
animation-direction |
規定是否應該輪流反向播放動畫。 |
使用js實現一個持續的動畫效果
最開始的思路是用定時器實現,最後沒有想的太完整,面試官給出的答案是用requestAnimationFrame
。
- 定時器思路
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
由於之前沒有用過這個API
所以是現學的。
//相容性處理
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);
})();
複製程式碼
不足之處請指正(畢竟是現學的)順便查了一下優勢:
- 瀏覽器可以優化並行的動畫動作,更合理的重新排列動作序列,並把能夠合併的動作放在一個渲染週期內完成,從而呈現出更流暢的動畫效果
- 解決毫秒的不精確性
- 避免過度渲染(渲染頻率太高、
tab
不可見暫停等等) 注:requestAnimFrame
和 定時器一樣也頭一個類似的清除方法cancelAnimationFrame
。
右邊寬度固定,左邊自適應
第一種:
<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>
複製程式碼
第二種
<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>
複製程式碼
暫時想到了兩種。
水平垂直居中
第一種
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
複製程式碼
第二種
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin:-50px 0 0 -50px;
}
複製程式碼
第三種
#container{
position:relative;
}
#center{
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;
}
複製程式碼
第四種 flex
#container{
display:flex;
justify-content:center;
align-items: center;
}
複製程式碼
四種定位的區別
static
是預設值relative
相對定位 相對於自身原有位置進行偏移,仍處於標準文件流中absolute
絕對定位 相對於最近的已定位的祖先元素, 有已定位(指position
不是static
的元素)祖先元素, 以最近的祖先元素為參考標準。如果無已定位祖先元素, 以body
元素為偏移參照基準, 完全脫離了標準文件流。fixed
固定定位的元素會相對於視窗來定位,這意味著即便頁面滾動,它還是會停留在相同的位置。一個固定定位元素不會保留它原本在頁面應有的空隙。
Flex佈局用的多嗎?
因為專案考慮相容 IE9
所以直接說用的不多
移動端適配怎麼做的?
使用媒體查詢做的響應式佈局,根據不同螢幕寬度載入不同css
.
let與var的區別?
let
為 ES6
新新增申明變數的命令,它類似於 var
,但是有以下不同:
var
宣告的變數,其作用域為該語句所在的函式內,且存在變數提升現象let
宣告的變數,其作用域為該語句所在的程式碼塊內,不存在變數提升let
不允許重複宣告.
為什麼 var 可以重複宣告?(這個就不知道了)
當我們執行程式碼時,我們可以簡單的理解為新變數分配一塊兒記憶體,命名為a
,並賦值為2
,但在執行的時候編譯器與引擎還會進行兩項額外的操作:判斷變數是否已經宣告:
- 首先編譯器對程式碼進行分析拆解,從左至右遇見
var a
,則編譯器會詢問作用域是否已經存在叫a
的變數了,如果不存在,則招呼作用域宣告一個新的變數a
,若已經存在,則忽略var
繼續向下編譯,這時a = 2
被編譯成可執行的程式碼供引擎使用。 - 引擎遇見
a=2
時同樣會詢問在當前的作用域下是否有變數a
,若存在,則將a
賦值為2
(由於第一步編譯器忽略了重複宣告的var
,且作用域中已經有a
,所以重複宣告會發生值得覆蓋而並不會報錯)。若不存在,則順著作用域鏈向上查詢,若最終找到了變數a
則將其賦值2
,若沒有找到,則招呼作用域宣告一個變數a
並賦值為2
。 參考連結
封裝一個函式,引數是定時器的時間,.then執行回撥函式。
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
複製程式碼
一個關於 this 指向的問題
差不多應該是這樣,記不太清了
obj = {
name: 'a',
getName : function () {
console.log(this.name);
}
}
var fn = obj.getName
obj.getName()
var fn2 = obj.getName()
fn()
fn2()
複製程式碼
CommonJS 中的 require/exports 和 ES6 中的 import/export 區別?
CommonJS
模組的重要特性是載入時執行,即指令碼程式碼在require
的時候,就會全部執行。一旦出現某個模組被”迴圈載入”,就只輸出已經執行的部分,還未執行的部分不會輸出。ES6
模組是動態引用,如果使用import
從一個模組載入變數,那些變數不會被快取,而是成為一個指向被載入模組的引用,需要開發者自己保證,真正取值的時候能夠取到值。import/export
最終都是編譯為require/exports
來執行的。CommonJS
規範規定,每個模組內部,module
變數代表當前模組。這個變數是一個物件,它的exports
屬性(即module.exports
)是對外的介面。載入某個模組,其實是載入該模組的module.exports
屬性。export
命令規定的是對外的介面,必須與模組內部的變數建立一一對應關係。
一行程式碼實現陣列去重?
[...new Set([1,2,3,1,'a',1,'a'])]
複製程式碼
使用addEventListener點選li彈出內容,並且動態新增li之後有效
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
複製程式碼
這個題沒答出來??
var ulNode = document.getElementById("ul");
ulNode.addEventListener('click', function (e) {
if (e.target && e.target.nodeName.toUpperCase() == "LI") {
alert(e.target.innerHTML);
}
}, false);
複製程式碼
怎麼判斷兩個物件相等?
obj={
a:1,
b:2
}
obj2={
a:1,
b:2
}
obj3={
a:1,
b:'2'
}
複製程式碼
最開始的思路是遍歷來判斷,但是最後好像沒有說清楚,查了下,好像可以轉換為字串來判斷。
JSON.stringify(obj)==JSON.stringify(obj2);//true
JSON.stringify(obj)==JSON.stringify(obj3);//false
複製程式碼
專案做過哪些效能優化?
- 減少
HTTP
請求數 - 減少
DNS
查詢 - 使用
CDN
- 避免重定向
- 圖片懶載入
- 減少
DOM
元素數量 - 減少
DOM
操作 - 使用外部
JavaScript
和CSS
- 壓縮
JavaScript
、CSS
、字型、圖片等 - 優化
CSS Sprite
- 使用
iconfont
- 字型裁剪
- 多域名分發劃分內容到不同域名
- 儘量減少
iframe
使用 - 避免圖片
src
為空 - 把樣式表放在 中
- 把指令碼放在頁面底部 歡迎補充。。。
模組化開發是怎麼做的?
使用名稱空間。
有沒有使用過webpack?
我說Vue專案中使用了,然後就沒問了。
gulp自己寫過任務嗎?還是都用的模組?
不知道怎麼怎麼回答,不都是使用模組來寫的麼,然後就說是使用模組。
Vue router 除了 router-link 怎麼實現跳轉?
router.go(1)
router.push('/')
複製程式碼
Vue router 跳轉和 location.href 有什麼區別?
router
是 hash
改變
location.href
是頁面跳轉,重新整理頁面
Vue 雙向繫結實現原理?
通過 Object.defineProperty
實現的
你能實現一下雙向繫結嗎???
<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 有什麼區別?
Set 和 Map 資料結構(??)
ES6
提供了新的資料結構Set
它類似於陣列,但是成員的值都是唯一的,沒有重複的值。ES6
提供了Map
資料結構。它類似於物件,也是鍵值對的集合,但是“鍵”的範圍不限於字串,各種型別的值(包括物件)都可以當作鍵。也就是說,Object
結構提供了“字串—值”的對應,Map
結構提供了“值—值”的對應,是一種更完善的Hash
結構實現。
WeakMap 和 Map 的區別?
WeakMap
結構與Map
結構基本類似,唯一的區別是它只接受物件作為鍵名(null
除外),不接受其他型別的值作為鍵名,而且鍵名所指向的物件,不計入垃圾回收機制。WeakMap
最大的好處是可以避免記憶體洩漏。一個僅被WeakMap
作為key
而引用的物件,會被垃圾回收器回收掉。WeakMap
擁有和Map
類似的set(key, value)
、get(key)、has(key)
、delete(key)
和方法, 沒有任何與迭代有關的屬性和方法。clear()
重排和重繪
- 部分渲染樹(或者整個渲染樹)需要重新分析並且節點尺寸需要重新計算。這被稱為重排。注意這裡至少會有一次重排-初始化頁面佈局。
- 由於節點的幾何屬性發生改變或者由於樣式發生改變,例如改變元素背景色時,螢幕上的部分內容需要更新。這樣的更新被稱為重繪。
什麼情況會觸發重排和重繪?
- 新增、刪除、更新
DOM
節點 - 通過
display: none
隱藏一個DOM
節點-觸發重排和重繪 - 通過
visibility: hidden
隱藏一個DOM
節點-只觸發重繪,因為沒有幾何變化 - 移動或者給頁面中的
DOM
節點新增動畫 - 新增一個樣式表,調整樣式屬性
- 使用者行為,例如調整視窗大小,改變字號,或者滾動。
瀏覽器快取
瀏覽器快取分為強快取和協商快取。當客戶端請求某個資源時,獲取快取的流程如下:
- 先根據這個資源的一些
http header
判斷它是否命中強快取,如果命中,則直接從本地獲取快取資源,不會發請求到伺服器; - 當強快取沒有命中時,客戶端會傳送請求到伺服器,伺服器通過另一些
request header
驗證這個資源是否命中協商快取,稱為http
再驗證,如果命中,伺服器將請求返回,但不返回資源,而是告訴客戶端直接從快取中獲取,客戶端收到返回後就會從快取中獲取資源; - 強快取和協商快取共同之處在於,如果命中快取,伺服器都不會返回資源;
- 區別是,強快取不對傳送請求到伺服器,但協商快取會。
- 當協商快取也沒命中時,伺服器就會將資源傳送回客戶端。
- 當
ctrl+f5
強制重新整理網頁時,直接從伺服器載入,跳過強快取和協商快取; - 當
f5
重新整理網頁時,跳過強快取,但是會檢查協商快取;
強快取
- Expires(該欄位是
http1.0
時的規範,值為一個絕對時間的GMT
格式的時間字串,代表快取資源的過期時間) - Cache-Control:max-age(該欄位是
http1.1
的規範,強快取利用其max-age
值來判斷快取資源的最大生命週期,它的值單位為秒)
協商快取
- Last-Modified(值為資源最後更新時間,隨伺服器response返回)
- If-Modified-Since(通過比較兩個時間來判斷資源在兩次請求期間是否有過修改,如果沒有修改,則命中協商快取)
- ETag(表示資源內容的唯一標識,隨伺服器response返回)
- If-None-Match(伺服器通過比較請求頭部的If-None-Match與當前資源的ETag是否一致來判斷資源是否在兩次請求之間有過修改,如果沒有修改,則命中協商快取)
WeakMap
的 clear()
方法已經廢棄了,感謝 @Feibuli 指正
判斷物件相等 obj3
寫錯了,已改正 謝謝 @silent同志
有的答案可能不太準確,希望大家輕噴
掘金技術證文活動連結: https://juejin.im/post/5aaf2a95f265da239b413aa1