記一次比較遙遠的面試提問,記得多少寫多少,附較詳細的解答,歡迎指出錯誤。
1. 說說CSS中的相對定位與絕對定位:
position: relative;
為相對定位,根據自身位置來進行定位。position: absolute;
為絕對定位,若父級節點的position
屬性不為static
,則根據父級節點位置進行定位;否則則繼續尋找上一級position
屬性不為static
的節點進行定位,若都沒有找到,則以視窗進行定位。
2. this
的指向
- 一般情況下,
this
指向呼叫該函式的物件 - 箭頭函式裡的
this
指向定義時所在的物件 this
的指向可以通過bind
函式改變
3. 類裡靜態方法的this
指向
因this
指向呼叫該函式的物件,而靜態方法不用建立例項來呼叫,而是通過類本身來直接呼叫,故this
指向這個類本身而不是例項。
4. let
、const
let
:
- 定義的變數只在當前程式碼塊有效,存在區域性作用域。
- 不存在變數提升,即未定義前訪問變數會報錯,而不是返回
undefined
。 - 在同一個程式碼塊內不允許重複定義同一個變數。
const
:
- 擁有
let
的所有特性 const
定義的常量指向的地址不能改變。- 如果定義的是個物件或者陣列這種引用型別,只是不能改變它指向的記憶體地址,但它的屬性可以改變。
5. 在React元件的render函式裡呼叫setState會發生什麼問題?哪個生命週期函式可以阻止這個問題發生?PureCompoent。
會發生死迴圈問題,因為setState
又會觸發render
函式。shouldComponentUpdate
生命週期函式返回false
的時候不會觸發render
,可以阻止這個問題發生。
PureCompoent在shouldComponentUpdate
實現一個淺比較,需要注意的是以下程式碼不會觸發render
:
const newState = this.state.someState;
newState.attr = `newValue`;
this.setState({
someState: newState,
});
複製程式碼
這是因為淺比較是比較這個變數的地址,地址不變則返回false
。
下面程式碼會觸發render
:
const newState = this.state.someState;
newState.attr = `newValue`;
this.setState({
someState: {...newState},
});
複製程式碼
還可以使用immutable來寫,這裡使用的是immutable的一個輔助庫immutability-helper-x:
import update from `immutability-helper-x`;
...
this.setState({
someState: update.$set(this.state.someState, `attr`, `newValue`),
});
複製程式碼
6. 淺拷貝和深拷貝。
淺拷貝
淺拷貝就是把物件的屬性的值都複製一份到新的記憶體地址,但只複製一層,若屬性的值為物件,則還是原來的引用。如:
const obj = {
child: {
key: `value`,
},
};
const newObj = shallowCopy(obj);
console.log(newObj.child === obj.child); // true
複製程式碼
實現方法:
function shallowCopy(obj) {
// ES6
// return {...obj};
return Object.assign({}, obj);
}
複製程式碼
深拷貝
而深拷貝則遍歷整個物件,把這個物件所有的值都移到新的記憶體空間,不存在原來的引用,如:
const obj = {
child: {
key: `value`,
},
};
const newObj = deepCopy(obj);
console.log(newObj.child === obj.child); // false
複製程式碼
深拷貝可以通過遍歷整個物件來拷貝,也有一種比較簡單的實現方法,但效率都比較差。
function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
複製程式碼
7. Node中的事件迴圈
因為JS是單執行緒的,執行I/O操作時會阻塞執行緒,如果一直等待I/O操作完成再執行下面的程式碼是不現實的,因此就需要事件迴圈。
事件迴圈就是當遇到像I/O這種阻塞執行緒的操作時,把他們交給系統核心去進行處理,Node繼續往下執行程式碼,等到I/O操作執行完後告知Node,然後Node會把響應的回撥函式加進事件佇列等待執行。
8. 瀏覽器快取
強快取
HTTP狀態碼為200(from cache)
,它的優點是沒有訪問伺服器,直接在本地讀取快取,減少HTTP請求,但也因為如此,這也是它的缺點,因為它不知道伺服器資源是否有更新,從而無法獲取到最新的資源,這個問題通常用給靜態資源新增Hash值來判斷資源有無更新,若Hash值不同,則會請求獲取最新資源。
相關Header有(按優先順序排序):
Cache-Control
。設定一個最大有效期,如Cache-Control: max-age=36000000
Expires
。它描述一個最後的過期時間,如Expires: Tue, 17 Jul 2018 15:42:01 GMT
協商快取
HTTP狀態碼為304
,當沒有強快取或者強快取過期時,會傳送請求到伺服器,若伺服器發現資源沒有更新,則返回304
告訴客戶端不必更新。因為它還是要傳送請求,所以比強快取慢。
相關Header有:
Last-Modified
、If-Modified-Since
ETag
、If-None-Match
9. 記憶體洩漏
JS提供自動管理記憶體,稱為“垃圾回收機制”,通常用的是“引用計數”,即當一個物件的引用數為0時就把它釋放回收。而當一個不在使用的物件的引用數又不為0的時候,無法把他進行回收,即造成記憶體洩漏問題。