1. 程式人生 > 其它 >面試十題(4)

面試十題(4)

1. 介紹下 BFC 及其應用。

BFC 就是塊級格式上下文,是頁面盒模型佈局中的一種 CSS 渲染模式,相當於一個獨立的容器,裡面的元素和外部的元素相互不影響。

  • 建立 BFC 的方式有:
  1. html 根元素
  2. float 浮動
  3. 絕對定位
  4. overflow 不為 visiable
  5. display 為表格佈局或者彈性佈局
  • BFC 主要的作用是:
  1. 清除浮動
  2. 防止同一 BFC 容器中的相鄰元素間的外邊距重疊問題

2. 在 Vue 中,子元件為何不可以修改父元件傳遞的 Prop?如果修改了,Vue 是如何監控到屬性的修改並給出警告的。

  • 因為vue設計是單向資料流,資料的流動方向只能是自上往下的方向;但是反過來則不行。這樣會防止從子元件意外變更父級元件的狀態,從而導致你的應用的資料流向難以理解。額外的,每次父級元件發生變更時,子元件中所有的 prop 都將會重新整理為最新的值。這意味著你不應該在一個子元件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制檯中發出警告。

  • 在initProps的時候,在defineReactive時通過判斷是否在開發環境,如果是開發環境,會在觸發set的時候判斷是否此key是否處於updatingChildren中被修改,如果不是,說明此修改來自子元件,觸發warning提示。

  • 需要特別注意的是,當你從子元件修改的prop屬於基礎型別時會觸發提示。 這種情況下,你是無法修改父元件的資料來源的, 因為基礎型別賦值時是值拷貝。你直接將另一個非基礎型別(Object, array)賦值到此key時也會觸發提示(但實際上不會影響父元件的資料來源), 當你修改object的屬性時不會觸發提示,並且會修改父元件資料來源的資料。

3. js 實現sleep函式

  • es6 非同步處理
// promise
const sleep = time => {
    return new Promise(resolve => setTimeout(resolve, time))
}
sleep(1000).then(() => {
    console.log('業務程式碼')
})

// async/await
const sleepPromise = (time) => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time);
  })
}
async function sleep (time) {
    await sleepPromise(time);
    console.log('業務程式碼')
}
sleep(5000)

// generator
const sleepPromise = (time) => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time);
  })
}
function* sleep(time) {
    yield sleepPromise(time);
}
sleep(5000).next().value.then(()=>{
    console.log('業務程式碼')
})
  • 偽死迴圈
function sleep(delay) {
  var start = (new Date()).getTime();
  while ((new Date()).getTime() - start < delay) {
    continue;
  }
}
console.log('1')
sleep(5000)
console.log('2')
  • 定時器+回撥函式
function sleep(time, callback) {
    setTimeout(callback, time)
}

sleep(time, () => {
    console.log('業務程式碼')
})

4. 雙向繫結和 vuex 是否衝突

參考連結

5. 為什麼通常在傳送資料埋點請求的時候使用的是 1x1 畫素的透明 gif 圖片?

  • 能夠完成整個 HTTP 請求+響應(儘管不需要響應內容)
  • 觸發 GET 請求之後不需要獲取和處理資料、伺服器也不需要傳送資料
  • 跨域友好
  • 執行過程無阻塞,只要 new Image 物件就好了,一般情況下也不需要 append 到 DOM 中,通過它的 onerror 和 onload 事件來檢測傳送狀態。
  • 相比 XMLHttpRequest 物件傳送 GET 請求,效能上更好
  • GIF 的最低合法體積最小(最小的 BMP 檔案需要 74 個位元組,PNG 需要 67 個位元組,而合法的 GIF,只需要 43 個位元組)

6. 實現 (5).add(3).minus(2) 功能。

  • 方法一
Number.prototype.add = function (number) {
  if (typeof number !== 'number') {
    throw new Error('請輸入數字~');
  }
  return this.valueOf() + number;
};
Number.prototype.minus = function (number) {
  if (typeof number !== 'number') {
    throw new Error('請輸入數字~');
  }
  return this.valueOf() - number;
};
console.log((5).add(3).minus(2));
  • 方法二
