几道常考的手写面试题

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 手写实现Array.prototype.map
    function map(arr, mapCallback) {
      // 首先检查传递的参数是否正确
      if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
        return []
      } else {
        // 每次调用此函数时,我们都会创建一个 result 数组
        // 因为我们不想改变原始数组。
        let result = []
        for (let i = 0; i < arr.length; i++) {
          result.push(mapCallback(arr[i], i, arr))
        }
        return result
      }
    }


    // 手动实现Array.prototype.filter
    function filter(arr, filterCallback) {
      if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
        return []
      } else {
        // 每次调用此函数时,我们都会创建一个 result 数组
        // 因为我们不想改变原始数组。
        let result = []
        for (let i = 0; i < arr.length; i++) {
          // 检查 filterCallback 的返回值是否是真值
          if (filterCallback(arr[i], i, arr)) {
            // 如果条件为真,则将数组元素 push 到 result 中
            result.push(arr[i])
          }
        }
        return result
      }
    }

    // 手写实现reduce
    function reduce(arr, reduceCallback, initialValue) {
      if (!Array.isArray(arr) || !arr.length || typeof reduceCallback !== 'function') {
        return []
      } else {
        // 如果没有将initialValue传递给该函数,我们将使用第一个数组项作为initialValue
        let hasInitialValue = initialValue !== undefined
        let value = hasInitialValue ? initialValue : arr[0]
        // 如果有传递 initialValue,则索引从 1 开始,否则从 0 开始
        for (let i = hasInitialValue ? 0 : 1; i < arr.length; i++) {
          value = reduceCallback(value, arr[i], i, arr)
        }
        return value
      }
    }

    // 深拷贝
    function deepCopy(newObj, oldObj) {
      for (let k in oldObj) {
        var item = oldObj[k]
        // 判断数组
        if (item instanceof Array) {
          newObj[k] = []
          deepCopy(newObj[k], item)
          // 判断对象
        } else if (item instanceof Object) {
          newObj[k] = {}
          deepCopy(newObj[k], item)
        } else {
          newObj[k] = item
        }
      }
    }

    // 手写实现call
    Function.prototype.myCall = function (context) {
      // 判断调用对象
      if (typeof this !== 'function') {
        console.error('type error')
      }
      // 获取参数
      let args = [...arguments].slice(1)
      result = null
      // 判断context是否传入,如果为传入,设置成window
      context = context || window
      // 将调用函数设置成对象的方法
      context.fn = this
      // 调用函数
      result = context.fn(...args)
      // 将属性删除
      delete context.fn
      return result
    }


    // 手写实现apply
    Function.prototype.myApply = function (context) {
      if (typeof this !== 'function') {
        console.error('type error')
      }
      context = context || window
      let result = null
      context.fn = this
      // 调用方法
      if (arguments[1]) {
        result = context.fn(...arguments[1])
      } else {
        result = context.fn()
      }
      delete context.fn
      return result
    }
    // 手写实现bind
    Function.prototype.myBind = function (context) {
      // 判断调用对象是否为函数
      if (typeof this !== "function") {
        throw new TypeError("Error");
      }
      // 获取参数
      var args = [...arguments].slice(1)
      fn = this
      return function Fn() {
        // 根据调用方式,返回不同的值
        return fn.apply(this instanceof Fn ? this : context, args.concat(...arguments))
      }
    }


    // 函数柯理化
    // 是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
    function curry(fn, args) {
      let length = fn.length
      args = args || []
      return function () {
        let subArgs = args.slice(0)
        // 拼接得到的所有参数
        for (let i = 0; i < arguments.length; i++) {
          subArgs.push(arguments[i])
        }
        // 判断参数长度是否满足函数所需参数的长度
        if (subArgs.length >= length) {
          // 执行函数
          return fn.apply(this, subArgs)
        } else {
          return curry.call(this, fn, subArgs)
        }
      }
    }

    // ES6实现
    function curry(fn, args) {
      return fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args)
    }


    // 快速排序
    function quickSort(arr) {
      if (arr.length <= 1) {
        return arr
      }
      const cIndex = Math.floor(arr.length / 2)
      const index = arr.splice(cIndex, 1)
      var l = []
      var r = []
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] < index) {
          l.push(arr[i])
        } else {
          r.push(arr[i])
        }
      }
      return quickSort(l).concat(index, quickSort(r))
    }
    console.log(quickSort([1, 8, 4, 6, 5, 9, 2, 3, 15, 45])); // (10) [1, 2, 3, 4, 5, 6, 8, 9, 15, 45]


    // 冒泡排序
    function mySort(arr) {
      if (arr == null || arr.length <= 1) {
        return arr
      }
      for (var i = 0; i < arr.length - 1; i++) {
        var done = true
        for (var j = 0; j < arr.length - 1 - i; j++) {
          if (arr[j] > arr[j + 1]) {
            var temp = arr[j]
            arr[j] = arr[j + 1]
            arr[j + 1] = temp
            done = false
          }
        }
        if (done) {
          break
        }
      }
      return arr
    }
    alert(mySort([1, 5, 4, 6, 8, 3, 2]))

    // 深拷贝
    function deepClone(newObj, oldObj) {
      for (let k in oldObj) {
        let item = oldObj[k]
      }
      if (item instanceof Array) {
        newObj[k] = []
        deepClone(newObj[k], item)
      } else if (item instanceof Object) {
        newObj[k] = {}
        deepClone(newObj[k], item)
      } else {
        newObj[k] === item
      }
    }
    // 手写Promise
    function myPromise(constructor) {
      let self = this;
      self.status = 'Pending'
      self.value = undefined
      self.reason = undefined
      function resolve(value) {
        if (self.status === 'Pending') {
          self.value = value
          self.status = 'resolved'
        }
      }
      function reject(reason) {
        if (self.status === 'Pending') {
          self.reason = reason
          self.status = 'rejected'
        }
      }
      try {
        constructor(resolve, reject)
      } catch (e) {
        reject(e)
      }
    }
    myPromise.prototype.then = function (onFulfilled, onRejected) {
      let self = this
      switch (self.status) {
        case 'resolved':
          onFulfilled(self.value)
          break
        case 'rejected':
          onRejected(self.reason)
          break
        default:
      }
    }

    // instanceof  原理
    function myInstanceof(left, right) {
      let prototype = right.prototype
      left = left.__proto__
      while (true) {
        if (left === null || left === undefined)
          return false
        if (prototype === left)
          return true
        left = left.__proto__
      }
    }

    // 函数节流
    function throttle(fn, delay) {
      var preTime = Data.now()
      return function () {
        var context = this
        args = arguments
        nowTime = Data.now()
        if (nowTime - preTime > delay) {
          preTime = Data.now()
          return fn.apply(context, args)
        }
      }
    }
    // 函数防抖
    function debounce(fn, wait) {
      var timer = null
      return function () {
        var context = this
        args = arguments
        if (timer) {
          clearTimeout(timer)
          timer = null
        }
        timer = setTimeout(() => {
          fn.apply(context, args)
        }, wait)
      }
    }


  </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值