前端手写题-防抖、节流,深浅拷贝等



防抖

  • 声明定时器
  • 返回函数
  • 判断是否有定时器,如果有,销毁定时器
  • 创建定时器,执行函数
js 复制代码
function debounce(fn,t){
    let timer    //声明定时器
    return function(){
        let context=this   //保存上下文
        let args=arguments  //保存参数
        if(timer){
        clearTimeout(timer)}  //如果有定时器,清除定时器
        timer=setTimeout(()=>{
            fn.apply(context,args)  //执行函数
            },t)
        }
  }

节流

  • 声明定时器变量为空
  • 返回函数
  • 判断如果没有定时器,声明定时器,执行函数
  • 销毁定时器
js 复制代码
function throttle(fn,t){
    let timer=null
    return function(){
        let context=this
        let args=arguments
        if(!timer){
            timer=setTimeout(()=>{
                fn.apply(context,args)
                timer=null
            },t)
        }
    }
}

浅拷⻉

js 复制代码
//数组的浅拷贝
let ar=[1,2,3]
let br=ar.concat()
let cr=ar.slice()
let dr=[...ar]

console.log(br,cr,dr)
js 复制代码
//对象的浅拷贝
const obj={
    name:"zhangsan "
}
const newobj={...obj}
const newobj2=Object.assign(obj)
console.log(newobj,newobj2)
  • 先判断要拷贝的对象,是不是对象类型,不是的话,直接返回
  • 新建一个对象或者数组 用来结果返回
  • 然后遍历对象的可枚举属性
  • 将老对象赋值给新对象
  • 返回新对象
js 复制代码
function shallowcopy(obj) {
    // 如果不是对象,直接返回
    if (typeof obj!== 'object' || obj === null) {
        return obj;
    }
    // 判断是数组还是对象,创建相应的新对象
    let newobj = Array.isArray(obj)? [] : {};
    // 遍历对象的所有可枚举属性
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 复制属性值
            newobj[key] = obj[key];
        }
    }
    return newobj;
}

深拷贝

js 复制代码
const obj={
    name:"zhangsan ",
    fa:{
        age:18
    }
}
方法一
const deepobj=JSON.parse(JSON.stringify(obj))
方法二
const _ = require('lodash');
const deepobj2=_.cloneDeep(obj)
输出结果
console.log(deepobj,deepobj2)
js 复制代码
使用了,weakmap,当函数不再使用的时候,可以垃圾回收,不会导致内存泄漏
使用闭包,实现数据的私有,避免影响全局变量
function  deepClone(target){
    const map=new WeakMap() 

    function _deepClone(target){

        if(typeof target!=='object'||target===null) { return target} // 不是引用类型的,直接返回

        if(map.has(target))
        {return map.get(target)}          //判断缓存里面是否有,有的话,直接返回就行。避免循环引用的问题

        let newTarget=Array.isArray(target)?[]:{}  // 判断是否为数组
         
        map.set(target,newTarget)  // 缓存里面没有
      
        for(let key in target){   // 循环拷贝
            if(target.hasOwnProperty(key)){
                newTarget[key]=_deepClone(target[key])
            }
        }
        return newTarget  // 返回拷贝后的对象 
 }
 return _deepClone(target)
}

new

  • 创建一个新对象
  • 让新对象的对象原型指向构造函数的原型对象
  • 执行构造函数,并把构造函数的this指向新创建出来的对象
  • 返回创建后的结果;
js 复制代码
function myNew(constructor, ...args) {
    // 创建一个新对象
    const obj = {};
    // 让新对象的原型指向构造函数的原型
    obj.__proto__ = constructor.prototype;
    // 执行构造函数,并且把 this 绑定到新对象上
    const result = constructor.apply(obj, args);
    // 若构造函数返回一个对象,则返回该对象;否则,返回新创建的对象
    return typeof result === 'object' && result!== null? result : obj;
}

instanceof

判断 是不是当前原型链上的属性

js 复制代码
function ins(target,type){
target=target.__proto__
type=type.prototype
while(true){
    if(target===null){
        return false
    }
    if(target===type){
        return true
    }
    target=target.__proto__
}
}

flat

  • 将多维数组转化为一维数组
  • 创建一个结果数组
  • this指向的是调用的数组,item就是数组里面的每一项
  • 对每一项进行判断,如果还是数组,递归调用函数。将结果和之前的结果拼接起来
  • 不是数组的话,直接将元素push进
  • 返回结果数组
js 复制代码
Array.prototype.falten= function (){
    let flat=[]
    for(let item of this){
        if(Array.isArray(item)){
            flat=flat.concat(item.falten())
        }else{
            flat.push(item)
        }
    }
    return flat
}

url解析

参考:htps://juejin.cn/post/7388057629773889562

完整的 URL 信息包括以下几点:

  • 协议(protocol):采用的协议方案;
  • 登录信息(username & password):(可选项)指定用户名和密码,用来从服务器获取资源时的认证信息;
  • 服务器地址(hostname):待访问的服务器地址。可以是域名形式也可以是 IP 地址;
  • 服务器端口号(port):;(可选项)指定服务器连接网路的端口号;
  • 带层次的文件路径(pathname):指定服务器上的文件路径来定位特指的资源;
  • 查询字符串(search):(可选项)查询字符串参数;
  • 片段标识符(hash):(可选项)用来标记已获取资源中的子资源;

数组转树 哈希解法

js 复制代码
const arr = [
  { id: 1, parentId: null, name: 'Root' },
  { id: 2, parentId: 1, name: 'Child 1' },
  { id: 3, parentId: 1, name: 'Child 2' },
  { id: 4, parentId: 2, name: 'Grandchild 1' },
]

 function arraytotree(arr){
   const map=new Map()
   for(let item of arr){     //用空间换时间 id:数组的每一项
    map.set(item.id,item)
   }
   const roots=[]  //根节点数组
   for(let item of arr){
    if(item.parentId===null){  //说明是根节点
        roots.push(item)
    }else{
        const parent=map.get(item.parentId)  //找到当前节点的父节点
        if(!parent.children){        //父节点没有children 属性,给他加一个孩子属性
            parent.children=[]
        }
        parent.children.push(item)  //把子项放入父亲的子节点中
    }
   }
}
相关推荐
恋猫de小郭19 分钟前
Android Studio Cloud 正式上线,不只是 Android,随时随地改 bug
android·前端·flutter
清岚_lxn5 小时前
原生SSE实现AI智能问答+Vue3前端打字机流效果
前端·javascript·人工智能·vue·ai问答
ZoeLandia5 小时前
Element UI 设置 el-table-column 宽度 width 为百分比无效
前端·ui·element-ui
橘子味的冰淇淋~6 小时前
解决 vite.config.ts 引入scss 预处理报错
前端·vue·scss
小小小小宇8 小时前
V8 引擎垃圾回收机制详解
前端
lauo8 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
拉不动的猪8 小时前
设计模式之------单例模式
前端·javascript·面试
一袋米扛几楼988 小时前
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
前端·react.js·前端框架
Alt.98 小时前
SpringMVC基础二(RestFul、接收数据、视图跳转)
java·开发语言·前端·mvc
进取星辰9 小时前
1、从零搭建魔法工坊:React 19 新手村生存指南
前端·react.js·前端框架