前端经验:快速解决前端代码面试题(四)

开课吧开课吧科科2021-02-23 10:20

作为一名前端工程师,总是少不了面试找工作。很多人为面试头疼,曾经的我也是。在准备面试的过程中,我开始整理出了一些有用的笔记,这篇就是其中之一。既然已经写好了,不妨就放在这里分享给大家,希望大家都能顺利找到理想的工作。

我说一下我的建议,首先在面试中的写代码的过程,一定不能紧张,要沉住气慢慢来。只要不是系统自动检查结果,只要是面试官看着你写,就有很大的表现的机会,哪怕最后做不出来。

作为一个专业的程序员,除了工作中的编码,额外的无实际产出的练习(反复练习解决一个问题,反复默写同一段代码),也是必不可少的。

下文中几乎每一段代码,都是我反复优化后的结果,希望可以带给读者新的启发。我把代码大致分成了几个专题,一共包含了大致30个问题的解决方案,我今天来分享的是前端工作中经常遇到的功能函数实现、防抖节流、数据结构、设计模式。上一章分享的是功能函数实现、防抖节流及数据结构,感兴趣的可以点击“前端经验:快速解决前端代码面试题(三)”查阅。

Web前端经验

JS原生API实现

bind() call() apply()

apply()

Function.prototype.myApply=function(context,args) {

 context.fn=this//为context设置函数属性

 let result=context.fn(...args)//调用函数

 delete context.fn//删除context的函数属性

 return result

}

call()

//除了...args

//和apply都一样

Function.prototype.myCall=function(context,...args) {

 context.fn=this

 let result=context.fn(...args)

 delete context.fn

 return result

}

bind()

Function.prototype.myBind=function(context,args1) {//使用[闭包+apply]实现

 return (...args2)=>this.apply(context,[...args1,...args2]);

}

InstanceOf

function myInstanceOf(son,father) {//沿着父亲的原型链向上查找是否有儿子的原型

 while (true) {

  son=son.__proto__

  if (!son) return false

  if (son===father.prototype) return true

 }

}

 

myInstanceOf([], Array)  // true

new

function myNew(constructor_fn,...args) {

 //构造新的空对象

 let new_obj={}

 new_obj.__proto__=constructor_fn.prototype

 let result=constructor_fn.apply(new_obj,args)

 //如果构造函数没有返回一个对象,则返回新创建的对象

 //如果构造函数返回了一个对象,则返回那个对象

 //如果构造函数返回原始值,则当作没有返回对象

 return result instanceof Object?result:new_obj

}

function Animal(name) {

  this.name = name;

}

let animal = myNew(Animal, 'dog');

console.log(animal.name)  // dog

reduce() forEach()

reduce()

api用法:

arr.reduce(function(prev, cur, index, arr){}, initialValue)

实现:

Array.prototype.myReduce=function(fn,init_val){

 let [val,idx]=init_val?[init_val,0]:[this[0],1]//设置初始值

 for (let i=idx,len=this.length;i<len;i++) {

  val=fn(val,this[i],i,this)//循环并迭代结果

 }

 return val

}

console.log([1,2,3,4,5].reduce((pre,item)=>pre+item,0)) // 15

forEach()

api用法:

[1,3,5,7,9].myForEach(function(item,index,arr) {

    console.log(this)

},15)

实现:

Array.prototype.myForEach=function(fn,temp_this) {

    for (let i=0,len=this.length;i<len;i++){

        fn.call(temp_this,this[i],i,this)//循环数组元素,为回调函数传入参数

    }

}

Promise

Promise.all()

Promise.prototype.all=function(promiseList) {

    return new Promise((resolve,reject)=>{

        if (promiseList.length===0) return resolve([])

        let result=[],count=0

        promiseList.forEach((promise,index)=>{

            Promise.resolve(promise).then(value=>{

                result[index]=value

                if (++count===promiseList.length) resolve(result)

            },reason=>reject(reason))

        })

    })

}

ES6所有API完整实现

通过Promise/A+ test测试

实现细节过多,还请参照Promise/A+规范阅读

也可以直接参考我关于promise的笔记

深入理解promise

https://blog.csdn.net/weixin_43758603/article/details/109641486

class Promise {

 constructor(task) {

  this.status="pending"

  this.value=undefined

  this.reason=undefined

  this.fulfilled_callbacks=[]

  this.rejected_callbacks=[]

  try {

   task(this._resolve,this._reject)

  } catch (error) {

   this._reject(error)

  }

 }

 then(onFulfilled,onRejected){

  if (this.status==='fulfilled') {

   let promise2=new Promise((resolve,reject)=>{

    setTimeout(()=>{

     try {

      if (!this._isFunction(onFulfilled)) {

       resolve(this.value)

      } else {

       this._resolvePromise(promise2,onFulfilled(this.value))

      }

     } catch (error) {

      reject(error)

     }

    },0)

   })

   return promise2

  } else if (this.status==='rejected') {

   let promise2=new Promise((resolve,reject)=>{

    setTimeout(()=>{

     try {

      if (!this._isFunction(onRejected)) {

       reject(this.reason)

      } else {

       this._resolvePromise(promise2,onRejected(this.reason))

      }

     } catch (error) {

      reject(error)

     }

    },0)

   })

   return promise2

  } else if (this.status==='pending')  {

   let promise2=new Promise((resolve,reject)=>{

    this.fulfilled_callbacks.push(()=>{

     try {

      if (!this._isFunction(onFulfilled)) {

       resolve(this.value)

      } else {

       this._resolvePromise(promise2,onFulfilled(this.value))

      }

     } catch (error) {

      reject(error)

     }

    })

    this.rejected_callbacks.push(()=>{

     try {

      if (!this._isFunction(onRejected)) {

       reject(this.reason)

      } else {

       this._resolvePromise(promise2,onRejected(this.reason))

      }

     } catch (error) {

      reject(error)

     }

    })

   })

   return promise2

  }

 }

