前端核心手写面试题(看你的马步扎实不扎实)

Posted 有两把刷子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端核心手写面试题(看你的马步扎实不扎实)相关的知识,希望对你有一定的参考价值。

防抖

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    防抖: <input id="input" type="text">
</body>
<script>
    // 监听拿到input输入的值
    input.addEventListener('input', function (e) 
        val(e.target.value)
    )
    // 防抖的核心代码
    function fn(time, fun) 
        let flag // 定义状态
        return function (value) 
            clearTimeout(flag)// 在执行之前 清除 定时器的 flag 不让他执行
            flag = setTimeout(() => 
                fun(value)
            , time)
        
    
    let val = fn(1000, function (val) 
        console.log(val)
    )
</script>
</html>

节流

<body>
    <button id="button">手在快1秒执行一次</button>
</body>
<script>
    /*
        定时器版本的
          fns 回调函数
          time 间隔时间
        function throttle(fns, time) 
        let flag // 定义一个空状态
        return function ()  // 内部函数访问外部函数形成闭包
            if (!flag)  // 状态为空执行
                flag = setTimeout(() => 
                    fns.apply(this, arguments) // 改变this指向 吧 event 事件对象传出去
                    flag = null
                , time)
            
        
       
    */

    function throttle(fun, time) 
        let flag = 0
        return function () 
            let now = +new Date().valueOf()
            // 当前的值 减去上一次的值 >= 传过来的事件 执行
            if (now - flag >= time) 
                fun.apply(this, arguments)
                flag = now
            
        
    



    button.onclick = throttle((e) => 
        console.log(e)
    , 1000)
</script>

深拷贝

   var arr = 
        a: 2,
        b: [33]
    

    function cloneDeep(arr = ) 
        // 终止递归 判断如果传进来的数据不是 object 或者 传进来的是一个 null 直接返回
        if (!arr || typeof arr != 'object' || arr == null) return arr
        // 声明一个对象
        let result
        // 用 instanceof 判断原型链上是否有该类型的原型 是 Array => [] ! Arrays =>
        arr instanceof Array ? result = [] : result = 
        // forin 循环对象的key值
        for (const key in arr) 
            //  对象 key 赋值 result
            result[key] = cloneDeep(arr[key])
        
        T
vv ro    


    let arr2 = cloneDeep(arr)
    // let arr2 = [...arr]
    arr2.b[0] = 5
    console.log(arr);//  a: 2, b: Array(1)   Array  a: 2  b: [33]
    console.log(arr2);//  a: 2, b: Array(1)  Array  a: 2  b: [5]
    // 修改新对象不影响原来的对象   

类型判断

    /*
      实现一个类型判断
        []     返回 array
             返回object
        /^$/   RegExp
        1      number
   */


    //   第一种方案
    function type_of(obj) 
        let res = Object.prototype.toString.call(obj).split(' ')[1] // 输出 RegExp]
        /*
        res.substring(0, res.length - 1) 从第 0 项开始截取 截取到它的长度 -1 
        也就是最后一项的前一项 把最后的一项  ] 给干掉
        */
        return res.substring(0, res.length - 1).toLowerCase()
    


    // 第二种方案
    function type_of(obj) 
        // .slice(8, -1) 从 第 8项开始截取 -1 不要最后一项
        return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
    

数字千位分割

  const format = (n) => 
        let num = n.toString() // 拿到传进来的 number 数字 进行 toString
        let len = num.length // 在拿到字符串的长度
        // 当传进来的结果小于 3 也就是 千位还把结果返回出去 小于3 不足以分割
        if (len < 3) 
            return num
         else 
            let render = len % 3 //传入 number 的长度 是否能被 3 整除
            console.log(render)
            /*
            match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
            该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。
            var str = '123123000'
            str.match(/\\w3/g).join(',') // 123,123,000
            */
            if (render > 0)  // 说明不是3的整数倍
                return num.slice(0, render) + ',' + num.slice(render, len).match(/\\d3/g).join(',')
             else 
                return num.slice(0, len).match(/\\d3/g).join(',')
            
        
    

    let str = format(298000)
    console.log(str)

生成随机数