// 這裡的~寫成加號+ 減號- 都可以。但必須是一元表示式
// 匿名函式前面加~一元運算子就會轉變成函式表示式,函式表示式後面加()
~ function(){
    function add(n){
      return this + n
    }
    function minus(n){
      return this - n
    }
    Number.prototype.add = add
    Number.prototype.minus = minus
}()
console.log((5).add(3).minus(2))

  • 方法三
function addmin(){
    function add(n){
      return this + n
    }
    function minus(n){
      return this - n
    }
    Number.prototype.add = add
    Number.prototype.minus = minus
}
addmin()
console.log((5).add(3).minus(2))

7. Vue 的響應式原理中 Object.defineProperty 有什 麼缺陷? 為什麼在 Vue3.0 採用了 Proxy,拋棄了 Object.defineProperty?

  1. Object.defineProperty 無法監控到陣列下標的變化,導致通過陣列下標新增元素,不能實時響應;
  2. Object.defineProperty 只能劫持物件的屬性,從而需要對每個物件,每個屬性進行遍歷,如果,屬性值是物件,還需要深度遍歷。Proxy 可以劫持整個物件,並返回一個新的物件。
  3. Proxy 不僅可以代理物件,還可以代理陣列。還可以代理動態增加的屬性。

補充回答:Object.defineProperty 本身有一定的監控到陣列下標變化的能力,但是在 Vue 中,從效能/體驗的價效比考慮,尤大大就棄用了這個特性。

8. div 水平垂直居中

  • 方法一
// 父元素
box {
    display: flex;
    justify-content: center;
    align-items: center;
}
  • 方法二
// 絕對定位
.div {
    width: 200px;
    height: 200px;
    background: green;
    position:absolute;
    left:0;
    top: 0;
    bottom: 0;
    right: 0;
    margin: auto;   
}
  • 方法三
// margin 負間距
div {
    width:200px;
    height: 200px;
    background:green;
    position: absolute;
    left:50%;
    top:50%;
    margin-left:-100px;
    margin-top:-100px;
}
  • 方法四
// transform 變形
div {
    width: 200px;
    height: 200px;
    background: green;
    position:absolute;
    left:50%;    /* 定位父級的50% */
    top:50%;
    transform: translate(-50%,-50%); /*自己的50% */
}

9. 下面程式碼執行結果及原因

var a = {n:1}
var b = a;
a.x = a = {n:2}
console.log(a.x) // undefined
console.log(b.x)    // {n: 2}

考察運算子的優先順序,雖然賦值是從右往左,但是.的運算子比=的優先順序高。所以先執行a.x = {n: 2}再執行a = {n: 2}

10. 氣泡排序如何實現,時間複雜度是多少, 還可以如何改進?

  • 氣泡排序
var a = [11,2,55,123,88,3,67];
function bubbleSort(arr) {
    console.time('time')
	for (var i = 0; i < arr.length; i++) {
		for (var j = 0; j < arr.length - i - 1; j++) {
			if (arr[j] > arr[j + 1]){
				let temp = arr[j]
				arr[j] = arr[j + 1]
				arr[j + 1] = temp
			}
		}
	}
	console.timeEnd('time')
	console.log(arr)
	return arr
}
bubbleSort(a)
  • 改進氣泡排序
var a = [11,2,55,123,88,3,67];
function bubbleSort1(arr) {
	console.time('time')
	var i = arr.length - 1;
	while(i > 0) {
		let pos = 0;
		for (var j = 0; j < i; j++) {
			if (arr[j] > arr[j + 1]) {
				pos = j
				let temp = arr[j]
				arr[j] = arr[j + 1]
				arr[j + 1] = temp
			}
		}
		i = pos
	}
	console.timeEnd('time')
	console.log(arr)
	return arr
}
bubbleSort1(a)