2020秋招前端面经-常见手撕代码题

下面整理一下最近这段时间面试过程当中遇到的一些手撕的代码题,其中有些题目遇到过不止一次,也都是比较基础的题目,你们能够参考一下,ps:若是你没时间刷完大部分的leetcode题,那么我建议优先刷一下leetcode的 热题 HOT 100,确实很容易被问到,并且笔试里面也会遇到,剑指也能够,可是我没刷过,具体的不是很了解。
面试

  1. 多维数组降维问题

关于这个问题,在ES6中有一个新的方法arr.flat()方法,能够直接返回降维后的数组,flat的参数为降维的维度,默认为一维,能够为数字,Infinity为任意维,可是这个方法在低版本的浏览器中还不支持,因此通常会让你写一个原生的方法,这里介绍几种方法
数组

//方法一:常规方法,递归遍历,判断是否数组,须要用到额外的全局变量
var result=[]
var flat=function (arr) {
  for(let i=0;i<arr.length;i++){
    if(Array.isArray(arr[i])){
      flat(arr[i])
    }else{
      result.push(arr[i]);
    }
  }
}
//上述方法优化
var flat=function (arr) {
  var result=[]
  for(let i=0;i<arr.length;i++){
    if(Array.isArray(arr[i])){
      result=result.concat(flat(arr[i]))
    }else{
      result.push(arr[i]);
    }
  }
  return result;
}
//上述方法的简洁写法,利用箭头函数
let flat = arr => arr.reduce((begin,current)=>{
  Array.isArray(current)?begin.push(...flat(current)):begin.push(current);
  return begin;
},[])
//方法二:使用字符串分割
var flat=function(arr){
  let strarr=arr+"";
  let str=strarr.split(",");
  return str;
}
复制代码
  1. 全部子序列问题
//全部顺序子序列(输出全部有序的子序列)
var subSequence=function (arr){
  let res=[];
  for(let i=0;i<arr.length;i++){
    for(let j=i;j<arr.length;j++){
      res.push(arr.slice(i,j+1))
    }
  }
  return res;
}
console.log(subSequence([1,2,3]))
//结果为 1 1,2 1,2,3, 2 2,3 3

//全部数组元素排列组合
// var allSubSequence=function(arr){
//   let len=arr.length;
//   let mark=new Array(len);
//   let result=[];
//   var recursion=function(arr,mark,n,i){
//     if(n==i){
//       let temparr=[];
//       for(let k=0;k<i;k++){
//         if(mark[k]==1){
//           temparr.push(arr[k]);
//         }
//       }
//       result.push(temparr);
//       return;
//     }
//     mark[n]=0;
//     recursion(arr,mark,n+1,i)
//     mark[n]=1;
//     recursion(arr,mark,n+1,i)
//   }
//   recursion(arr,mark,0,len);
//   return result;
// }
// console.log(allSubSequence([1,2,3,4]));
//输出结果为
// [],
// [ 4 ],
// [ 3 ],
// [ 3, 4 ],
// [ 2 ],
// [ 2, 4 ],
// [ 2, 3 ],
// [ 2, 3, 4 ],
// [ 1 ],
// [ 1, 4 ],
// [ 1, 3 ],
// [ 1, 3, 4 ],
// [ 1, 2 ],
// [ 1, 2, 4 ],
// [ 1, 2, 3 ],
// [ 1, 2, 3, 4 ] 
//原理: 
//原理,使用二进制的排列组合来实现
//将a,b,c,d 分别以二进制占位符表示,0即表示不存在,1表示不存在,mark数组即用来存储这个占位符
//如0000则表示空集,1111表示集合{a,b,c,d},0001表示{d},0110表示{b,c}
//本质就是将0000按二进制加到1111,每加1就输出一次其表示的数
//递归的原理图以下,当只有abc三个数时
//                0
//            0
//                1
//        0
//                0
//            1
//                1
// start
//                0
//            0
//                1
//        1
//                0
//            1
//                1
复制代码
  1. 多维数组每一维排列组合
var result=[];
var results=[];
var doExchange=function (arr, depth) {
  for (let i = 0; i < arr[depth].length; i++) {
    result[depth] = arr[depth][i];
    if (depth !== arr.length - 1) {
      doExchange(arr, depth + 1)
    } else {
      results.push(result.join(" ").split(" "))
    }
  }
}

doExchange([[1,2,3],[4,5],[6,7]],0)
for(let i=0;i<results.length;i++){
  for(let j in results[i]){
    results[i][j]=parseInt(results[i][j])
  }
}
console.log(results)
//结果:
// [ 1, 4, 6 ],
// [ 1, 4, 7 ],
// [ 1, 5, 6 ],
// [ 1, 5, 7 ],
// [ 2, 4, 6 ],
// [ 2, 4, 7 ],
// [ 2, 5, 6 ],
// [ 2, 5, 7 ],
// [ 3, 4, 6 ],
// [ 3, 4, 7 ],
// [ 3, 5, 6 ],
// [ 3, 5, 7 ]
复制代码
  1. js实现对象属性的get,set方法