MDN随机数 https://developer.mozilla.org/zh-CN/docs/Web/javascript/Reference/Global_Objects/Math/random

    // 生成随机数
    function random(min, max) 
        //  Math.floor() 向下进行取证
        return Math.floor(Math.random() * (max - min + 1) + min)
    
    console.log(random(3, 5))

手写call方法

    // 给function的原型上面添加一个 _call 方法
    Function.prototype._call = function (context) 
        //  判断调用者是否是一个函数  this 就是调用者
        if (typeof this != 'function') 
            return
        
        // 如果有 context 传参就是传参者 没有就是window
        that = context || window
        // 保存当前调用的函数
        that.fn = this   // 吧 this == fns   存到that.fn来
        // 截取传过来的参数
        /*
          arguments
                 a: 1
                 fn: ƒ fns()
        */
        // 通过 slice 来截取传过来的参数
        const local = [...arguments].slice(1)
        // 传入参数调用函数
        let result = that.fn(...local)
        // 删出 fn 属性
        delete that.fn
        return result
    

    let obj =  a: 1 
    function fns(a, b) 
        console.log(a, b);
        console.log(this)
    
    fns._call(obj, 23, 555)

手写apply

    Function.prototype.myApply = function (context) 
        if (typeof this !== 'function') 
            // 判断当前调用者是否为函数
            return
        
        // 保存传入的this指向
        that = context || window
        // 保存当前调用的函数
        that.fn = this
        let result
        // 这里开始判断传入的参数是否存在,此时参数是一个数组形式[thisArg,[传参]]
        // 那么如果arguments[1]即传参存在的时候,就是需要传参调用保存的函数
        // 如果不存在就直接调用函数
        if (arguments[1]) 
            result = that.fn(...arguments[1])
         else 
            result = that.fn()
        
        return result
    

    let obj = 
        a: 1
    

    function fn(...val) 
        console.log(this)
        console.log(...val)
    
    fn.apply(obj, [1, 4, 5, 6, 7, 9])

手写 bind

    Function.prototype._bind = function (context) 
        // 当调用用了_bind 函数  this 指向调用 _bind 的那个函数
        // this 不是 function 不让使用 抛出类型错误
        if (typeof this != 'function') 
            throw new TypeError('Error')
        
        // 获取参数 除了传过来的第一项我全都要
        const args = [...arguments].slice(1)
        // 吧 function 进行一个缓存
        fn = this

        // 返回一个函数 因为 bind 不是立即调用的
        return function Fn() 
            // 判断  this 原型链上是否又该类型的原型 Fn
            return fn.apply(this instanceof Fn ? new fn(...arguments) : context, args.concat(...arguments))
        

    

    let obj = 
        a: 1
    

    function fn(...val) 
        console.log(this)               // obj
        console.log(...val)   // 231, 31242344, 432
    
    fn._bind(obj, 231, 31242344, 432)()

数组去重

        /*
          数组的去重 
        */
        let ylbsz = [1, 35, 6, 78, 66, 6, 35]
        function _set(arr) 
            // 放一个新数组
            let newArr = []
            for (let i = 0; i < arr.length; i++) 
                if (newArr.indexOf(arr[i]) == -1) 
                    newArr.push(arr[i])
                
            
            return newArr
        
        console.log(_set(ylbsz))
        console.log([...new Set([11, 11, 222, 222])])

        // 字符串去重
        let str = '123321你好你好'
        console.log([...new Set(str.split(''))].join(''))

