日問週刊 | 全棧面試彙總 | 第二期

勤學如春起之苗,不見其增,日有所長;輟學如磨刀之石,不見其損,日有所虧。javascript

我在 github 上新建了一個倉庫 日問,天天至少一個問題。有關全棧,graphql,devops,微服務以及軟技能,促進職業成長,歡迎交流。html

以諸葛武侯的誡子書與君共勉前端

夫君子之行,靜以修身,儉以養德。非澹泊無以明志,非寧靜無以至遠。夫學須靜也,才須學也,非學無以廣才,非志無以成學。淫慢則不能勵精,險躁則不能治性。年與時馳,意與日去,遂成枯落,多不接世,悲守窮廬,將復何及!java

【Q037】linux 有哪些發行版,你最喜歡哪個

原文連接,歡迎討論: 【Q037】linux 有哪些發行版,你最喜歡哪個react

開放問題,不過你至少得知道一個發行版...linux

【Q036】http 狀態碼中 301,302和307有什麼區別

原文連接,歡迎討論: 【Q036】http 狀態碼中 301,302和307有什麼區別git

  • 301,Moved Permanently。永久重定向,該操做比較危險,須要謹慎操做:若是設置了301,可是一段時間後又想取消,可是瀏覽器中已經有了緩存,仍是會重定向。
  • 302,Fount。臨時重定向,可是會在重定向的時候改變 method: 把 POST 改爲 GET,因而有了 307
  • 307,Temporary Redirect。臨時重定向,在重定向時不會改變 method

【Q035】http 常見的狀態碼有哪些

原文連接,歡迎討論: 【Q035】http 常見的狀態碼有哪些github

【Q034】如何實現一個 loading 動畫

原文連接,歡迎討論:【Q034】如何實現一個 loading 動畫web

【Q033】如何對接口進行限流]

原文連接,歡迎討論: 【Q033】如何對接口進行限流面試

通常採用漏桶算法:

  1. 漏桶初始爲空
  2. API 調用是在往漏桶裏注水
  3. 漏桶會以必定速率出水
  4. 水滿時 API 拒絕調用

漏桶算法

可使用 redis 的計數器實現

  1. 計數器初始爲空
  2. API 調用計數器增長
  3. 給計數器設置過時時間,隔段時間清零,視爲必定速率出水
  4. 計數器達到上限時,拒絕調用

固然,這只是大體思路,這時會有兩個問題要注意

  1. 最壞狀況下的限流是額定限流速率的2倍
  2. 條件競爭問題

不過實際實現時注意如下就行了(話說通常也是調用現成的三方庫作限流...),能夠參考我之前的文章 https://shanyue.tech/post/rate-limit/

【Q032】js 中什麼是 softbind,如何實現

原文連接,歡迎討論:【Q032】js 中什麼是 softbind,如何實現

【Q031】js 中如何實現 bind

原文連接,歡迎討論: 【Q031】js 中如何實現 bind

最簡單的 bind 一行就能夠實現,而在實際面試過程當中也不會考察你太多的邊界條件

Function.prototype.fakeBind = function(obj) {
  return (...args) => this.apply(obj, args)
}

測試一下

function f (arg) {
  console.log(this.a, arg)
}

// output: 3, 4
f.bind({ a: 3 })(4)

// output: 3, 4
f.fakeBind({ a: 3 })(4)

【Q030】linux 中如何打印全部網絡接口

原文連接,歡迎討論: 【Q030】linux 中如何打印全部網絡接口

ifconfig

ifconfig 是最簡單最經常使用,可是打印信息太多了

$ ifconfig

netstat

netstatip 也挺好用,特別是它們還能夠打印路由表

$ netstat -i

ip

$ ip link

$ ip addr

【Q029】websocket 如何向特定的用戶組推送消息

redis 處維護一個對象,記錄每一個 group 所對應的 connections/sockets

{
  'Class:201901': [student1Socket, student2Socket]
}

當 client 剛連入 server 時,便加入某個特定的組,或者叫 room,好比 student01,剛開始連入 server,可能要加入 room:Student:01Class:201901Group:10086

