代码编织梦想

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近24届秋招也在如火如茶地进行中,小编也是在实习之余,利用有限的时间来准备秋招,今天分享前端几个常见的手写题:


一、Promise.all

/**
 * 
 * @param {*} promises 
 * @returns 
 * Promise.all(iterable) 方法返回一个 Promise 实例,
 * 此实例在 iterable 参数内所有的 promise 都“完成(resolvedresolved)”或
 * 参数中不包含 promise 时回调完成(resolveresolve);如果参数中 promise
 *  有一个失败(rejectedrejected),此实例回调失败(rejectreject),
 * 失败的原因是第一个失败 promise 的结果。

 */

function promiseAll(promises) {
    return new Promise((resolve,reject)=> {
        if(!Array.isArray(promises)) {
            return reject(new TypeError('arguments must be an array'))
        }
        var resolvedCounter = 0
        var promiseNum = promises.length;
        var resolvedValues = new Array(promiseNum);

       for(let i = 0; i < promiseNum; i++) { 
            (function(i){
                Promise.resolve(promises[i]).then(function(value){
                    resolvedCounter++
                    resolvedValues[i] = value
                    if(resolvedCounter == promiseNum) {
                        return resolve(resolvedValues)
                    }
                },function(reason){
                    console.log(reason);
                    reject(reason)
                })
            })(i)
       }
    })
}


var p1 = Promise.resolve(1),
    p2 = Promise.resolve(2),
    p3 = Promise.resolve(3);
promiseAll([p1,p2,p3]).then(function(res) {
    console.log(res);
})
Promise.all([p1,p2,p3]).then(function(res) {
    console.log(res);
})

二、防抖函数

// 改进
export function debounce<Fn extends Function>(fn:Fn, delay:number,immediate = false) {
    let timeout: number | undefined
    const debounced = function(args:any) {
        const later = () => {
            timeout = undefined
            if(!immediate) {
                fn.apply(null,args)
            }
        }
        // 判断是否立即执行
        const callNow = immediate && !timeout // timeout没有意味着还没有计时器
        clearTimeout(timeout)
        timeout = setTimeout(later,delay)
        // 如果需要立即执行,则立即执行
        if(callNow) {
            fn.apply(null, args)
        }
    }
    debounced.cancel = function() {
        clearTimeout(timeout)
        timeout = undefined
    }   
}

三、节流

export function throttle<Fn extends Function>(fn:Fn, delay:number, immediate = false) {

    // 最后一次执行的时间
    let last = Date.now()

    return function (args:any) {
        // 当前时间
        let now = Date.now()
        //当前距离上一次执行的时间大于间隔时间 
        if(now - last >= delay) {
            fn.apply(null, args)
            last = now
        }
    }
}

四、数据扁平化

var arr = [1, [2, [3, 4]]];
const res = [];
function flatten(arr) {
  arr.map((item) => {
    if (Array.isArray(item)) {
      flatten(item);
    } else {
      res.push(item);
    }
  });
  return res;
}

function flattens(arr) {
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}

//console.log(flatten(arr));
//console.log(flattens(arr));
console.log([].concat(...arr));
// 原地解法
const arr1 = [0, 1, 2, [[[3, 4]]]];

console.log(arr1.flat(3)); // 3 代表数组内最多嵌套层数
// expected output: [0, 1, 2, 3, 4] 

五、简单手写Vue双向数据绑定

class Vue {
  constructor(options) {
    this.$options = options
    this.$data = options.data

    // 对data做响应式处理
    observe(this.$data)
    // 代理data到vm上
    proxy(this)

    //执行编译
    new Complie(options.el, this)
  }
}
//对data选项执行响应式具体操作

function observe(obj) {
  if (typeof obj !== "object" || obj == null) {
    return
  }
  new Observer(obj)
}

class Observer {
  constructor(value) {
    this.value = value
    this.walk(value)
  }
  walk(obj) {
    Object.keys(obj).forEach((key) => {
      defineReactive(obj, key, obj[key])
    })
  }
}

// 编译过程
class Compiler {
    constructor(el,vm) {
        this.$vm = vm
        this.$el = document.querySelector(el) // 获取dom元素
        if(this.$el) {
            this.compile(this.$el)
        }
    }
    compile(el) {
        const childNodes = el.childNodes
        Array.from(childNodes).forEach(node => {
            if(this.isElement(node)) {  //判断是否为节点
                console.log("编译元素" + node.nodeName);
            }
            else if (this.isInterpolation(node)) {
                console.log('编译插值文本' + node.textContent); // 判断是否为插值文本 {{}}
            }
            if(node.childNodes && node.childNodes.length > 0) {  // 判断是否有子元素
                this.compile(node) // 对子元素进行递归遍历 
            }
        })
    }
    isElement(node) {
        return node.nodeType == 1
    }
    isInterpolation(node) {
        return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent)
    }
}

// 负责更新视图
class Watcher {
    constructor(vm,key,updater) {
        this.vm = vm
        this.key = key
        this.updateFn = updater
        // 创建实例时,把当前实例指定到Dep.target静态属性上
        Dep.target = this
        // 读一下key ,触发get
        this.vm[this.key]
        // 置空
        Dep.target = null
    }

    // 未来执行dom更新函数,由dep调用
    update() {
        this.updateFn.call(this.vm,this.vm[this.key])
    }
}
// 声明一个Dep
class Dep {
    constructor() {
        this.deps = []
    }
    addDep(dep){
        this.deps.push(dep)
    }
    notify() {
        this.deps.forEach((dep)=> dep.update())
    }
}

// 依赖收集创建Dep实例

