当前位置: 首页 > article >正文

前端面试常见手写题

实现一个new操作符

//实现一个new操作符
function myNew(fn,...args){
    if(typeof fn !== 'function') {
        throw ('fn is not a function')
    }
    //将对象的原型设置为fn的prototype
    let res=Object.create(fn.prototype)

    //使用 apply 执行构造函数 并传入参数 arguments 获取函数的返回值
    let result=fn.apply(res,args)

    return result
}

实现instanceof

//实现instanceof

function myInstanceof(left,right){
    //如果左边不是引用数据类型
    if(typeof left !== 'object' || left === null) return false

    //获取左边的原型
    let proto=Object.getPrototypeOf(left)

    while(true){
        //查找到底了
        if(proto==null) return false
        //相等
        if(proto==right.prototype) return true
        //顺着原型链继续查找
        proto=Object.getPrototypeOf(proto)
    }
}

实现浅拷贝

function shallowClone(obj){
    //如果是基础数据类型,直接返回
    if(typeof obj !== 'object' || obj==null) return obj

    //如果是引用数据类型,新开辟一个地址,拷贝一层
    let newObj=Array.isArray(obj) ? [] : {}

    for(let key in obj){
        newObj[key]=obj[key]
    }

    return newObj
}

实现深拷贝

function deepClone(obj){
    let cloneObj=Array.isArray(obj)?[]:{};

    //遍历其中的key
    for(let key in obj){
        if(typeof obj[key]==='object'){
            //递归
            cloneObj[key]=deepClone(obj[key]);
        }else{
            cloneObj[key]=obj[key];
        }
    }
    return cloneObj
}

实现call/apply

// 实现call/apply

//挂载到 Function.prototype上
Function.prototype.myCall = function(val,...args) {
    //判断this指向,需要指向function
    //谁调用这个方法,this就指向谁
    if(typeof this !== 'function') {
        throw new TypeError('error')
    }   

    //获取程序执行上下文
    let context=val || window
    // 将当前函数绑定到 context 上
    context.fn = this;

    // 调用函数并获取结果
    const result = context.fn(...args);

    // 删除临时属性
    delete context.fn;

    return result;
}

实现防抖

// 防抖:n秒后执行事件,若n秒内再次触发,则重新计时

function debounce(fn,delay){
    //设置定时器
    let timer = null;
    return function(){
        //如果还存在定时器,清除定时器后重新计时
        if(timer) clearTimeout(timer);
        timer=setTimeout(fn,delay)
    }
}

实现节流

// 实现节流:n秒内只允许一次,若n秒内反复触发,只有一次生效
function throttle(fn,delay){
    //设置开关,是否允许执行
    let valid=true;
    return function(){
        if(!valid) return;
        //一定延迟后执行
        setTimeout(()=>{
            fn();
            valid=true;
        },delay)
    }
}

实现promise

//自定义promise

class MyPromise{
    //定义三种状态
    static PENDING = 'pending';
    static FULFILLED = 'fulfilled';
    static REJECTED = 'rejected';

    //定义构造函数
    constructor(fn){
        //默认等待状态
        this.status=MyPromise.PENDING;
        //默认结果
        this.result=null

        try{
            fn(this.resolve.bind(this),this.reject.bind(this))
        }catch(err){
            //捕获异常
            this.reject(err)
        }
    }

    //定义resolve方法
    resolve(result){
        if(this.status===MyPromise.PENDING){
            this.status=MyPromise.FULFILLED
            this.result=result
        }
    }

    //定义reject方法
    reject(result){
        if(this.status===MyPromise.PENDING){
            this.status=MyPromise.REJECTED
            this.result=result
        }
    }

    //定义then方法
    then(resolve,reject){
        //判断是否为空函数
        resolve=typeof resolve==='function'?resolve:()=>{}
        reject=typeof reject==='function'?reject:()=>{}

        //根据当前status返回不同结果
        if(this.status===MyPromise.FULFILLED){
            setTimeout(()=>{resolve(this.result)})
        }

        if(this.status===MyPromise.REJECTED){
            setTimeout(()=>{reject(this.result)})
        }
    }
}

实现函数柯里化

//实现函数柯里化
function curry(fn,args){
    var num=fn.length
    var args=args||[];

    //返回方法
    return function(){
        //把参数放入数组
        var arr=[].slice.call(arguments);
        //将收集到的参数放入arr
        [].push.apply(arr,args)
        if(arr.length<num){
            //递归调用方法
            return curry.call(this,fn,arr)
        }
        return fn.apply(this,arr)
    }
}

实现无限级目录树

function renderMenu(menuItems,parentElement){
    //获取页面上的ul元素
    const ul=document.createElement("ul");
    //遍历menuItems数组,生成li元素
    menuItems.forEach(item=>{
        const li=document.createElement("li");
        li.textContent=item.name;
        if(item.children && item.children.length>0){
            renderMenu(item.children,li);
        }
        ul.appendChild(li);
    })
    if(parentElement){
        parentElement.appendChild(ul);
    }
}

实现快速排序

//实现快速排序

function quickSort(arr){
    //递归中止条件
    if(arr.length<=1) return arr

    //定义基准值,可任取,这里取数组第一项
    let base=arr[0]
    //基准值左侧和右侧的数组
    let leftArr=[]
    let rightArr=[]

    //遍历数组,根据值的大小分别放入对应的数组
    for(let i=1;i<arr.length;i++){
        if(arr[i]<base) leftArr.push(arr[i])
        else rightArr.push(arr[i])
    }

    //合并数组
    let resArr=quickSort(leftArr).concat(base,quickSort(rightArr))

    return resArr
}

http://www.kler.cn/a/300818.html

相关文章:

  • Linux网络 TCP socket
  • redis 分布式重入锁
  • 如何在vue中渲染markdown内容?
  • VD:生成a2l文件
  • SpringSecurity详解
  • 持续集成 01|Gitee介绍、Pycharm使用Gitee
  • C/C++ 网络编程之关于多核利用问题
  • 【openGauss】WDR快照无法生成或执行生成不报错,但是snapshot.snapshot为空的问题
  • Linux s3c2440 开发板上的操作系统实现 ubuntu
  • 《中国制药设备行业市场现状分析与发展前景预测研究报告》
  • spring中添加@Test注解测试
  • docker的相关网络问题
  • 【编程基础知识】mysql中的insert into ... on DUPLICATE key和replace into的性能对比
  • AI产品经理:站在科技风口上的新兴职业
  • 一些实用的高阶用法--python
  • EtherCAT EOE移植及上手说明
  • CSP-J 初中的数学知识要学完, CSP-S 肯定是要需高中的知识
  • C# 如何检查两个给定的线段是否相交(How to check if two given line segments intersect)
  • 谷歌GMS认证之手机的AACT测试,AACT测试与车机Android Auto认证有什么区别?AACT测试流程介绍
  • 【自动驾驶】决策规划算法 | 数学基础(三)直角坐标与自然坐标转换Ⅰ
  • PHP随时随地预订民宿酒店预订系统小程序源码
  • UNIX IPC方法的分类
  • mysql 之 information_schema
  • DataGridView组件中显示的SQLite表中数据
  • 【MySQL】从0开始在Centos 7环境安装MySQL
  • 探索Python中文拼音转换的奥秘:xpinyin库