前端手写面试题汇总--连载中

手写instanceof

function _instanceof (obj, constructor) {
    if(typeof obj !== 'object' || obj === null) return false
    let proto = Object.getPrototypeOf(obj)
    while (proto) {
      if(proto === constructor.prototype) {
        return true
      }
      proto = Object.getPrototypeOf(proto)
    }
    return false
  }

手写深拷贝

function deepClone (obj) {
    if(typeof obj !== 'object' || obj === null) return obj
    let newObj = Array.isArray(obj) ? [] : {}
    for(let key in obj) {
      if(obj[key] !== 'object' || obj[key] === null) {
        newObj[key] = deepClone(obj[key])
      } else {
        newObj[key] === obj[key]
      }
    }
    return newObj
  }

手写call

Function.prototype.Mycall = function (obj, ...args) {
    let context = obj || window
    let key = Symbol('key')
    obj[key] = this
    let res = obj[key](...arg)
    delete obj[key]
    return res
  }

手写防抖节流

// 手写防抖节流
  function debounce (time, fn) {
    let timer = null
    return function (...args) {
      let _this = this
      if(timer) clearTimeout(timer)
      timer = setTimeout(() => {
        fn.call(_this,...args)
      }, time);
    }
  }
  // 节流
  function throttle (time, fn) {
    let time = null
    let nowTime = 0
    return function (...args) {
      let _this = this
      let currentTime = +new Date()
      if(currentTime - nowTime > time) {
        fn.call(_this,...args)
        nowTime = currentTime
      }
    }
  }

手写继承

// 原型继承
function Parent (name) {
    this.name = name
    this.likes = ['yellow', 'blue', 'red']
    this.hellow = function () {
      console.log(`my name is ${this.name}`)
    }
  }
  function Child (name) {
    this.name = name
  }
  Child.prototype = new Parent()
  let c = new Child('xiaom')
  // 
  c.hellow()
  let c1 = new Child('xiaoh')
  console.log(c.likes)
  //缺点 c修改了父元素的属性 c1也会变化
  c.likes.push('pink')
  console.log(c1.likes)

  // 构造函数继承
  function Parent (name) {
    this.name = name
    this.likes = ['yellow', 'blue', 'red']
    this.hellow = function () {
      console.log(`my name is ${this.name}`)
    }
  }
  Parent.prototype.sayLikes = function () {
    console.log(`my like color  ${this.likes.join(',')}`)
  }
  function Child (name) {
    Parent.call(this)
    this.name = name
  }
  let c = new Child('xiaom')
  c.hellow()
  // 不会影响其他子类
  c.likes.push('pink')
  console.log(c.likes)
  let c1 = new Child('xiaoh')
  console.log(c1.likes)
  // 报错 缺点 不能继承父类原型上的属性和方法
  c.sayLikes()

// 组合式继承 -- 缺点父类会被调用2次
  function Parent (name) {
    this.name = name
    this.likes = ['yellow', 'blue', 'red']
    this.hellow = function () {
      console.log(`my name is ${this.name}`)
    }
  }
  Parent.prototype.sayLikes = function () {
    console.log(`my like color  ${this.likes.join(',')}`)
  }
  function Child (name) {
    Parent.call(this)
    this.name = name
  }
  Child.prototype = new Parent()
  let c = new Child('xiaom')
  c.hellow()
  // 不会影响其他子类
  c.likes.push('pink')
  console.log(c.likes)
  let c1 = new Child('xiaoh')
  console.log(c1.likes)
  c.sayLikes()

// 组合寄生式继承
  function Parent (name) {
    this.name = name
    this.likes = ['yellow', 'blue', 'red']
    this.hellow = function () {
      console.log(`my name is ${this.name}`)
    }
  }
  Parent.prototype.sayLikes = function () {
    console.log(`my like color  ${this.likes.join(',')}`)
  }
  function Child (name) {
    Parent.call(this)
    this.name = name
  }
  Child.prototype = Object.create(Parent.prototype)
  Child.constructor = Child
  let c = new Child('xiaom')
  c.hellow()
  // 不会影响其他子类
  c.likes.push('pink')
  console.log(c.likes)
  let c1 = new Child('xiaoh')
  console.log(c1.likes)
  c.sayLikes()

// class类继承
  class Parent {
    constructor (name) {
      this.name = name
    }
    say = function () {
      console.log(`my name is ${this.name}`)
    }
  }
  class Child extends Parent {
    constructor (name) {
      super(name)
      this.name = name
    }
  }
  let c = new Child('xiaom')
  c.say()

手写new