【Q028】在linux中如何獲取登陸的用戶

【Q028】在linux中如何獲取登陸的用戶

$ who

$ last

【Q027】在前端開發中,如何獲取瀏覽器的惟一標識

fingerprintjs2

【Q026】如何對接口進行壓力測試

【Q025】簡述 socket 創建的過程

一圖勝千言

image

【Q024】在 postgres 中,查詢時如何對 jsonb 數據格式化

使用 jsonb_pretty 函數,示例以下

> select jsonb_pretty('{"a": {"b": 4}}'::jsonb)
+----------------+
| jsonb_pretty   |
|----------------|
| {              |
|     "a": {     |
|         "b": 4 |
|     }          |
| }              |
+----------------+
SELECT 1
Time: 0.018s

【Q023】websocket 服務多節點部署時會有什麼問題,怎麼解決

借用 redis

【Q022】如何實現一個簡單的 Promise

一個簡單的 Promise 的粗糙實現,關鍵點在於

  1. pending 時, thenable 函數由一個隊列維護
  2. 當狀態變爲 resolved(fulfilled) 時,隊列中全部 thenable 函數執行
  3. resolved 時, thenable 函數直接執行

rejected 狀態同理

class Prom {
  static resolve (value) {
    if (value && value.then) {
      return value 
    }
    return new Prom(resolve => resolve(value))
  }

  constructor (fn) {
    this.value = undefined
    this.reason = undefined
    this.status = 'PENDING'

    // 維護一個 resolve/pending 的函數隊列
    this.resolveFns = []
    this.rejectFns = []

    const resolve = (value) => {
      // 注意此處的 setTimeout
      setTimeout(() => {
        this.status = 'RESOLVED'
        this.value = value
        this.resolveFns.forEach(({ fn, resolve: res, reject: rej }) => res(fn(value)))
      })
    }

    const reject = (e) => {
      setTimeout(() => {
        this.status = 'REJECTED'
        this.reason = e
        this.rejectFns.forEach(({ fn, resolve: res, reject: rej }) => rej(fn(e)))
      })
    }

    fn(resolve, reject)
  }


  then (fn) {
    if (this.status === 'RESOLVED') {
      const result = fn(this.value)
      // 須要返回一個 Promise
      // 若是狀態爲 resolved,直接執行
      return Prom.resolve(result)
    }
    if (this.status === 'PENDING') {
      // 也是返回一個 Promise
      return new Prom((resolve, reject) => {
        // 推動隊列中,resolved 後統一執行
        this.resolveFns.push({ fn, resolve, reject }) 
      })
    }
  }

  catch (fn) {
    if (this.status === 'REJECTED') {
      const result = fn(this.value)
      return Prom.resolve(result)
    }
    if (this.status === 'PENDING') {
      return new Prom((resolve, reject) => {
        this.rejectFns.push({ fn, resolve, reject }) 
      })
    }
  }
}

Prom.resolve(10).then(o => o * 10).then(o => o + 10).then(o => {
  console.log(o)
})

return new Prom((resolve, reject) => reject('Error')).catch(e => {
  console.log('Error', e)
})

【Q021】React 中,cloneElement 與 createElement 各是什麼,有什麼區別

首參不同,直接上 API

React.cloneElement(
  element,
  [props],
  [...children]
)

React.createElement(
  type,
  [props],
  [...children]
)

【Q020】如何實現一個分佈式鎖

【Q019】如何實現選中複製的功能

它通常可使用第三方庫 clipboard.js 來實現,源碼很簡單,能夠讀一讀

主要有兩個要點

  1. 選中
  2. 複製

選中

選中主要利用了 Selection API

選中的代碼以下

const selection = window.getSelection();
const range = document.createRange();

range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);

selectedText = selection.toString();

取消選中的代碼以下

window.getSelection().removeAllRanges();

它有現成的第三方庫可使用: select.js

複製

複製就比較簡單了,execCommand

document.exec('copy')
相關文章
相關標籤/搜索