反复刷这些javascript面试手写题,我感觉我真的变强了

Posted 阿锋不知道丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反复刷这些javascript面试手写题,我感觉我真的变强了相关的知识,希望对你有一定的参考价值。

用正则能实现的手写题

前段时间刚好复习了正则,所以把正则的写前面

实现千分位分隔符

题目描述:实现将一个数从各位数开始,每距离一个千分位添加一个分割符 ‘ ,’
如输入: 12345678.32423432
输出:12,345,678.32423432

这道题在最近一两个月的面试中遇到两次,可以分别有字符串和数组的一些方法结合解决,也可以用正则解决,我觉得正则可能更难以理解

第一种方法:


const num = 12345678.32423432

function getForm(num) {
  let arr = num.toString().split('.')
  // 取出整数部分
  let arr0 = arr[0].split('')
  // console.log(arr0);
  let stack = []
  let i = 0
  while (arr0.length > 0) {
    // 没3位添加一个分割符
    if (i % 3 == 0 && i !== 0) {
      stack.push(',')
    }
    stack.push(arr0.pop())
    i++
  }
  let res = stack.reverse()
  console.log(res);
  // 考虑是否存在小数部分
  if (arr[1]) {
    return res.join('') + '.' + arr[1]
  } else {
    return res.join('')
  }
}

console.log(getForm(num));

第二种方法用正则解决:

function regForm(num) {
  // console.log(num.toString());
  return num.toString().replace(/\\d+/, (p) => {
    return p.replace(/\\d(?=(\\d{3})+$)+/g, (p1, p2) => {
      return p1 + ','
    })
  })
}

实现一个trim()

实现string原型上的trim()方法:
解决方法有很多,我常用的是下面这两个

String.prototype.my_trim = function () {
  return this.replace(/^\\s+/, '').replace(/\\s+$/, ' ')
}

String.prototype.trim = function() {
  return  this.replace(/^\\s+|\\s+$/g, '');
}

取出连续重复的字符

取出 :'sadddddddddddddsssssssssssssdddddddasddd’重复的字符
最终为 [“ddddddddddddd”, “sssssssssssss”, “ddddddd”, “ddd”]

面试腾讯暑期实习生遇到此题,我当时真的菜没做出来,回过头来发现真简单


let a = 'sadddddddddddddsssssssssssssdddddddasddd'

console.log(a.match(/([a-z])\\1+/ig));

解析url参数为对象形式

const url = 'http://www.baidu.com/we/index.html?id=098&aaa=123&ccc=456'


function parseParam(url) {
  let arr = url.split('?')[1].split('&')
  console.log(arr);
  let obj = {}
  arr.forEach(item => {
    console.log(item.split('='));
    let [key, value] = item.split('=')
    if (/^\\d+$/.test(value)) {
      value = parseInt(value)
    }
    obj[key] = value
  })
  return obj

}

console.log(parseParam(url));

在这里插入图片描述

关于闭包的手写题

自我感觉这部分的手写题能够全部理解的话,对于闭包的理解会更加深刻

利用高阶函数实现函数缓存

高阶函数应该就是输入参数是函数,返回也是一个函数

var add = function (a) {
  return a + 1
}


function memo(fn) {
  const cache = {}
  return function (...ret) {
    let key = JSON.stringify(ret)
    return cache[key] || (cache[key] = fn.apply(fn, [...ret]))
  }
}

const adder = memo(add)
console.log(adder);
console.log(adder(1));
console.log(adder(1));
console.log(adder(3));
console.log(adder(3));

在这里插入图片描述

手写call,apply,bind

这几个函数只有把手写学会才会理解的更深刻

点击查看详细解说分别手写call,apply,bind

柯里化-实现实现一个add(1)(2)(3)

具体要求就是能使本来函数add(1,2,3)变成add(1)(2)(3)

具体思路就是将参数用递归的方式一个一个的传入目标函数

function curry(fn, args) {
  var ofArgs = args || []
  var len = fn.length
  var self = this
  // 
  return function (...ret) {
    // ret是后面传入的函数
    var currentArg = [...ofArgs, ...ret]
    console.log(currentArg);
    // 如果当前参数数组的长度小于fn的要求长度  那么继续递归
    if (len > currentArg.length) {
      return curry.call(self, fn, currentArg)
    }
    return fn.apply(self, currentArg)
  }
}

