JavaScript 常见面试题-手写代码篇

本文探讨JavaScript面试中的常见问题,包括手写call、apply、bind的实现,Promise封装AJAX,函数节流、防抖,函数柯里化,深浅拷贝,字符串和数组操作等实战技巧。通过实例解析,帮助你巩固JavaScript基础和提升面试技巧。

Github:https://github.com/ChenMingK/WebKnowledges-Notes
推荐在线阅读:https://www.kancloud.cn/chenmk/web-knowledges/1077426

实现 call、apply、bind

实现 call

首先要明白 call 是干什么的:call 方法在使用一个指定的 this 和若干个指定的参数值的前提下调用某个函数或方法

① 如何改变 this 指向?

  • 将函数设置为对象的属性
  • 执行该函数
  • 删除该函数

delete 运算符可以删除对象的属性,但是不能删除一个变量或者函数

② 如何把参数传给要执行的函数并使其执行,且传入的参数个数是不确定的?

  • 运用 rest 运算符,或者使用 arguments 对象
Function.prototype.call2 = function (context, ...args) {
   
   
  // 首先要获取调用 call 的函数,用 this 可以获取
  context.fn = this
  context.fn(...args)
  delete context.fn // delete 删除对象的属性
}

let foo = {
   
   
  value: 1
}

function bar(name, age) {
   
   
  console.log(name)
  console.log(age)
  console.log(this.value)
}

bar.call2(foo, 'kevin', 18) // kevin 18 1

实现 apply

和 call 基本一样,只是参数变为数组了而已

Function.prototype.apply2 = function (context, arr) {
   
   
  // 首先要获取调用 call 的函数,用 this 可以获取
  context.fn = this
  context.fn(...arr)
  delete context.fn // delete 删除对象的属性
}

let foo = {
   
   
  value: 1
}

function bar(name, age) {
   
   
  console.log(name)
  console.log(age)
  console.log(this.value)
}

bar.apply2(foo, ['kevin', 18]) // kevin 18 1

实现 bind

首先也是搞明白 bind 的作用是什么:bind() 方法会创建一个新函数,当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,传递参数时,
可以在 bind 时传递部分参数,调用时又传递其余参数

完整的 bind 还考虑了:一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当成构造器。
提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。

下面的代码只实现 bind 的部分功能:

Function.prototype.myBind = function (context, ...args1) {
   
   
  if (typeof this !== 'function') {
   
    // 只允许函数调用 bind 方法
    throw new Error('Error')
  }
  let self = this
  let firstArgs = args1
  
  return function (...args2) {
   
   
    return self.apply(context, firstArgs.concat(args2))
  }
}

更完整的 bind 实现参考:https://github.com/mqyqingfeng/Blog/issues/12

Promise 封装原生 AJAX

let AJAX = function (url) {
   
   
  let promise = new Promise(function (resolve, reject) {
   
   
    let XHR = new XMLHttpRequest()
    XHR.open('get', url, false) // false:异步 true:同步
    XHR.onreadystatechange = handler
    XHR.send()

    function handler() {
   
   
      if (XHR.readyState !== 4) {
   
   
        return 
      }
      if (XHR.status === 200) {
   
   
        resolve(XHR.response)
      } else {
   
   
        reject(new Error(XHR.statusText))
      }
    }
  })
  return promise
}

XMLHttpRequest 的一些属性和方法可参考:AJAX 整理

函数节流、防抖 + immediate版

参考 https://github.com/mqyqingfeng/Blog/issues/22

防抖和节流的作用都是防止函数多次调用,区别在于,假设一个用户一直触发这个函数,且每次触发函数的时间间隔小于 wait,
防抖的情况下只会调用一次,而节流的情况会每隔一定时间调用函数

// 防抖
function debounce(fn, wait) {
   
   
  let timer = 0
  return function (...args) {
   
   
    if (timer) clearTimeout(timer) // 清除并重新设置定时任务
    timer = setTimeout(() => {
   
   
      fn.apply(this, args)
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值