 catch=onRejected=>this.then(null,onRejected)

 

 finally=onFinished=>this.then(onFinished,onFinished)

 static deferred(){

  let deferred={}

  deferred.promise=new Promise((resolve,reject)=>{

   deferred.resolve=resolve

   deferred.reject=reject

  })

  return deferred

 }

 static resolve(value) {

  if (value instanceof Promise) return value

  return new Promise(resolve=>resolve(value))

 }

 static reject=reason=>{return new Promise((resolve, reject)=>reject(reason))}

 static all(promiseList) {

  return new Promise((resolve,reject)=>{

   if (promiseList.length===0) return resolve([])

   let result=[],count=0

   promiseList.forEach((promise,index)=>{

    Promise.resolve(promise).then(value=>{

     result[index]=value

     if (++count===promiseList.length) resolve(result)

    },reason=>reject(reason))

   })

  })

 }

 static race(promiseList) {

  return new Promise((resolve,reject)=>{

   if (promiseList.length===0) return resolve()

   promiseList.forEach(promise=>{

    Promise.resolve(promise)

     .then(value=>resolve(value),reason=>reject(reason))

   })

  })

 }

 static allSettled(promiseList) {

  return new Promise(resolve=>{

   let result=[],count=0

   if (len===0) return resolve(result)

   promiseList.forEach((promise,i)=>{

    Promise.resolve(promise).then(value=>{

     result[i]={

      status:'fulfilled',

      value:value

     }

     if (++count===promiseList.length) resolve(result)

    },reason=>{

     result[i]={

      status:'rejected',

      reason:reason

     }

     if (++count===promiseList.length) resolve(result)

    })

   })

  })

 }

 _resolve=value=>{

  if (this.status!=='pending') return

  setTimeout(()=>{

   this.status ='fulfilled'

   this.value = value

   this.fulfilled_callbacks.forEach(cb=>cb(this.value))

  },0)

 }

 _reject=reason=>{

  if (this.status!=='pending') return

  setTimeout(()=>{

   this.reason = reason

   this.status ='rejected'

   this.rejected_callbacks.forEach(cb=>cb(this.reason))

  },0)

 }

 _isFunction=f=>Object.prototype.toString.call(f).toLocaleLowerCase()==='[object function]'

 _isObject=o=>Object.prototype.toString.call(o).toLocaleLowerCase()==='[object object]'

 _resolvePromise(promise,x){

  if (promise===x) {

      promise._reject(new TypeError('cant be the same'))

      return

  }

  if (x instanceof Promise) {

   if (x.status==='fulfilled') {

    promise._resolve(x.value)

   } else if (x.status==='rejected') {

    promise._reject(x.reason)

   } else if (x.status==='pending') {

    x.then(value=>{

     this._resolvePromise(promise,value)

    },reason=>{

     promise._reject(reason)

    })

   }

   return

  }

  if (this._isObject(x)||this._isFunction(x)) {

   let then

   try {

    then=x.then

   } catch (error) {

    promise._reject(error)

    return

   }

   if (this._isFunction(then)) {

    let called=false

    try {

     then.call(x,value=>{

      if (called) return

      called=true

      this._resolvePromise(promise,value)

     },reason=>{

      if (called) return

      called=true

      promise._reject(reason)

     })

    } catch (error) {

     if (called) return

     promise._reject(error)

    }

   } else {

    promise._resolve(x)

   }

  } else {

   promise._resolve(x)

  }

 }

}

module.exports = Promise

以上内容就是开课吧广场小编今天分享的“前端经验:快速解决前端代码面试题(四)”一文,希望为准备面试的朋友提供参考,顺利通过面试,找到理想工作。更多前端经验分享及前端面试题尽在开课吧广场Web前端面试题频道!

上一篇:前端经验:快速解决前端代码面试题(五)下一篇: 精选web前端开发面试题

最新文章

文章图0

2021年精选前端面试题

Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点:(1)对象的状态不受外界影响。(2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。

2021-03-04 15:31:35

文章图1

前端面试题:Javascript中的DOM是什么?

DOM是文档对象模型,它是网站的面向对象的表示形,可以使用Javascript进行修改。 使用JS可以操纵DOM元素,例如颜色,位置,大小。为了选择页面的特定元素,Javascript提供了一些方法:

2021-03-04 14:54:32

文章图2

Web前端面试官会问什么?

如何进行:如何XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到Web页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

2021-03-02 16:23:09

文章图3

前端免费资料大放送

前端开发是从网页制作演变而来,早期的网页制作主要内容都是静态的,以文字图片为主,用户使用网站也以浏览为主。随着互联网的发展,现代网页更加美观,交互效果更加显著,

2021-03-01 15:04:23

文章图4

精选前端开发面试题

方法1,通过回调函数。优点是简单、容易理解和部署;缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程混乱,而且每个任务只能指定一个回调函数。

2021-02-26 17:38:45