const add = function (a, b, c) {
  return a + b + c
}

const newFn = curry(add)

// newFn(1)(2)(3)
console.log(newFn(1)(2)(3));

在这里插入图片描述

防抖和节流

防抖和节流

关于对象

手写深拷贝

拷贝一个地址不同其他完全相同的对象

function deepClone(obj) {

  if (typeof obj !== 'object') {
    return obj
  }
  let res

  // 数组和对象的限定
  if (Array.isArray(obj)) {
    res = []
  } else {
    res = {}
  }

  //一层层递归赋值
  for (let key in obj) {
    console.log(key);
    if (obj.hasOwnProperty(key)) {
      res[key] = obj[key]
    }
  }
  return res
}

let book = {
  name: "局外人",
  types: {
    t1: "中文版",
    t2: "英文版",
    a: {
      c: 2
    }
  }
}
5


let book_clone = deepClone(book)
console.log(book_clone === book);
console.log(book_clone);

手写深度比较

深度比较两个对象的值是否完全相同

function isEqual(obj1, obj2) {
  // 判断两个是不是对象
  if (typeof obj1 !== 'object' && typeof obj2 !== 'object'
    && obj1 !== null && obj2 !== null) {
    return obj1 === obj2
  }

  if (obj1 === obj2) {
    return true
  }
  // 先取出obj1和obj2的keys,比较个数
  let leng1 = Object.keys(obj1).length
  let leng2 = Object.keys(obj2).length
  // console.log(leng1);
  if (leng1 !== leng2) {
    return false
  }
  // 以obj1为基准和obj2递归比较
  for (let key in obj1) {
    const res = isEqual(obj1[key], obj2[key])
    if (!res) {
      return false
    }
  }

  return true
}

const obj1 = {
  a: 2,
  b: 'a',
  c: {
    e: 'f',
    f: 's'
  }
}

const obj2 = {
  a: 2,
  b: 'a',
  c: {
    e: 'f',
    f: 's',
    // a: 41
  }

}

console.log(isEqual(obj1, obj2));



关于数组

数组去重

最简单的去重:用set


var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));
// 注意Set是能够去掉NaN的重复的

// [...new Set(arr)]

function unique(arr) {
  return Array.from(new Set(arr))
}

在这里插入图片描述
使用indexOf无法去除 NaN的重复 indexOf(NaN)永远等于-1


var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));


function unique(arr) {
  if (!Array.isArray(arr)) {
    {
      console.log('is nor a array');
    }
  }
  const res = []
  arr.forEach(element => {
    if (res.indexOf(element) === -1) {
      res.push(element)
    }
  });
  return res
}

在这里插入图片描述

includes也是能够去掉NaN的重复的


var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));

function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('is not array')
  }
  const new_arr = []
  arr.forEach(e => {
    if (!new_arr.includes(e)) {
      new_arr.push(e)
    }
  })

  return new_arr
}

在这里插入图片描述

splice使用此函数特别需要注意的一点:会改变数组,改变数组的长度

var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));


function unique(arr) {
  let len = arr.length
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arr[i] == arr[j]) {
        //       console.log(arr);
        arr.splice(j, 1)
        // console.log(arr);
        j--;
      }
    }
  }
  return arr
}

用filter+hasOwnProperty两个空对象也能去重

var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));

function unique(arr) {
  var obj = {};
  return arr.filter(function (item, index, arr) {
    console.log(item);
    console.log(typeof item + item);
    // console.log(obj[typeof item + item]);
    // 判断obj对象是否有这个属性,如果有(说明数组元素重复)直接返回false过滤掉数组中的重复元素
    // 如果没有,为obj对象添加上这个属性
    return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
  })
}

在这里插入图片描述

数组乱序

主要用到的api是Match.random和set

function disorder(arr) {
  let len = arr.length
  let res = []
  let remember = new Set()
  // console.log(remember.size);
  while (remember.size < len) {

    let randomNum = Math.floor(len * Math.random())
    if (!remember.has(randomNum)) {
      res.push(arr[randomNum])
      remember.add(randomNum)
    }
  }
  return res


}

console.log(disorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));

手写数组filter方法

先具体了解一下filter -MDN
反复刷这些javascript手写题,我又变强了

反复刷这些javascript手写题,我又变强了

简单的面试题

知乎万赞,值得反复刷的Android面试题

15 道二叉树手写算法题

算法如何刷题