function defineReactive(obj,key,val) {
     this.observe(val)
     const dep = new Dep()
     Object.defineProperty(obj, key, {
        get() {
            Dep.target && dep.addDep(Dep.target)  // Dep.target也就是Watcher实例
            return val
        },
        set(newVal) {
            if(newVal === val) return
            dep.notify() // 通知dep执行更新方法
        }
     })
}


六、手写深拷贝

在这里插入图片描述

七、手写call

在这里插入图片描述

八、实现LPU缓存算法

class LRUCache {
    #map; // 私有属性
    #length; // 私有属性
    constructor(length) {
        this.#map = new Map()
        this.length = length
    }

    get(key) {
        if(!this.#map.has(key)) {
            return
        }
        const value = this.#map.get(key)
        // 删除之前的数据
        this.#map.delete(key)
        // 再把数据加进去
        this.#map.set(key,value)
        return value
    }

    set(key,value) {
        // 如果之前有这条数据,就删掉
        if(this.#map.has(key)) {
            this.#map.delete(key)
        }
        // 统一变成添加行为
        this.#map.set(key,value)
        if(this.#map.size > this.#length) {
            const firstKeyValue = this.#map.keys().next().value
            // 如果大于最大长度,我们需要删除第一个key值
            this.#map.delete(firstKeyValue)
        }
    }
}

总结

以上就是今天要讲的内容,期望大家秋招都能成功拿到心仪的offer!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/bin_123ge/article/details/132926570

vue3表单-爱代码爱编程

文章目录 Vue3表单1. 概念2. 输入框3. 复选框4. 单选按钮5. select下拉列表5.1 下拉列表单选5.1 下拉列表多选时绑定到数组5.3 使用 v-for 循环输出选项 6. 值绑定7

前端设计模式和设计原则之设计原则-爱代码爱编程

前端设计原则 1 开闭原则 该原则指出软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,在添加新功能时,应该通过扩展现有代码来实现,而不是直接修改已有的代码。这样可以确保现有代码的稳定性,并且减少对其他部

[js电子榨菜]事件传递机制 event propogate-爱代码爱编程

(这篇文章可能图片会少一些,理解一下),毕竟这个币设备实在不太灵敏 其实在vue操作事件的时候,我们经常可以了解到一个“修饰”stop,官方给出的解释是阻止事件冒泡传递。冒泡传递其实值得是事件传递过程中的一个阶段(bubble)。 接下来将从js原生的角度讲解事件传递机制 1.propogate's phases 事件传播从生成,到对应dom全

js-数字格式化千分位-爱代码爱编程

数字格式化千分位1234567890 转 1,234,567,890 1、while循环 <template> <div>{{ num | formatNum }}</div> </template> <script> export default { data() {

4.1.5-检查网页内容是否存在信息泄露-爱代码爱编程

检查网页内容是否存在信息泄露 IDWSTG-INFO-05 总结 程序员在他们的源代码中包含详细的注释和元数据是很常见的,甚至建议这样做。但是,HTML 代码中包含的注释和元数据可能会泄露潜在攻击者不应获得的内部信息。

vue知识系列(4)每天10个小知识点-爱代码爱编程

目录 系列文章目录Vue知识系列(1)每天10个小知识点Vue知识系列(2)每天10个小知识点Vue知识系列(3)每天10个小知识点 知识点**31. Vuex 四种属性的概念、作用、使用示例****32

vue3 - setup之defineemits-爱代码爱编程

基础形式 子组件 const emits = defineEmits(['name']) //触发emits事件 const eventButton = () => { emits('name') }

react-实现循环轮播-爱代码爱编程

问题:写字体轮播的时候,不使用swiper库,使用top定位,让字体过渡上下移动,发现写成的效果就是每次播到最后一个元素后,只能突然展示第一个元素,失去了那种上下移的动过渡效果。 ss 解决:

vue列表跳转详情,记录列表滚动不变-爱代码爱编程

记录主元素 computed: { elTable: function() { return document.getElementsByClassName('layout-content')[0]

浅析vue中computed,method,watch,watcheffect的区别-爱代码爱编程

方法methods只要调用每次都会执行watch(惰性)只有依赖项更新才会执行回调函数,且组件初次渲染不会执行watchEffect:自动追踪依赖变化,只要依赖更新即执行回调函数,且组件初次渲染即执行回调函数computed

【校招vip】前端js语言考点之px rem等单位-爱代码爱编程

考点介绍 rem vm等问题是前端面试里的高频题型。但是不少同学并不能很清楚的说明为什么在有px单位之后,还需要rem单位?往往会往不对的自适应方向回答。 作为基础性问题,只要回答不出来,面试就通过不了,需要真正理解,而不是死记硬背...... 前端JS语言考点之px rem等单位-相关题目及解析内容可点击文章末尾链接查看! 一、考点题目 1.请你说

vue3为什么推荐使用ref而不是reactive-爱代码爱编程

为什么推荐使用ref而不是reactive reactive本身具有很大局限性导致使用过程需要额外注意,如果忽视这些问题将对开发造成不小的麻烦;ref更像是vue2时代option api的data的替代,可以存放任

web storage是什么?web storage详解-爱代码爱编程

Web Storag是HTML5引入的一个非常重要的功能,可以将数据存储在本地,如保存用户的偏好设置、复选框的选中状态、文本框默认填写的值等。用户在浏览器中刷新网页时,网页通过Web Storage就可以知道用户之前所做的一

【前端项目】博客系统(页面设计)-爱代码爱编程

文章目录 一、预期效果二、实现博客列表页三、实现博客正文页四、实现博客登录页五、实现博客编辑页 一、预期效果 代码详情见:gitee链接 💕 博客列表页效果 💕 博客详情页效果 💕