8、你對重繪、重排的理解?
- 首先網頁數次渲染生成時,這個可稱為重排;
- 修改DOM、樣式表、用戶事件或行為(鼠標懸停、頁面滾動、輸入框鍵入文字、改變窗口大小等等)這些都會導致頁面重新渲染,那麼重新渲染,就需要重新生成佈局和重新繪製節點,前者叫做"重排",後者"重繪";
- 減少或集中對頁面的操作,即多次操作集中在一起執行;
- 總之可以簡單總結為:重繪不一定會重排,但重排必然為會重繪。
8、有用過promise嗎?請寫出下列代碼的執行結果,並寫出你的理解思路:
setTimeout(()=>{
console.log(1);
}, 0);
new Promise((resolve)=>{
console.log(2);
for(var i = 1; i < 200; i++){
i = 198 && resolve();
}
console.log(3);
}).then(()=>{
console.log(4);
});
console.log(5);
// 結果:2、3、5、4、1;
- 首先要講一下,js是單線程執行,那麼代碼的執行就有先後;
- 有先後,那就要有規則(排隊),不然就亂套了,那麼如何分先後呢?大體分兩種:同步、異步;
- 同步很好理解,就不用多說了(我就是老大,你們都要給我讓路);
- 異步(定時器[setTimeout ,setInterval]、事件、ajax、promise等),說到異步又要細分宏任務、微任務兩種機制,
- 宏任務:js異步執行過程中遇到宏任務,就先執行宏任務,將宏任務加入執行的隊列(event queue),然後再去執行微任務;
- 微任務:js異步執行過程中遇到微任務,也會將任務加入執行的隊列( ),但是注意這兩個queue身份是不一樣的,不是你先進來,就你先出去的(就像宮裡的皇上選妃侍寢一樣,不是你先進宮(或先來排隊)就先寵幸的 ),真執行的時候是先微任務裡拿對應回調函數,然後才輪到宏任務的隊列回調執行的;
- 理解了這個順序,那上面的結果也就不難懂了。
說細步驟如下:
setTimeout 是異步,不會立即執行,加入執行隊列;
new Promise 會立即執行 輸出 2、3,而在2、3之間執行了resolve 也就是微任務;
再到console.log(5)了,輸出5;
然後異步裡的微任務先出,那就得到4;
最後執行宏任務 setTimeout 輸出 1;
如有錯誤歡迎糾正!
9、new SouthSu() 在這個過程中都做了些什麼?
function SouthSu(){
this.name
this.age
this.address
this.address
};
let South = new SouthSu();
console.log(South,South.__proto__ === SouthSu.prototype) //true
執行過程:
創建一個空的對象
let p1 = new Object();
設置原型鏈
p1.__proto__ = SouthSu.prototype;
讓 構造函數 的this 指向 p1 這個空對象
let funCall = SouthSu.call(p1);
處理 構造函數 的返回值:判斷SouthSu的返回值類型,如果是值類型則返回obj,如果是引用類型,就返回這個引用類型的對象;
10、工作中如果讓你使用js實現一個持續的動畫,你會怎麼做(比如轉盤抽獎)??
- js來實現動畫,第一時間想到的就是定時器(setTimeout、setInterval);
- 後面想起來js有個 window.requestAnimationFrame ,當時只是說了記得有這麼一個API,具體的細節沒能答上,面試官直言想聽的就是這個API的使用,好吧是我準備的不夠充分,希望其他同學不再犯同樣錯誤;
window.requestAnimationFrame() 方法告訴瀏覽器您希望執行動畫並請求瀏覽器在下一次重繪之前調用指定的函數來更新動畫。該方法使用一個回調函數作為參數,這個回調函數會在瀏覽器重繪之前調用,回調的次數通常是每秒60次,是大多數瀏覽器通常匹配 W3C 所建議的刷新頻率。在大多數瀏覽器裡,當運行在後臺標籤頁或者隱藏的
小結:以往項目開發中大數人可能都是第一時間選擇JS定時器setInterval 或者setTimeout 來控制的動畫每隔一段時間刷新元素的狀態,來達到自己所想要的動畫效果,但是這種方式並不能準確地控制動畫幀率,因為這是開發者主動要求瀏覽器去繪製,它這可能會因為動畫控制的時間、繪製的頻率、瀏覽器的特性等而導致丟幀的問題; requestAnimationFrame 是瀏覽器什麼時候要開始繪製了瀏覽器它自己知道,通過requestAnimationFrame告訴我們,這樣就不會出現重複繪製丟失的問題。
//一個持續旋轉的正方形,
11、如何設置http緩存?
1)、Expires
- Expires的值為服務端返回的到期時間,響應時告訴瀏覽器可以直接從瀏覽器緩存中讀取無需再次請求。
缺點:返回的是服務端的時間,比較的時間是客戶端的時間,如果時間不一致有可能出現錯誤。
2)、Cache-Control
- Cache-Control可設置的字段有:
- private:客戶端可以緩存
- public:客戶端和代理服務器都可以緩存
- max-age=xxx:緩存內容在xxx秒後失效
- no-cache:需要用另一種緩存策略來驗證緩存(ETag,Last-Modified)
- no-store:不進行緩存
- Last-Modified:瀏覽器請求獲得文件後,服務器返回該文件的最後修改時間Last-Modified,下一次請求會帶上If-Modified-Since標識,如果If-Modified-Since等於服務器的文件修改時間,則表示文件沒有修改,返回304狀態碼,瀏覽器從瀏覽器緩存中讀取文件。如果If-Modified-Since小於服務端的文件修改時間,則瀏覽器會重新發送請求獲取文件,返回狀態碼200。
- ETag:服務器文件的一個唯一標識,例如對文件內容取md5值作為ETag的字段返回給瀏覽器。當文件變化時ETag的值也會發生變化。下次請求會帶上If-None-Match即瀏覽器保留的ETag值,如果發送了變化,則文件被修改,需要重新請求,返回200狀態碼。反之瀏覽器就從緩存中讀取文件,返回304狀態碼。
總結:——幾者之間的關係
- 當Cache-Control設置為max-age=xx並且同事設置Expires時,Cache-Control的優先級更高
- 當ETag和Last-Modified同時存在時,服務器先會檢查ETag,然後再檢查Last-Modified,最終決定返回304還是200
- 該題由 本文由平頭哥聯盟-成員(ZodiacSyndicate )補充
12、隨機打亂一個數組
- 思路:從數組的最後一項開始,隨機選擇前面的一個元素進行交換,然後一步步往前交換
const shuffle = arr => {
let end = arr.length - 1
while(end) { // 當end為0時不需要交換
const index = Math.floor(Math.random() * (end + 1))
[arr[index], arr[end]] = [arr[end], arr[index]]
end -= 1
}
return arr
}
13、用React實現一個顯示鼠標位置的高階組件
const mousePosition = Component => class extends React.Component {
state = {
x: 0,
y: 0,
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
const { x, y } = this.state
return (
<>
x: {x}
y: {y}
>
)
}
}
閱讀更多 前端嫣然呀呀呀 的文章