// 手写new操作符
  function _new (fn, ...args) {
    // 定义一个空对象
    let obj = {}
    // 空对象的__proto__ = 构造函数的prototype
    obj.__proto__ = fn.prototype
    // 执行构造函数 将新创建的对象作为构造函数的执行上下文
    let res = fn.call(obj, ...args)
    // 如果构造函数的返回值是一个对象则返回这个对象否则返回新创建的对象
    return (typeof res !== 'object' || res === null) ? obj : res
  }

手写promise

class MPromise  {
    constructor(fn) {
      this.val = ''
      this.reson = ''
      this.status = 'pending'
      this.onFulfilledCallback = []
      this.onRejectedCallback = []
      try {
        fn(this.resolve.bind(this), this.reject.bind(this))
      } catch (error) {
        this.reject(error)
      }
    }
    resolve(val){
      if(this.status === 'pending') {
        this.status = 'fulfilled'
        this.val = val
        this.onFulfilledCallback.forEach(item => item());
      }
    }
    reject (reson){
      if(this.status === 'pending') {
        this.status = 'rejected'
        this.reson = reson
        this.onRejectedCallback.forEach(item => item());
      }
    }
    then (onFulfilled, onRejected) {
      let p = new MPromise((resolve, reject)=>{
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : ()=>{}
        onRejected = typeof onRejected === 'function' ? onRejected : ()=>{}
          if(this.status === 'rejected'){
            setTimeout(() => {
              try {
                let x = this.onRejected(this.reson)
                this.resolvePromise(p, x,resolve, reject)
              } catch (error) {
                this.reject(error)
              }
            });
          }
          if(this.status === 'fulfilled'){
            setTimeout(() => {
              try {
                let x = this.onFulfilled(this.val)
                this.resolvePromise(p, x,resolve, reject)
              } catch (error) {
                this.reject(error)
              }
            });
          }
          if(this.status === 'pending') {
            this.onFulfilledCallback.push(()=>{
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.val)
                  this.resolvePromise(p, x,resolve, reject)
                } catch (error) {
                  this.reject(error)
                }
              });
            })
            this.onRejectedCallback.push(()=>{
              setTimeout(() => {
                try {
                  let x = onRejected(this.reson)
                  this.resolvePromise(p, x,resolve, reject)
                } catch (error) {
                  this.reject(error)
                }
              });
            })
          }
      })
      return p
    }
    resolvePromise (p,x,resolve,reject) {
      // 如果p和x相同报错
      if(p === x) {
        return reject(new TypeError('Chaining cycle detected for promise'));
      }
      if(x !== null && (typeof x==='object' || typeof x==='function')){
        try {
          let then = x.then
          if(typeof then ==='function') {
            then.call(x, y=>{
              resolvePromise(p, y, resolve, reject);
            },r =>{
              reject(r)
            })
          }else{
            resolve(x)
          }
        } catch (error) {
          reject(error)
        }
      }else[
        resolve(x)
      ]
    }
    catch (onRejected) {
      onRejected = typeof onRejected === 'function' ? onRejected : ()=>{}
      return this.then(undefined, onRejected)
    }
    static all (promises) {
      let result = []
      let index
      return new MPromise((resolve, reject)=>{
        function addData(key, value) {
          result[key] = value
          index++
          if(index === array.length) {
            resolve(result)
          }
        }
        for(let i = 0; i < promises.length; i++) {
          let current = promises[i]
          if(current instanceof MPromise) {
            current.then(value => addData(i, value), reason => reject(reason))
          } else {
            addData(i, promises[i])
          }
        }
      })
    }
    static  race (promises) {
      return new MPromise((resolve, reject)=>{
        for(let i = 0; i < promises.length; i++) {
          let current = promises[i]
          if(current instanceof MPromise) {
            current.then(value => resolve(value), reason => reject(reason))
          } else {
            resolve(current)
          }
        }
      })
    }
    static  any (promises) {
      let result = []
      let index
      return new MPromise((resolve, reject)=>{
        function addData(key, value) {
          result[key] = value
          index++
          if(index === array.length) {
            reject(result)
          }
        }
        for(let i = 0; i < promises.length; i++) {
          let current = promises[i]
          if(current instanceof MPromise) {
            current.then(value => resolve(value), reason => addData(i, reason))
          } else {
            resolve(promises[i])
          }
        }
      })
    }
    static  allSettled () {
      let result = []
      let index
      return new MPromise((resolve, reject)=>{
        function addData(key, value) {
          result[key] = value
          index++
          if(index === array.length) {
            resolve(result)
          }
        }
        for(let i = 0; i < promises.length; i++) {
          let current = promises[i]
          if(current instanceof MPromise) {
            current.then(value => addData(i, value), reason => addData(i, reason))
          } else {
            addData(i, promises[i])
          }
        }
      })
    }
    finally (callback) {
      return this.then((val)=>{
        return MPromise.resolve(callback()).then(()=>val)
      },(reason)=>{
        return MPromise.reject(callback()).then(()=>{ throw reason})
      })
    }
    static resolve(value) {
      if(value instanceof MPromise) return value
      return new MPromise(resolve => resolve(value))
    }
    static reject(reason) {
      return new MPromise((resolve, reject) => reject(value))
    }
  }

