筆試題

實現繼承

// call方法
// 缺點無法繼承原型方法
 function Parent () {}
 function Child () {
   Parent.call(this)
}
// 原型鏈繼承
// 缺點:所有實例共用同一個原型對象
function Parent () {}
function Child () {}
Child.prototype = new Parent()
// 組合形式
function Parent () {}
function Child () {
  Parent.call(this)
}
Child.prototype. = Object.create(Parent.prototype)
Child.prototype.constructor = Child

// es6繼承
class Parent {}
class Child extends Parent {
  constructor() {
      super()
  }
}

防抖

function debounce (fn, delay) {
  let timer = null
  return function () {
    const that = this
    const ars = Array.prototype.slice.call(arguments)
    if (timer) {
        clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(that, ars)
    }, delay)
}

節流

function throttle(fn, delay) {
  let timer = null
  return function () {
    const that = this
    if (timer) {
      return 
    }
    const args = Array.prototype.slice.call(arguments)
    timer = setTimerout(() => {
      fn.apply(that, args)
      timer = null
    }, delay)
  }
}

reduce實現map

Array.prototype.map = function (cb) {
  return this.reduce((acc, cur, index, arr) => {
     acc.push(cb.call(null, cur, index, arr))
    return acc
  }, [])
}

二叉樹遍歷

// 前序遍歷
function visit (node) {
  const arr = []
  function _v (n) {
    if (!n) return
    arr.push(n.val)
    _v(n.left)
    _v(n.right)
  }
  _v(node)
  return arr
}
function visit(node) {
  const arr = []
  const stack = [node] 
  while(stack.length) {
    const curNode = stack.pop()
    arr.push(curNode.val)
    if (curNode.right) {
      stack.push(node.right)
    }
    if(curNode.left){
      stack.push(node.left)
    }
  }
  return arr
}

// 中續遍歷
function visit (node) {
  let arr = []
  function _v (n) {
    if (!n) return
    _v(n.left)
    arr.push(n.val)
    _v(n.right)
  }
  _v(node)
  return arr
}
// 中序遍歷 迭代法
var inorderTraversal = function(root) {
    const stack = []
    const res = []
    while(root || stack.length) {
        while(root) {
            stack.push(root)
            root = root.left
        }
        const curNode = stack.pop()
        res.push(curNode.val)
        root = curNode.right
    }
    return res
};

// 后續遍歷
function visit (node) {
  let arr = []
  function _v (n) {
    if (!n) return
    _v(n.left)
    _v(n.right)
    arr.push(n.val)
  }
  _v(node)
  return arr
}
// 迭代法 后序遍歷
var postorderTraversal = function (root) {
    const stack = [root];
    const res = [];

    while (stack.length > 0) {
        const node = stack.pop();
        if (node) {
            stack.push(node.left, node.right);
            res.unshift(node.val);
        }
    }
    return res;
};
// 層序遍歷
function solution (root) {
  const res = []
  if (!root) {
    return res
  }
  const queue = []
  queue.push(root)
  while (queue.length !== 0) {
    const curQueueLength = queue.length
    const curArr = []
    for (let i = 0; i < curQueueLength; i++) {
      const node = queue.shift()
      curArr.push(node.val)
      node.left && queue.push(node.left)
      node.right && queue.push(node.right)
    }
    res.push(curArr)
  }
  return res
}

數組去重

function unique (arr) {
  if (Array.isArray(arr)) {
    return Array.from(new Set(arr))
  }
}
function unique (arr) {
  let cache = {}
  let uniqueArr = []
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] in cache) {
      continue
    } else {
      cache[arr[i]] = true
      uniqueArr.push(arr[i])
    }
  }
  return uniqueArr
}

斐波那契數列

function Fibonacci(j)
{
  // n = (n-1)+(n-2)
  const cache = {
    0: 0,
    1: 1
  }
  function _fibonacci (n) {
    if (cache[n] !== undefined) {
      return cache[n]
    }
    cache[n] = _fibonacci(n-1) + _fibonacci(n-2)
    return cache[n]
  }
  
  return _fibonacci(j)

}

function fbnc (n) {
  let cur = new Array(n)
  cur[0] = 0
  cur[1] = 1
  for (let i = 2; i < n; i++) {
    cur[i] = cur[i - 1] + cur[i - 2]
  }
  return cur
}

調度器

//JS實現一個帶并發限制的異步調度器Scheduler,保證同時運行的任務最多有兩個。完善代碼中Scheduler類,使得以下程序能正確輸出
class Scheduler {
  constructor() {
    this.tasks = {}
    this.queue = []
    this.uid = 0
  }
  get taskLength() {
    return Object.keys(this.tasks).length
  }

  add(promiseCreator) {
    return new Promise((resolve) => {
      this.queue.push({
        id: this.uid++,
        isCreated: false,
        promiseCreator,
        resolve
      })
      this.pushTasks()
    })
  }

  pushTasks () {
    if (this.taskLength < 2 && this.queue.length > 0) {
      const cur = this.queue.shift()
      this.tasks[cur.id] = cur
    }
    this.startTasks()
  }

  startTasks () {
    for(let id in this.tasks) {
      const task = this.tasks[id]
      if (task.isCreated) {
        continue
      }
      task.isCreated = true
      task.promiseCreator().then(() => {
        task.resolve()
        delete this.tasks[id]
        this.pushTasks()
      })
    }
  }

  // ...
}

const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler()
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => console.log(order))
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// output: 2 3 1 4

// 一開始,1、2兩個任務進入隊列
// 500ms時,2完成,輸出2,任務3進隊
// 800ms時,3完成,輸出3,任務4進隊
// 1000ms時,1完成,輸出1
// 1200ms時,4完成,輸出4

