几道需要必会的手写题

212 阅读3分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

大家好,我是cv竹叶,面试的时候经常遇到要求手写解题,为了防止题留空白,今天我们就来学习几道高频的手写题目吧!万一中了呢!

手写相关

手写new函数

思路:以Object对象创建新对象,再把传入的函数this转向新对象的this,然后再对结果类型进行判断是函数还是对象,再返回。

function myNew(fn,...item){
    let obj = Object.create(fn.prototype);//以旧的构造函数创建obj对象;
    let res = fn.call(obj,...item);//把旧的this指向新的obj对象
    if(res&&(typeof res === 'object' || typeof res === 'function')){
        return res;//返回新的对象
    }
    return obj;
}
function Person(name, age) {
  this.name = name;
  this.age = age;
}
let obj = myNew(Person, "竹叶", 666);
obj.name;//竹叶

手写bind函数

思路:借用call()、apply()函数改变this指向,运用arguments获取全部传入的参数值进行重新赋值,最终返回一个新的对象。

Function.prototype.myBind = function(thisArg){
    if(typeof this !== 'function') {
        throw TypeError("必须是函数")
    } 
    const args = Array.prototype.slice.call(arguments,1),//取出除了第一个this,其他的数组值,构造函数
    self = this,
    newfn = function(){},//用于保存原函数的原型
    bound = function(){
        return self.apply(
            this instanceof newfn ? this : thisArg,
            args.concat(Array.prototype.slice.call(arguments))//获取传入bound函数的值
        )
    }
    //有传入对象,重新指定this到保存函数
    if(this.prototype){
        newfn.prototype = this.prototype; 
    }
    bound.prototype = new newfn();//修改绑定函数的原型指向
    return bound;
}
let obj = {
    name:'竹叶',
}
function test(x,y,z){
    console.log(this.name,x+y+z)
}
let Bound = test.myBind(obj,1,2)
Bound(3);//竹叶 6
new Bound(2);//undefined 5 

手写实现防抖

防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间(每次触发前都取消之前的延时调用方法)

用到场景:搜索输入框

思路:给定指定时间,在时间内如果再次触发,则重新执行执行函数。

function clickFn(fn,delay){
    let timer = null;
    return function(){
            let that = this;
            let args = [...arguments]//点击事件的事件组,构造函数
            if(timer) clearTimeout(timer);//清掉之前的时间,重新计算时间
            timer = setTimeout(function(){
                fn.call(that,...args);//为了防止 this 指向改变,确保上下文为当前的this,传递参数
            },delay)
    }
}
function testFn(){
    console.log('竹叶')
}
document.addEventListener('click',clickFn(testFn,1000))

手写实现节流

节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率 思路:每次触发事件时都判断当前是否有等待执行的延时函数,需要一个标记

使用场景:滚动加载更多

思路:在给定的时间内,只能执行一次函数,执行完成后再重新按时间执行一次。

function clickFn(fn,delay){
    let timer = null;
    let isNext = false;
    return function(){
         if(isNext) return;//时间到了才执行下一步,否则返回
         let args = [...arguments];//点击事件的事件组,构造函数
         let that = this;
         isNext = true;
         if(timer) clearTimeout(timer);
         timer = setTimeout(function (){
             fn.call(that,...args);//为了防止 this 指向改变,确保上下文为当前的this,传递参数
             isNext = false;
         },delay)
    }
}
function testFn(){
    console.log('竹叶')
}
document.addEventListener('input',clickFn(testFn,1000))//监听输入频繁

结言

会写了吗?就算不会写,思路也要有哦,至少能在面试官面前加点分。如果对你有帮助就点个赞吧!