手写基础题--前端篇

总结高频手写题目
会每日更新,记录自己的学习进度。


文章目录

  • JS系列
    • 一、实现函数节流、防抖方法
    • 二、数组去重
    • 三、深克隆
    • 四、实现instance of
    • 五、嵌套数组指定层次展开flat扁平化
    • 六、实现 reduce 数组方法
    • 七、实现数组map方法
    • 八、实现Array.fill()、Array.filter()
    • 九、实现Array.find()、Array.finIndex()
    • 十、Promise简单实现
    • 十一、Ajax请求的原生实现
    • 十二、模拟new
    • 十三、实现Object.create方法
    • 十四、ES5实现继承那些事
    • 十五、实现函数的call、apply、bind方法
    • 十六、实现一个双向绑定
    • 十七、单例模式
    • 十八、观察者模式
    • 十九、使用setTimeout实现setInterval方法
    • 二十、实现jsonp
  • CSS
    • 一、CSS画各种图形
    • 二、三列布局
    • 三、垂直水平居中
  • 总结


JS系列

一、实现函数节流、防抖方法

节流函数(throttle):规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只能有一次生效。

//func用户传入的防抖函数;wait是等待时间为1s
const throttle= (func,wait = 1000) => {
     
    //上一次执行该函数的时间
    let lastTimer = 0;
    return function () {
     
        let now = +new Date();
        let args = arguments;
        // 将当前时间和上一次执行时间做对比
        // 差值大于wait 执行函数
        if (now-lastTimer > wait) {
     
            lastTimer = now;
            func.apply(this, args)
        }
    }
};

setInterval(
    throttle(()=>{
     
        console.log(1);
    },500)
); 

适用场景:

  • 拖拽场景:固定时间内只执行一次,防止高频词触发位置变动。
  • 缩放场景:监控浏览器resize
  • 动画场景:避免短时间内多次触发动画引起性能为题。

防抖函数(debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

//func需要传入的防抖函数
//wait是等待时间
const debounce = (func,wait=50)=>{
     
    let timer = 0;
    // 返回函数是用户每次实际调用的防抖函数
    return function (...args) {
     
        // 如果已经设定过定时器了就清空上一次的定时器
        if(timer) clearTimeout(timer);
        // 开启一个新的定时器,延迟执行用户传入的方法
        timer = setTimeout(()=>{
     
            func.apply(this,args) //通过this,args获取函数作用域和变量
        },wait)    
    }
};

上面实现了简单的防抖,但是有缺陷,这个防抖只能在最后调用。详细的防抖会有 immediate选项。表示是否立即调用。

适用场景

  • 表单验证:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次。
  • 按钮提交:只执行最后一次提交,防止多次提交按钮。

二、数组去重

给定一个数组:var arr = [1,1,‘true’,‘true’,true,true,0,0,undefined,undefined,null,null,NaN,NaN,‘NaN’,2,{},{}];

  • 方法一:双重for + splice
function arrayUnique_1(arr) {
     
    let res = [];
    for(let i=0;i<arr.length;i++) {
     
        for (let j=i+1;j<arr.length;j++) {
     
            //当第一个等于第二个,splice方法删除第二个
            if(arr[i]===arr[j]){
     
                arr.splice(j,1);
                j-- //第二个删除后,这个索引位需要重新判断
            }
        }
    }
    return arr
}
console.log(arrayUnique_1(arr)); //NaN和{}没有去重

  • 方法二: 利用ES6的 set 去重
function arrayUnique_2(arr) {
     
    return Array.from(new Set(arr))
}

function arrayUnique_3(arr) {
     
    return [...new Set(arr)]
}
console.log(arrayUnique_2(arr)); //{}没有去重
console.log(arrayUnique_3(arr)); //{}没有去重

  • 方法三:利用indexof去重
function arrayUnique_4(arr) {
     
    //判断是否是数组
    if (!Array.isArray(arr)) {
     
        console.log('type error!');
        return
    }
    var array = [];
    for (let i=0;i<arr.length;i++) {
     
        if (array.indexOf(arr[i]) === -1){
      //利用indexof 检测元素在数组中第一次出现的位置是否和元素现在的位置相等
            array.push(arr[i])
        }
    }
    return array
}

console.log(arrayUnique_4(arr)); //NaN,{}没有去重

- 方法四:利用sort()排序后,判断相邻元素是否相等
function arrayUnique_5(){
     
    if (!Array.isArray(arr)) {
     
        console.log('type error!');
        return ;
    }
    arr = arr.sort();
    let array = [arr[0]]
    for (let i=1;i<arr.length;i++) {
     
        if(arr[i]!==arr[i-1]){
     
            array.push(arr[i])
        }
    }
    return array
}

console.log(arrayUnique_5(arr)); //NaN,{}没有去重

  • 方法五:includes检测数组中是否有某个值
function arrayUnique_6(arr) {
     
    if (!Array.isArray(arr)){
     
        console.log('type error!');
        return ;
    }
    let array = [];
    for (let i=0;i<arr.length;i++){
     
        if (!array.includes(arr[i])){
      //includes:检测数组是否有某个值
            array.push(arr[i]);
        }
    }
    return array
}

console.log(arrayUnique_6(arr)); //{}没有去重

  • 方法六:利用filter
//利用filter
function arrayUnique_7(arr) {
     
    return arr.filter(function (item,index,arr) {
     
        // 当前元素,在原始数组中的第一个索引===当前索引值,则返回
        return arr.indexOf(item,0) === index; //每次都是从左边开始找
    })
}

console.log(arrayUnique_7(arr)); //{}没有去重,NaN直接没了

  • 方法七:利用Map

利用Map中不会出现相同key值的特点,创建一个空的Map数据结构,
遍历数组,把数组中的每一个元素作为key存到Map中。

function arrayUnique_8(arr) {
     
    let map = new Map();
        let array = new Array();
        for(let i=0;i<arr.length;i++){
     
            if(map.has(arr[i])) {
     
            map.set(arr[i],true)
        }else{
     
             map.set(arr[i],false);
             array.push(arr[i])
        }
    }
    return array;
}

console.log(arrayUnique_8(arr)); //{}没有去重

三、深克隆

四、实现instance of

五、嵌套数组指定层次展开flat扁平化

六、实现 reduce 数组方法

七、实现数组map方法

八、实现Array.fill()、Array.filter()

九、实现Array.find()、Array.finIndex()

十、Promise简单实现

十一、Ajax请求的原生实现

十二、模拟new

十三、实现Object.create方法

十四、ES5实现继承那些事

十五、实现函数的call、apply、bind方法

十六、实现一个双向绑定

十七、单例模式

十八、观察者模式

十九、使用setTimeout实现setInterval方法

二十、实现jsonp

CSS

一、CSS画各种图形

二、三列布局

三、垂直水平居中

每日一更,持续练习!颤抖吧、愚蠢的面试题们。


总结

你可能感兴趣的:(面经辑录,javascript)