數組快排

// 冒泡
var sortArray = function(arr) {

    const max = arr.length
    for(let i = 0; i < max - 1; i++) {
        for (let j = 0; j < max - 1 -i; j++) {
            if (arr[j] > arr[j+1]) {
                const temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
            }
        }
    }
    return arr
    
};
// 快排
var quickSort = function(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];
  var left = [];
  var right = [];

  for (var i = 0; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return quickSort(left).concat([pivot], quickSort(right));
};

洗牌算法 (打亂數組)

function randArr (arr) {
  const n = arr.length
  const randOne = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)
  for(let i = 0; i < n; i++) {
    const rand = randOne(i, n - 1)
    const temp = arr[i]
    arr[i] = arr[rand]
    arr[rand] = temp
  }
  return arr
}

二分查找

var search = function(nums, target) {
    let l = 0;
    let r = nums.length - 1
    while(l <= r) {
        const m = Math.floor((l + r) / 2)
        if(nums[m] == target) {
            return m
        } else if( target < nums[m]) {
            r = m - 1
        } else {
            l = m + 1
        }
    }
    return -1
};

翻轉鏈表

function ReverseList(pHead)
{
  let pre = null
  while(pHead) {
    const next = pHead.next
    pHead.next = pre
    pre = pHead
    pHead = next
  }
  return pre
}

sleep

function sleep(delay){
  return new Promise((resolve) => {
    setTimeout(resolve, delay)
  })
}

Emitter

class Emitter {
  constructor() {
    this.listeners = {}
  }
  addEventListener (name, fn) {
    this.on(name, fn)
  }
  on(name, fn) {
    if (name in this.listeners) {
      this.listeners[name].push(fn)
    } else {
      this.listeners[name] = [fn]
    }
  }
  emit(name, ...args) {
    const events = this.listeners[name]
    for(let i = 0; i < events.length; i++) {
      events[i](args)
    }
  }
  removeListener(name, fn) {
    const events = this.listeners[name] || []
    const i = events.indexOf(fn)
    if (~i) {
      events.splice(i, 1)
    }
  }
  once(name, listener) {
    const self = this
    const fn = function () {
      const args = Array.prototype.slice.call(arguments)
      listener.apply(null, args)
      self.removeListener(name, fn)
    }
    this.on(name, fn)
  }
}

實現兩個大數相加 IEEE754

function add(a ,b){
   //取兩個數字的最大長度
   let maxLength = Math.max(a.length, b.length);
   //用0去補齊長度
   a = a.padStart(maxLength , 0);//"0009007199254740991"
   b = b.padStart(maxLength , 0);//"1234567899999999999"
   //定義加法過程中需要用到的變量
   let t = 0;
   let f = 0;   //"進位"
   let sum = "";
   for(let i=maxLength-1 ; i>=0 ; i--){
      t = parseInt(a[i]) + parseInt(b[i]) + f;
      f = Math.floor(t/10);
      sum = t%10 + sum;
   }
   if(f == 1){
      sum = "1" + sum;
   }
   return sum;
}

深拷貝

function deepClone(raw) {
  const type = Object.prototype.toString.call(raw)
  if (type == '[object Number]' ||
    type == '[object String]' ||
    type == '[object Null]' ||
    type == '[object Undefined]'
  ) {
    return raw
  }
  let obj
  if(Array.isArray(raw)) {
    obj = []
    for(let i = 0; i < raw.length; i++) {
      obj[i] = deepClone(raw[i])
    }
    return obj
  } else {
    obj = {}
    Object.keys(raw).forEach(key => {
      obj[key] = deepClone(raw[key])
    })
    return obj
  }
}

回文字符串

function judge(str) {
  const mid = str.length % 2 ? (str.length + 1) / 2 : str.length / 2
  let start = 0;
  let end = str.length - 1
  let value = true
  for (let i = 0; i <= mid; i++) {
    if (str[start] == str[end]) {
      continue
    } else {
      value = false
    }
  }
  return value
}

手寫bind

function myBind (asThis) {
  const fn = this
  const slice = Array.prototype.slice
  const args = slice.call(arguments, 1)
  return function () {
    const args2 = slice.call(arguments)
    return fn.apply(asThis, args.concat(args2))
  }
}

手寫promise.all

function promiseAll (arr) {
  return new Promise((resolve, reject) => {
    const list = []
    if (arr.length < 1) {
      resolve([])
      return
    }
    for (let i = 0; i < arr.length; i++) {
      const item = arr[i]
      Promise.resolve(item).then(val => {
        list[i] = val
        if (i == arr.length) {
          resolve(list)
        }
      }).catch(e => {
        reject(e)
      })
    }
  })
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.下面代碼輸出是什么? 結果為 [1, 2, 3, 4, 5, empty × 5, 100]如果你為數組中的索...
    前端輝羽閱讀 1,351評論 0 15
  • 1 哪些操作會引起內存泄漏,如何發現 一些常見的內存泄露代碼 參考文章: https://juejin.im/po...
    不止前端閱讀 373評論 0 0
  • 1。Android的生命周期: onCreate(第一次被創建的時候調用) onStart(這個方法在活動由不可見...
    浮夸初衷閱讀 409評論 0 0
  • 1▲ Vue 中雙向數據綁定的實現原理是怎樣的?vue數據雙向綁定的原理是通過數據劫持結合發布訂閱模式,通過Obj...
    梁笨笨閱讀 455評論 0 1
  • JavaScript 筆試部分 實現防抖函數(debounce) 防抖函數原理:在事件被觸發 n 秒后再執行回調,...
    ERIC_s閱讀 171評論 0 0