1. 程式人生 > >前端面試中常問的問題

前端面試中常問的問題

play section 深克隆 數據類型 use count () group flex布局

  1、event loop是什麽?
  
  主線程和任務隊
  
  2、HTTP協議與狀態碼,HTTP2.0等,狀態碼301、302等
  
  3、原生實現promise
  
  //原生js實現promise
  
  function PromiseM() {
  
  this.status = "pending"
  
  this.mag = ""
  
  let process = arguments[0]
  
  let that = this
  
  process(function(){
  
  that.status = "resolve"
  
  that.msg = arguments[0]
  
  },function(){
  
  that.status = "reject"
  
  that.msg = arguments[0]
  
  })
  
  return this
  
  }
  
  PromiseM.prototype.then = function() {
  
  let resolve = arguments[0]
  
  let reject = arguments[1]
  
  if(this.status == "resolve") {
  
  resolve(this.msg)
  
  }
  
  if(this.status == "reject" && arguments[1]) {
  
  reject(this.msg)
  
  }
  
  }
  
  4、CSS3中display屬性的Flex布局
  
  http://www.cnblogs.com/xuyuntao/articles/6391728.html
  
  5、瀏覽器緩存相關、強緩存與協商緩存、瀏覽器 http 200(from cache)和304的區別
  
  https://segmentfault.com/a/1190000012897512
  
  6、解決跨域的方法
  
  jsonp、window.postMessage等
  
  7、跨域資源共享 CORS
  
  http://www.ruanyifeng.com/blog/2016/04/cors.html
  
  8、typeof返回哪些數據類型
  
  https://blog.csdn.net/yellowmushroom/article/details/80249493
  
  9、Vue.nextTick()
  
  10、css盒子模型
  
  https://blog.csdn.net/zlingyun/article/details/81835665
  
  11、原生實現bind函數
  
  12、手寫一個object的深克隆
  
  13、算法-將以下數據結構按順序輸出
  
  var arr = [
  
  [1,2,3,4,5],
  
  [16,17,18,19,6],
  
  [15,24,25,20,7],
  
  [14,23,22,21,8],
  
  [13,12,11,10,9]
  
  ]
  
  14、算法-根據數據生成一個樹狀結構的對象
  
  var aTree = [
  
  {"id": "1", "name": "動物", "pid": "0"},
  
  {"id": "2", "name": "鳥類", "pid": "5"},
  
  {"id": "3", "name": "無脊椎動物", "pid": "1"},
  
  {"id": "4", "name": "哺乳動物", "pid": "5"},
  
  {"id": "5", "name": "脊椎動物", "pid": "1"},
  
  {"id": "6", "name": "喜鵲", "pid": "2"},
  
  {"id": "7", "name": "蚯蚓", "pid": "3"}
  
  ];
  
  15、函數節流與函數防抖
  
  16、圖片懶加載
  
  圖片懶加載實現(js部分):
  
  var imgSrc = "https://ss1.bdstatic.com/5aAHeD3nKgcUp2HgoI7O1ygwehsv/media/ch1000/png/pct1.png"
  
  var io = new IntersectionObserver(function(entries){
  
  entries.forEach(function(value){
  
  if(value.intersectionRatio > 0) {
  
  var target = value.target
  
  //var src = target.dataset.src
  
  target.src = imgSrc;
  
  io.unobserve(target)
  
  console.log(111)
  
  }
  
  })
  
  })
  
  var imgs = Array.from(document.querySelectorAll("#isImg"))
  
  console.log(imgs)
  
  imgs.forEach(function(item){
  
  io.observe(item)
  
  WaitGroup主要是三個方法,Add(int),Done()和Wait(), 其中Done()是調用了Add(-1),推薦使用方法是,先統一Add,在goroutine裏並發的Done,然後Wait
  
  WaitGroup主要維護了2個計數器,一個是請求計數器 v,一個是等待計數器 w,二者組成一個64bit的值,請求計數器占高32bit,等待計數器占低32bit。
  
  簡單來說,當Add(n)執行時,請求計數器 v 就會加n,當Done()執行時,v 就會減1,可以想到,v 為0時就是結束,可以觸發Wait()執行了,所謂的觸發Wait()是通過信號量實現的。
  
  那麽等待計數器拿來幹嘛?是因為Wait()方法支持並發,每一次Wait()方法執行,等待計數器 w 就會加1,而等待v為0觸發Wait()時,要根據w的數量發送w份的信號量,正確的觸發所有的Wait()。
  
  同時,WaitGroup裏還有對使用邏輯進行了嚴格的檢查,比如Wait()一旦開始不能Add().
  
  下面是帶註釋的代碼:
  
  復制代碼
  
  func (wg *WaitGroup) Add(delta int) {
  
  statep := wg.state()
  
  // 更新statep,statep將在wait和add中通過原子操作一起使用
  
  state := atomic.AddUint64(statep, uint64(delta)<<32)
  
  v := int32(state >> 32)
  
  w := uint32(state)
  
  if v < 0 {
  
  panic("sync: negative WaitGroup counter")
  
  }
  
  if w != 0 && delta > 0 && v == int32(delta) {
  
  // wait不等於0說明已經執行了Wait,此時不容許Add
  
  panic("sync: WaitGroup misuse: Add called concurrently with Wait")
  
  }
  
  // 正常情況,Add會讓v增加,Done會讓v減少,如果沒有全部Done掉,此處v總是會大於0的,直到v為0才往下走
  
  // 而w代表是有多少個goruntine在等待done的信號,wait中通過compareAndSwap對這個w進行加1
  
  if v > 0 || w == 0 {
  
  return
  
  }
  
  // This goroutine has set counter to 0 when waiters > 0.
  
  // Now there can‘t be concurrent mutations of state:
  
  // - Adds must not happen concurrently with Wait,
  
  // - Wait does not increment waiters if it sees counter == 0.
  
  // Still do a cheap sanity check to detect WaitGroup misuse.
  
  // 當v為0(Done掉了所有)或者w不為0(已經開始等待)才會到這裏,但是在這個過程中又有一次Add,導致statep變化,panic
  
  if *statep != state {
  
  panic("sync: WaitGroup misuse: Add www.michenggw.com called concurrently with Wait")
  
  }
  
  // Reset waiters count to 0.
  
  // 將statep清0,在Wait中通過這個值來保護信號量發出後還對這個Waitgroup進行操作
  
  *statep = 0
  
  // 將信號量發出,觸發wait結束
  
  for ; w != 0; w-- {
  
  runtime_Semrelease(&wg.sema, false)
  
  }
  
  }
  
  // Done decrements the WaitGroup counter by one.
  
  func (wg *WaitGroup) Done() {
  
  wg.Add(-1)
  
  }
  
  // Wait blocks until the WaitGroup counter is zero.
  
  func (wg *WaitGroup) Wait() {
  
  statep := wg.state()
  
  for {
  
  state := atomic.LoadUint64(statep)
  
  v := int32(state www.dasheng178.com>> 32)
  
  w := uint32(state)
  
  if v == 0 {
  
  // Counter is 0, no need to wait.
  
  if race.Enabled {
  
  race.Enable()
  
  race.Acquire(unsafe.Pointer(wg))
  
  }
  
  return
  
  }
  
  // Increment waiters count.
  
  // 如果statep和state相等,則增加等待計數,同時進入if等待信號量
  
  // 此處做CAS,主要是防止多個goroutine裏進行Wait()操作,每有一個goroutine進行了wait,等待計數就加1
  
  // 如果這裏不相等,說明statep,在 從讀出來 到 CAS比較 的這個時間區間內,被別的goroutine改寫了,那麽不進入if,回去再讀一次,這樣寫避免用鎖,更高效些
  
  if atomic.CompareAndSwapUint64(statep,www.mhylpt.com/ state, state+1) {
  
  if race.Enabled && w == 0 {
  
  // Wait must be synchronized with the first Add.
  
  // Need to model this is as a write to race with the read in Add.
  
  // As a consequence, can do the write only for the first waiter,
  
  // otherwise concurrent Waits www.fengshen157.com/ will race with each other.
  
  race.Write(unsafe.Pointer(&wg.sema))
  
  }
  
  // 等待信號量
  
  runtime_Semacquire(&wg.sema)
  
  // 信號量來了,代表所有Add都已經Done
  
  if *statep != 0 {
  
  // 走到這裏,說明在所有Add都已經Done後,觸發信號量後,又被執行了Add
  
  panic("sync: WaitGroup is reused before previous Wait has returned")
  
  }
  
  17、怎麽去掉首尾的空格(多種方法)
  
  18、事件觸發機制以及為什麽將事件綁定在冒泡階段?
  
  19、vue-router的配置
  
  20、為什麽說virtual DOM渲染更快
  
  21、HTTP的各種狀態碼

前端面試中常問的問題