手写一个单例

// 手写一个单例
  class Single{
    constructor () {
      this.instance = null
    }
    static getInstance =  (...args) => {
        if(!this.instance) {
          this.instance = new Single(...args)
        }
        return this.instance
      }
  }

手写一个发布订阅

class eventEmit {
    constructor() {
      this.events = {}
    }
    on (key, fn, isOnce) {
      if(this.events.hasOwnProperty(key)){
        this.events[key].push({fn, isOnce})
      } else {
        this.events[key] = [{fn, isOnce}]
      }
    }
    once (key, fn) {
      this.on(key, fn, true)
    }
    off(key, fn){
      if(!fn){
        this.events[key] = []
      } else{
        if(this.events.hasOwnProperty(key)){
          this.events[key] = this.events[key].filter((item) => item.fn === fn)
        }
      }
    }
    emit (key, ...args) {
      if(this.events.hasOwnProperty(key)){
        this.events[key] = this.events[key].filter((item) => {
          item.fn(...args)
          return !item.isOnce
        })
      }
    }
  }

手写一个观察者

 // 手写观察者
  // 被观察者
  class Student {
    constructor(name, status) {
      this.name = name
      this.observes = []
      this.status = status
    }
    // 添加观察者
    addObserve (obj) {
      this.observes.push(obj)
    }
    // 移除观察者
    removeObserve (obj) {
      this.observes = this.observes.filter((item) =>  item !== obj)
    }
    updateStatus (status) {
      this.observes.forEach(item => {
        item.notify(this.name, this.status, status)
      })
      this.status = status
    }
  }
  class Observer {
    constructor(name) {
      this.name = name
    }
    // 通知
    notify (name, status, newStatus) {
      console.log(`${this.name} 您好 ${name} 的状态由是 ${status} 变为 ${newStatus}`)
    }
  }
  let s = new Student('小明', 'happay')
  let t = new Observer('小明老师')
  let p = new Observer('小明爸爸')
  s.addObserve(t)
  s.addObserve(p)
  s.updateStatus('bad')

手写一个常用的loader

 // 手写一个常用的loader
  module.exports = function (countent) {
    // loader 分为 pre normal inline post loader 执行顺序从下往上 从右往左
    // loader 有同步 异步 和 row
    // 可以做一些操作 例如 style-loader
    let str = `
      let style = document.createElement('style')
      style.innerHTML = ${JSON.stringify(content)}
      document.head.appendChild(style)
    `
    return str
  }

手写一个常用的plugin

 // 手写一个常用的plugin
  class AnalyzeWbpackPlugin {
    constructor(parameters) {
      
    }
    apply (compiler) {
      let str = `| fileName | size | 
                  | --- | --- |`
      compiler.hooks.emit.tap('AnalyzeWbpackPlugin', (compliactiong)=>{
        const arr = []
        Object.keys(compliactiong.assets).forEach((fileName)=>{
          const file = compliactiong.assets[fileName]
          const obj = {fileName, size:  Math.ceil(file.size() / 1024)}
          arr.push(obj)
        })
        arr.sort((a,b) => {
          return b.size - a.size
        })
        arr.forEach((item) => {
          let {fileName, size} = item
          let s = `| ${fileName} | ${size}kb |`
          str += s + '\n'
        })
        compliactiong.assets['analyze.md'] = {
          source(){
            return str
          },
          size () {
            return str.length
          }
        }
      })
    }
  }
  moudle.exports = AnalyzeWbpackPlugin

手写一个基本的webpack配置

const {reslove} = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = function () {
  return {
    entry: reslove(__dirname, '../src/main.js'),
    output: {
      path: reslove(__dirname, '../dist'),
      fileName: "static/js/[name].[fullhash:8].js",
      clear: true
    },
    module: {
      rules: [
        {
          test: /\.(js)$/,
          use: {
            loader: "babel-loader"
          }
        },
        {
          test: /\.(css|less)$/,
          use: {
            loader: "style-loader",
            loader: "css-loader",
            loader: "postcss-loader",
            loader: "less-loader"
          }
        },
        {
          test: /\.(png|jpeg|jpg|gif|webp|svg)$/,
          generator: {
            filename: "static/images/[name].[contenthash:8][ext]"
          }
        }
      ]
    },
    plugin:[
      new HtmlWebpackPlugin({
        template: reslove(__dirname, "../public/index.html"),
        inject: true
      })
    ]
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值