这里其实考察的是函数中this的指向问题,这里用到了前文提到过的一个知识点 在js部分-ES6新增-函数相关扩展方法-普通函数中的this的四种调用模式
浏览器

//方法一:使用函数的方式实现
function Person(val){
  this.name="admin";
  this.getName=function(){
    return this.name;
  }
  this.setName=function(val){
    this.name=val;
  }
}
var per=new Person();
console.log(per.name)//admin
console.log(per.getName())//admin
per.setName(111)
console.log(per.getName())//111
//方法二:使用对象的方式实现(这种方式不能new一个实例)
var Person={
  name:"admin",
  getName(){
    return this.name;
  },
  setName(val){
    this.name=val
  }
}
console.log(Person.name)//admin
console.log(Person.getName())//admin
Person.setName("111")
console.log(Person.getName())//111
//方法三:使用原型链的按时实现
function Person(){ } 
Person.prototype.name="admin";
Person.prototype.getName=function(){
  return this.name;
};
Person.prototype.setName=function(val){
  this.name=val;
};
var per=new Person();
console.log(per.name)//admin
console.log(per.getName())//admin
per.setName(111)
console.log(per.getName())//111
复制代码
  1. a==1&&a==2返回true,这个问题的原理就是js中的隐式类型转换,涉及到两个函数,js在遇到==的时候会先对数据使用valueOf函数将数据转换为原始类型,而后判断值是否相等,若是不等,会对数据使用toString()方法,而后判断两个字符串是否相等。

toString()会把数据类型转换成string类型,也就是说无论原来是什么类型,转换后一概是string类型
valueOf()会把数据类型转换成原始类型,也就是说原来是什么类型,转换后仍是什么类型,日期类型除外
markdown

let a={
  i:1,
  valueOf(){
    return a.i++;
  }
}
console.log(a==1&&a==2) //true

let b={
  i:1,
  toString(){
    return b.i++;
  }
}
console.log(b==1&&b==2) //true
复制代码
  1. 每隔1秒输出1,2,3,4...
//方法一:ES6 let 块级做用域
//注意:这里若是使用var的话,会每一个一秒输出一个5,输出5个5
for(let i = 1; i <5; i++){
  setTimeout(function () {
  console.log(i);
  },1000*i);
}
//方法二:ES5 闭包 匿名函数and函数自动执行
//       (function(i){})(i) 其中第一个()返回一个匿名函数,第二()起到当即执行的做用
for (var i = 1; i <= 10; i++) {
  (function (i) {
    setTimeout(function () {
      console.log(i);
    }, 1000 * i);
  })(i);
}
复制代码
  1. js实现防抖和节流
/* 
  *fn --> 须要防抖的函数;
  *delaytime --> 毫秒数,防抖所需期限值;
*/
//防抖
//原理:当持续触发事件时,必定时间段内没有再触发事件,事件处理函数才会执行一次,若是设定的时间到来以前,又一次触发了事件,
//就从新开始延时。
function debounce(fn,delaytime){
  let timer = null 
  return function(){
      if(timer){
        //进入这里说明当前存在一个执行过程,而且同时又执行了一个相同事件,故取消当前的执行过程
        clearTimeout(timer) 
      }
      timer = setTimeout(fn,delaytime)    
  }
}
function show_scrollPosition(){
  var scrollPosition = document.body.scrollTop || document.documentElement.scrollTop;
  console.log("当前滚动条位置为:",scrollPosition);
} 

window.onscroll = debounce(show_scrollPosition,1000)
//节流
//原理:规定一个期限时间,在该时间内,触发事件的回调函数只能执行一次,若是期限时间内回调函数被屡次触发,则只有一次能生效。
function throttle(fn, delay) {
  let last_time
  let timer = null
  return function () {
    let cur_time = new Date().getTime()
    if (last_time && cur_time < last_time + delay) { 
      //若为真,则表示上次执行过,且在期限值范围内
      clearTimeout(timer)
      timer = setTimeout(() => {
        fn();
        last_time = cur_time
      }, delay)
    } else {
      last_time = cur_time;
      fn();
    }
  }
}
function show_scrollPosition() {
  var scrollPosition = document.body.scrollTop || document.documentElement.scrollTop;
  console.log("当前滚动条位置为:", scrollPosition);
}
window.onscroll = throttle(show_scrollPosition, 1000)
复制代码
  1. js实现add(1)(2)(3)=6
function add(val){
  var rs = function(oval){
      return add(val + oval);
  }
  rs.toString = function(){
      return val;
  }
  return rs;
}
console.log(add(1)(2)(3) == 6);
复制代码
相关文章
相关标签/搜索