廣州-鬥遊前端筆試題

這是面試的第三家公司了= =砥礪前行好吧。javascript

說實話,筆試題手寫代碼真的難受 = =,面試的時候還不問我實現思路和答案(那我筆試的意義何在),面談最後仍是三句靈魂拷問:css

  • 你以爲你本身作前端有什麼優點?
  • 你以爲你最有成就感的項目是?印象最深入的項目是?

話很少說了,直接上題吧!html

一、對於一個寬度固定可是高度不固定的元素,如何實現水平居中和垂直居中?

html 文檔前端

<div class="parent">
    <div class="child"></div>
</div>
  • flex實現

.parent{
  display: flex;
  justify-content:center;
  align-items:center;
  height:100px;
  border: 1px solid red;
}
.child {
  width:  100px;
  border: 1px solid red;
}
  • position實現

margin常見的幾種寫法
默認值:margin: 0;
  1. margin: 10px; // 外邊距離全是10px
  2. margin: 10px 20px; // 上下外邊距10px,左右外邊距20px
  3. margin: 10px 20px 30px;// 上外邊距10px,左右外邊距20px,下邊距是30px
  4. margin: 10px 20px 30px 40px; // 從左往右依次外邊距方向依次是上、右、下、左
.parent{
  height:100px;
  border: 1px solid red;
  position: relative;
}
.child {
  position: absolute;
  width: 100px;
  top: 50%;
  left:50%;
  transform: translate(-50%,-50%);
}
這裏有個小提問:爲何設置margin:auto;水平會居中,可是垂直卻不居中呢?不是說auto是自動計算屬性?

二、下面三段代碼分別輸出什麼?而且何時輸出什麼?

for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
}
for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
}
for (var i = 0; i < 5; i++) {
    (function (i) {
      setTimeout(function () {
        console.log(i)
      }, 1000 * i)
    })(i)
}

答案:java

  1. 在極短的一段時間內輸出5,隨後每隔一秒輸出一個5

// 5 5 5 5 5node

  1. 在極短的一段時間內輸出0,隨後每隔一秒結果加1

// 0 1 2 3 4面試

  1. 在極短的一段時間內輸出0,隨後每隔一秒結果加1

// 0 1 2 3 4數組

解析:
1.首先要明白js的事件循環機制,for循環結束後纔到宏觀任務setTimeout,這時候i的值已經變爲5了
2.let i 是塊做用域,相似於app

for (let i = 0; i < 5; i++) {
  let i = /* 塊做用域裏面的i */
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
}

所以每一次循環,i的值都是塊做用域裏面的值
3.當即執行函數,建立了屬於本身的做用域,所以每一次執行都是不一樣的i函數

三、下面這段代碼輸出了什麼?

var a = 1;
var obj = {
  a: 2,
  func1: () => {
    console.log(this.a);
  },
  func2: function () {
    console.log(this.a);
  }
}

var obj2 = { a: 3 };

console.log(obj.func1());
console.log(obj.func2());

obj.func2.apply(obj2);

var newFunc = obj.func2;

newFunc();

答案:

var a = 1;
var obj = {
  a: 2,
  // 注意箭頭函數的this指向是在定義的時候就綁定了而不是在執行的時候,所以func1的this指向一個空對象
  func1: () => {
    console.log(this.a);
  },
  func2: function () {
    console.log(this.a);
  }
}

var obj2 = { a: 3 };

console.log(obj.func1()); // 函數是沒返回值的,首先會打印undefined,函數體裏面是箭頭函數this指向undefined,所以還會打印出undefined
console.log(obj.func2());// 函數是沒返回值的,首先會打印undefined,函數體裏面是普通匿名函數this指向obj,所以還會打印出2

obj.func2.apply(obj2);
// 顯式更改this的指向到obj2,所以打印3

var newFunc = obj.func2;

newFunc();
// 在全局環境下調用func2函數,此時this指向全局變量window,打印1

四、實現一個函數:輸入一個整數,求該整數的二進制表達中有多少個1?

個人答案:

// 十進制轉化二進制--除2取餘法
function toBinary(number) {
  let arr = []
  while (number > 0) {
    let a = number % 2
    number = (number - a) / 2
    arr.push(a)
  }
  return arr.reverse()
}
// 篩選出含有1的數組
// 一次遍歷 時間複雜度是N
let a = toBinary(1223).filter(item=>item === 1)
console.log(a.length) // 得到多少個1個數

網上還有一些利用補碼等解決的方式

五、實現一個函數:給定一個字符串,找出出現次數最多的字符。

個人答案:

// 暴力的2次循環,複雜度n^2
function getMostChart(str) {
  let list = [...str]; // 拆分字符串爲數組
  let noRepeatList = Array.from(new Set(list)) // 合併數組中重複的元素
  let lengthList  = [] // noRepeatList每一項在list出現的次數組成的數組
  noRepeatList.map(ele => {
    let count = 0;
    list.map(item => {
      if (ele === item) {
        count++
      }
    })
    lengthList.push(count) // [ 1, 1, 2, 1, 1 ]
  })
 let max = lengthList[0]
  // 獲取最大值及其下標
  for (let i = 0; i < lengthList.length; i++) {
    let current = lengthList[i];
    current > max ? max = current : null
  }
  
  // 注意這裏maxIndex可能不止一個,最好仍是for循環獲取最大值的下標
  let maxIndex = lengthList.findIndex(item => item === max)
  
  return noRepeatList[maxIndex]
}

getMostChart('choose') // o
個人答案不夠優秀而且忽略了次數出現最多的字符可能會有多個
,好比說'ccoo'

網上利用JSON特性,時間複雜度只有N的答案

六、實現一個單向鏈表類,要求支持新增、刪除、查找操做

答案

/**
* 定義一個節點類
*/
class Node {
  constructor(val) {
    this.val = val; // 結點值
    this.next = null; // 結點指針,指向下一項
  }
}

/**
* 定義一個單向鏈表類
*/

class LinkedList {
  constructor() {
    this.headNode = new Node('head'); // 初始化一個頭結點
  }
    
  // 新增節點
  insert(val) {
    let currentNode = this.headNode,
        lastNode = new Node(val);
    
    while(true) {
      if(currentNode.next == null) {
        break;
      } else {
        currentNode = currentNode.next;
      }
    }
    
    lastNode.next = currentNode.next;
    currentNode.next = lastNode;
  }
    
  
    
  // 刪除鏈表某一項
  remove(val) {
    let currentNode = this.headNode;
    
    while(true) {
      if(currentNode.next.val == val) {
        break;
      } else {
        currentNode = currentNode.next;
      }
    }
    
    currentNode.next = currentNode.next.next;
  }
  
  // 查找
  search(val) {
    let currentNode = this.headNode;
    while (currentNode.next) {
          currentNode = currentNode.next;
          if (currentNode.val === val) {
            return currentNode
          }
        }
      }
  }
}


var nodes = new LinkedList();

nodes.insert('a');
nodes.insert('b');
nodes.insert('c');
console.log(nodes.search('c')); // Node { val: 'orange', next: null }
個人答案不必定是正確且優秀的,解析可能也有寫不充分的地方,歡迎你們留言指正或補充
相關文章
相關標籤/搜索