数组排序(冒泡)

    function sort(arr) 
        // 外层循环控制的是比较的轮数,你要循环几轮
        //  arr.length (5 ) - 1  = 4
        for (let i = 0; i < arr.length - 1; i++) 
            // 内层循环控制的每一轮交换的次数
            // 第一轮要比较4次   下标为 0     arr.length - 1(4) - i(0)  =  4
            // 第二轮要比较3次   下标为 1     arr.length - 1(4) - i(1)  =  3
            // 第三轮要比较2次   下标为 2     arr.length - 1(4) - i(2)  =  2
            // 第四轮要比较1次   下标为 3     arr.length - 1(4) - i(3)  =  1

            // 内层循环控制的每一轮交换的次数
            for (let j = 0; j < arr.length - 1 - i; j++) 
                // arr[j] 第一项  arr[j + 1] 第二项
                // arr[j] 第二项  arr[j + 1] 第三项
                // ....
                if (arr[j] > arr[j + 1]) 
                    //  大于后一项 做一个交换变量 es6 结构赋值 的变量交换
                    [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
                
            
        
        return arr
    
    console.log(sort([200, 100, 3, 9, 4]));

数组的排序(快排)

    let arr = [1, 4, 6, 7, 7, 9]

    // 1. 取出我们数组的中间项 用splice 拿到中间项 
    // 2. 在声明两个空数组,一个空数组用来放置 中间一项 大于 循环的每一项的话 就把他放到左边的数组里,下
    // 余的话就放到右边的数组
    // 3.接下来就是循环便利了 
    // 最后再次利用函数自己调用自己一直执行 递归
    // 4. 如果传进来的数组 小于等于 1 的话就终止递归循环

    // 做一个快排
    function fn(arr) 
        // 如果传进来的数组 小于等于 1 的话就终止递归循环
        if (arr.length <= 1) return arr

        // 总长度除以2的话就可以拿到中间一项的下标
        let n = Math.floor(arr.length / 2)
        // splice 返回被删除的元素 下标为 0 就是只拿第一项 因为它只返回一个数据 就是被删除的一项
        let cen = arr.splice(n, 1)[0]

        // 2. 在声明两个空数组,一个空数组用来放置 中间一项 大于 循环的每一项的话 就把他放到左边的数组里,下
        // 余的话就放到右边的数组

        let leftArr = []
        let rightArr = []
        // 接下来就是循环便利了 判断
        for (let j = 0; j < arr.length; j++) 
            let item = arr[j]
            //  > 如果是大于就是 从大到小   如果是小于  < 从小到大
            cen < item ? rightArr.push(item) : leftArr.push(item)
        

        return fn(leftArr).concat(cen, fn(rightArr))
    
    console.log(fn(arr))

数组排序(插入排序)

  function insert(arr) 
        // 1、准备一个数组这个数组就是新抓的牌,开始先抓一张牌进来
        let handle = []
        handle.push(arr[0])
        // 2、第二次开始按顺序抓牌一直把牌抓光了
        for (let i = 1; i < arr.length; i++) 
            // a 是新抓的牌
            let a = arr[i]
            // 和手里的牌进行比较(从后向前比)
            //  handle.length - 1 因为下标是从 0 开始数的
            for (let j = handle.length - 1; j >= 0; j--) 
                // 每一次要比较手里的牌
                let b = handle[j]
                // 如果当前新牌a比b 大了,可就要放到 b 的后面
                // 如果 a > b 就是表示从小到大
                // a < b 送大到小
                if (a > b) 
                    // 如果想要放到 j 的后面就要加上一个 1,
                    /**
                     * 比如说我要插队一般要插就是插到 a 的前面
                     * 但是我想要插到 a 的后面怎么办
                     * 那这个时候就要插到 a 下一个人的人前面就可以了
                     * 
                    */
                    handle.splice(j + 1, 0, a)
                    break
                
                // 还有一种情况就是如果你比较到第一项的还比较吗,不比较了
                // 我们吧新牌放到最前面即可
                if (j == 0) 
                    handle.unshift(a)
                
            
        
        return handle
    

    console.log(insert([2, 8, 5, 92, 52, 4]))

数组的最大值最小值

    const array = [5, 4, 7, 8, 9, 2];
    let num = array.reduce((a, b) => a > b ? a : b);
    console.log(num) // 9
    let nums = array.reduce((a, b) => a < b ? a : b);
    console.log(nums) // 2

对象去重

    /*@  数据处理对象去重*/
    let arr = [
        
            a: 1,
            b: 2,
            id: 6666
        ,
        
            a: 1,
            b: 2,
            id: 6666
        C语言经典面试题丨快来测一测你的基础语法扎不扎实,你能做出几题?

关于前端大厂面试经验分享

iOS面试题 -总结 ,你的基础扎实吗?

C语言经典面试题丨快来测一测你的基础语法扎不扎实,你能做出几题?

这些面试题你会怎么答?

这些面试题你会怎么答? (系列一)