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

刷刷前端手写题

闭包用途

闭包

闭包让你可以在一个内层函数中访问到其外层函数的作用域

防抖

描述

        前面所有触发都被取消,最后一次执行,在规定时间之后才会触发,也就是说如果连续快速的触发,用户操作频繁,但只会执行一次

        常用场景:输入框输入

代码实现

1、lodash的debounce函数

2、 当用户点击按钮时,debounce 包装的 getBtnValue 函数会延迟 3000 毫秒执行。如果在这 3000 毫秒内用户再次点击按钮,那么之前的定时器会被清除,重新开始计时。因此,getBtnValue 函数只会在用户停止点击 3000 毫秒后才执行

function debounce(fn,apply){let timer;// 初始状态下,timer是undefinedreturn function(){// 如果timer有值,清除之前的定时器if(timer) {clearTimeout(timer);}timer = setTimeout(()=>{fn.apply(this,args)},delay)} 
}
function getValue(e){console.log('1111')
}
const btn = document.createElement('button')
btn.innerHTML = 'btn'
document.body.appendChild(btn)
btn.onclick = debounce(getValue, 3000)

         浏览器环境:timer 会被赋值为一个整数,例如 1、2、3 等;Node.js 环境:timer 会被赋值为一个 Timeout 对象。

节流

描述

有规律执行,减少时间执行次数,拖放,滚屏;

只会在第一个点击时执行一次,后续点击将被忽略,直到 delay时间过去后才能再次执行

代码实现

        function throttle(func, delay) {let timer; // 用于保存定时器标识符return function() {if (timer) return; // 如果 timer 已经存在,说明在 delay 时间内已经触发过,直接返回,跳过本次调用const args = arguments; // 保存当前的参数const context = this; // 保存当前的执行上下文// 设置一个定时器,在 delay 毫秒后执行 functimer = setTimeout(() => {func.apply(context, args); // 执行原始函数,传递当前上下文和参数timer = null; // 重置 timer,表示可以再次触发 func}, delay);};}const btn = document.createElement('button')btn.innerHTML = 'btn'document.body.appendChild(btn)function handleClick() {console.log('Button clicked!');}btn.onclick = throttle(handleClick, 3000);
  • 点击第一次:创建 timer,设置 delay 毫秒后执行 func
  • delay 期间再次点击:由于 timer 存在,函数直接返回,不会再次执行 func
  • delay 时间到达func 被执行,timer 被重置为 null
  • 允许新的点击执行:可以再次创建新的 timer 并触发 func。

因此,尽管多次点击,只有第一次点击时创建的定时器会生效!!

函数柯里化

描述

使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

代码实现

function curry(fn){let args = []return function res(...rest){if(arguments.length==0){//当没有参数传递给 res 时于是调用 fn(...args)return fn(...args)}else{args.push(...rest)return res}}
}
var sumFn = function(...arr){return arr.reduce((prev,cur)=>{return prev+cur})
}
let res = curry(sumFn)(1)(2)(3,4)() //15

手写New

描述

  new 操作符的主要作用是生成一个新对象,并将这个对象与构造函数的原型连接起来,同时构造函数中的代码会在新对象的上下文中执行,给新对象赋予属性和方法。

主要流程是:const person1 = new Person('Alice', 25);

  • 新建一个对象const person1 = {};
  • 设置原型person1.__proto__ = Person.prototype;//隐式原型指向构造函数的显示原型
  • 绑定 this:执行 Person 构造函数时,this 被绑定到 person1
  • 执行构造函数:在 Person 函数中,this.name = name;name 赋值给 person1
  • 返回对象:如果没有显式返回对象,new 操作符会返回 person1

代码实现

function Person(a){// 检查 this 是否是 Person 的实例//if (!(this instanceof Person)) {//throw new Error("Person 只能通过 new 关键字调用");//}this.a=a
}
function myNew(fn,...args){const obj={};obj._proto_=fn.prototypefn.apply(obj,args)return obj
}
const obj = myNew(Person,123)

数组去重

描述

顾名思义:console.log(uniqueArray([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5])); // [1, 2, 3, 4, 5, 6]

代码实现

const uniqueArray = (arr) => {return [...new Set(arr)]
}

实现正则切分千分位(js)

描述

顾名思义:console.log(formatThousands(123456789)); // 输出: 123,456,789

代码实现

function format(num){//将数字转为字符串并分割整数和小数部分let arr = String(num).split(.)let char = arr[0].split('').reverse()return char.reduce((pre,cur,curIndex)=>{if(curIndex+1) %3 ===0 && curIndex !==char.length -1){return ','+cur+pre}return cur+pre},"")    
}

手写call/apply

描述:通过使用call/apply方法,可以将一个对象的方法应用到另一个对象上,区别是传入参数一个是参数列表,一个是数组;都是立即执行

代码实现

Function.prototype.myCall = function(context,...args){if (typeof this!=="function"){throw new TypeError("被调用的必须是函数")}context||globalThis//用Symbol来创建唯一的fn,防止名字冲突const fn = Symbol('key')// this是调用myCall的函数test,将函数绑定到上下文对象的新属性上context[fn] = thisconst res =  context[fn](...args)//hello,worlddelete context[fn]return res
}const test = {name:"xxx",hello: function(){console.log(`hello,${this.name}!`);}
}
const obj = {name:"world"};
test.hello.myCall(obj);//hello,world

手写Bind

描述

与call和apply方法不同,bind方法并不会立即执行函数,而是返回一个新函数,可以稍后调用;

且参数可以分多次传入

代码实现

Function.prototype.myBind = function(thisArg,...args1){const fn = this;return function(...args2){if(typeof fn!=="function"){throw new TypeError("被调用的是函数")}thisArg = thisArg||globalThis;let uniqueFn = Symbol("fn")thisArg[uniqueFn] = fn;//合并参数并调用函数const res = thisArg[uniqueFn](...args1,...args2)delete thisArg[uniqueFn]return res}
}
function greet(param1,param2) {console.log(`${param1},${this.name}${param2}`)   
}
const boundGreet = greet.myBind(obj,"Hey");
boundGreet("!!")// "Hey, Alice!!"

扁平化

描述

将多维转为一维

代码实现--数组

遍历,检查是数组,递归,不是数组扔进去

let arr = [1, [2, 3], [4, [5, 6, [7, 8]]]];
function flatten(arr){let res = []let len = arr.lengthfor (let i=0;i<len;i++){if(Array.isArray(arr[i])){res.concat(flatten(arr[i]))}else{res.push(arr[i])}}return res
}

代码实现--对象

function flattenObj(){let res = {}for (let key in obj){if(typeof obj[key] ==='object'&& obj[key] !==null){flatten(res,obj[key],`${key}`)}else{res[key]=obj[key]}}function flatten(res,obj,keyname){for(let key in obj){if(typeof obj[key] ==='object'&& obj[key] !==null){flatten(res,obj[key],`${keyname}.${key}`)}else{res[`${keyname}.${key}`]=obj[key]}}}return res
}const obj = {a: 1,b: [1, 2, { c: true }],c: { e: 2, f: 3 },g: null,};
let res = flattenObj(obj)
结果:{a: 1,'b.0': 1,'b.1': 2,'b.2.c': true,'c.e': 2,'c.f': 3,g: null
}

模拟Promise.all()

描述

        入参是个Promise实例组成的数组,返回值是个promise,因为可以使用.then,如果全部成功,状态变为resolved, 并且返回值组成一个数组传给回调,但凡有一个失败,状态变为rejected, 并将error返回给回调

代码实现

// 添加一个自定义的静态方法
Promise.MyAll = function(promises){let arr = []count = 0return new Promise((resolve,reject)=>{promises.forEach((item,i)=>{//将 item 转换为一个 PromisePromise.resolve(item).then(res=>{arr[i]=rescount+=1if(count === promises.length) resolve(arr)}).catch(reject)})})
}

 测试

const p1 = Promise.resolve('p1')
const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('p2')}, 500)
})
Promise.MyAll([p1, p2]).then(res => console.log(res))//['p1','p2'].catch(err => console.log(err))

模拟Promise.race()

描述

返回状态以最快的那个为准

代码实现

Promise.MyRace(promises=>{return new Promise((resolve,reject)=>{for(const x of promises){Promise.resolve(x).then(resolve,reject)}})
})

观察者模式

描述

        观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新

例如公司(被观察者)发中秋福利给员工(观察者)

代码实现

//被观察者
class Subject{constructor(){this.observerList = []}addObserver(observer){this.observerList.push(observer)}removeObserver(observer){const index = this.observerList.findIndex(o => o.name===observer.name)this.observerList.splice(index,1)}notifyObservers(message){const observers = this.observerList;observers.forEach(observer=>observer.notified(message))}
}
//观察者
class Observer{constructor(name,subject){this.name = name;if(subject){subject.addObserver(this)}}notified(message){console.log(this.name,message)}
}

 测试

const subject = new Subject();
const observerA = new Observer('observerA', subject);
subject.notifyObservers('Hello from subject');//observerA Hello from subject

常见使用场景 

        数据绑定机制通常采用观察者模式。当数据模型变化时,所有绑定了该数据的组件(观察者)都会自动更新。例如,一个购物车系统,当用户添加商品到购物车时,购物车总价会自动更新。这个过程可以通过观察者模式来实现

订阅者模式

描述

发布-订阅是一种消息范式,消息的发送者(发布者)不会将消息直接发送给特定的接收者(订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在

例如:公司发快递给消费者

代码实现

class Publisher {constructor(name, context) {this.name = name; // 设置发布者的名称this.context = context; // 设置发布者所属的 PubSub 实例}publish(type, content) {this.context.publish(type, content); // 调用 PubSub 实例的 publish 方法,发布消息}
}class Subscriber {constructor(name, context) {this.name = name; // 设置订阅者的名称this.context = context; // 设置订阅者所属的 PubSub 实例}subscribe(type, cb) {this.context.subscribe(type, cb); // 调用 PubSub 实例的 subscribe 方法,订阅某个消息类型}
}class PubSub {constructor() {this.messages = {}; // 存储已发布的消息,按消息类型存储this.listeners = {}; // 存储订阅者回调函数,按消息类型存储}publish(type, content) {const existContent = this.messages[type]; // 检查是否已有该类型的消息if (!existContent) {this.messages[type] = []; // 如果没有,初始化一个数组来存储该类型的消息}this.messages[type].push(content); // 将消息内容添加到对应类型的消息数组中}subscribe(type, cb) {const existListener = this.listeners[type]; // 检查是否已有订阅者监听该类型的消息if (!existListener) {this.listeners[type] = []; // 如果没有,初始化一个数组来存储该类型的订阅者回调函数}this.listeners[type].push(cb); // 将订阅者的回调函数添加到对应类型的监听数组中}notify(type) {const messages = this.messages[type]; // 获取该类型的所有已发布的消息const subscribers = this.listeners[type] || []; // 获取该类型的所有订阅者回调函数subscribers.forEach((cb, index) => cb(messages[index])); // 将对应的消息传递给订阅者的回调函数}
}

 测试

const TYPE_A = 'music'; // 定义一个消息类型
const pubsub = new PubSub(); // 创建一个 PubSub 实例const publisherA = new Publisher('publisherA', pubsub); // 创建一个发布者,并与 PubSub 实例关联
publisherA.publish(TYPE_A, 'we are young'); // 发布者发布一条类型为 'music' 的消息,内容是 'we are young'const subscriberA = new Subscriber('subscriberA', pubsub); // 创建一个订阅者,并与 PubSub 实例关联
subscriberA.subscribe(TYPE_A, res => {console.log('subscriberA received', res); // 订阅者订阅 'music' 类型的消息,并定义回调函数处理接收到的消息
});pubsub.notify(TYPE_A); // 通知所有订阅了 'music' 类型的订阅者,调用他们的回调函数并传递消息

常见使用场景 

事件总线:不同组件之间不直接通信,而是通过事件总线来发布和订阅事件。这使得组件之间高度解耦,组件可以独立发展

手写vuex

描述

Vuex 是 Vue.js 的状态管理模式,主要解决组件之间共享状态时的问题

代码实现

相关文章:

刷刷前端手写题

闭包用途 闭包 闭包让你可以在一个内层函数中访问到其外层函数的作用域 防抖 描述 前面所有触发都被取消&#xff0c;最后一次执行&#xff0c;在规定时间之后才会触发&#xff0c;也就是说如果连续快速的触发&#xff0c;用户操作频繁&#xff0c;但只会执行一次 。 常用场…...

论文解读:LONGWRITER: UNLEASHING 10,000+ WORD GENERATION FROM LONG CONTEXT LLMS

摘要 现象&#xff1a;当前的大预言模型可以接受超过100,000个tokens的输入&#xff0c;但是却难以生成超过2000个token的输出。 原因&#xff1a;监督微调过程(SFT)中看到的样本没有足够长的样本。 解决方法&#xff1a; Agent Write&#xff0c;可以将长任务分解为子任务&a…...

一文了解Ansible原理以及常见使用模块

ansible使用手册 1. 简述 Ansible 是一种开源的自动化工具&#xff0c;主要用于配置管理、应用程序部署和任务自动化。 它使用简单的 YAML 语言来定义自动化的任务【playbook】&#xff0c;使得配置和部署变得更加直观和易于管理。 基于SSH协议连接到远程主机来执行指令。 2…...

JavaEE从入门到起飞(九) ~Activiti 工作流

工作流 当一道流程逻辑需要用到多个表单的提交和多个角色的审核共同完成的时候&#xff0c;就可以使用工作流。 工作流一般使用的是第三方技术&#xff0c;也就是说别人帮你创建数据库表和service层、mapper层&#xff0c;你只需要注入工具接口即可使用。 原理&#xff1a;一…...

微服务的保护

一、雪崩问题及解决方案 1.雪崩问题 微服务之间&#xff0c;一个微服务依赖多个其他的微服务。当一个微服务A依赖的一个微服务B出错时&#xff0c;微服务A会被阻塞&#xff0c;但其他不依赖于B的微服务不会受影响。 当有多个微服务依赖于B时&#xff0c;服务器支持的线程和并…...

2024前端面试题-网络篇

1.跨域问题 同源策略&#xff1a;需要协议、域名、端口号相同跨域原因&#xff1a;不符合同源策略便会产生跨域问题解决跨域&#xff1a;JSONP、配置代理、通过CORS解决 2.RPC和HTTP的区别 主要区别是序列化和反序列化&#xff0c;RPC通过二进制高效传输&#xff0c;HTTP是j…...

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——6.vector

1.杨辉三角 . - 力扣&#xff08;LeetCode&#xff09; 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> arr;int i 0;int j 0;for (i…...

设计模式---简单工厂模式

简单工厂模式&#xff08;Simple Factory Pattern&#xff09; 是一种创建型设计模式&#xff0c;它定义了一个工厂类&#xff0c;通过这个工厂类可以创建不同类型的对象。简单工厂模式的主要目的是将对象的创建逻辑集中在一个地方&#xff0c;简化客户端的代码&#xff0c;使得…...

Vue | Vue 中的 refInForde 用法

refInFor&#xff1a;如果你在渲染函数中给多个元素都应用了相同的 ref 名&#xff0c;那么 $refs.myRef 会变成一个数组。 vue中的refInFor属性是Vue框架中用于在循环渲染的元素上设置引用的一种方式。‌ 在Vue中&#xff0c;‌ref属性通常用于给元素或子组件注册引用信息&am…...

【原创】java+swing+mysql房屋租赁管理系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 文末有本人名片&#xff0c;希望和大家…...

Django 中render、redirect 和 HttpResponse的区别

在 Python 的 Web 框架 Django 中&#xff0c;render, redirect 和 HttpResponse 是用于处理 HTTP 响应的不同函数&#xff0c;它们各自有不同的用途&#xff1a; HttpResponse&#xff1a; HttpResponse 是 Django 中最基本的响应对象&#xff0c;用于返回给客户端的 HTTP 响应…...

CRYPTO 2020

分类文章编号安全模型1-6公钥加密,功能加密,见证加密7-12后量子密码13-20密码分析21-31最佳论文32-34多方安全计算35-49真实应用50-55零知识证明56-62格和相关难题63-68泄露和外包加密69-74非交互式零知识证明,共识和延迟函数75-79构建80-85Security Models 1. Handling Ad…...

java 函数接口Consumer简介与示例【函数式编程】【Stream】

Java 8 中的 消费者接口Consumer 是一个函数接口&#xff0c;它可以接受一个泛型 类型参数&#xff0c;它属于java.util.function包。我们来看看Java函数接口库中的定义&#xff1a; FunctionalInterface public interface Consumer<T> {/*** Performs this operation o…...

黑神话:悟空-配置推荐

显卡推荐&#xff08;按类别整理&#xff09; 1. GTX 10系列、GTX 16系列&#xff1a; 如果希望体验光线追踪&#xff0c;建议根据预算升级到RTX 40系列显卡。对于1080p分辨率&#xff0c;至少需要RTX 4060才能流畅运行。 2. RTX 20系列&#xff1a; RTX 2060、RTX 2070&#…...

Android14 蓝牙设备类型修改

Android14 蓝牙设备类型设置修改设置 文章目录 Android14 蓝牙设备类型设置修改设置一、前言二、修改蓝牙设备类型1、蓝牙设备类型和对应的属性2、Debug设备设置和获取蓝牙设备类型3、系统源码中设置蓝牙设备类型4、Java代码中设置蓝牙prop属性可行吗&#xff1f; 三、其他1、A…...

vue3 语法糖<script setup>

在 Vue 3 中&#xff0c;<script setup>是一种新的语法糖&#xff0c;它极大地简化了组件的编写方式。 <script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。 基本概念 简洁的语法&#xf…...

微服务设计原则——高性能:异步与并发

文章目录 1.异步1.1 调用异步1.2 流程异步1.3 数据流异步1.4 小结 2.并发2.1 请求并发2.2 冗余请求2.3 小结 参考文献 1.异步 对于处理耗时长的任务&#xff0c;如果采用同步等待的方式&#xff0c;会严重降低系统的吞吐量&#xff0c;可以采用异步化进行解决。 异步&#xf…...

机器学习——决策树,朴素贝叶斯

一.决策树 决策树中的基尼系数&#xff08;Gini Index&#xff09;是用于衡量数据集中不纯度&#xff08;或混杂度&#xff09;的指标。基尼系数的取值范围在0到0.5之间&#xff0c;其中0表示数据完全纯&#xff08;同一类别&#xff09;&#xff0c;0.5表示数据完全混杂。 基…...

C语言基础(十)

编译预处理命令&#xff1a; 预编译命令在C语言中用于在编译前进行一些特定的处理和控制&#xff0c;帮助程序员更灵活地管理源代码和控制编译过程。 C语言常用的预编译命令&#xff1a; #include&#xff1a;用于包含头文件&#xff0c;将另一个文件的内容插入到当前文件中…...

人像比对-人证比对-人脸身份证比对-人脸身份证实名认证-人脸三要素对比-实人认证

人脸身份证实名认证是一种基于生物识别技术的身份验证方式&#xff0c;主要依托证件OCR识别技术、活体检测、人脸比对等技术手段&#xff0c;对用户身份信息真实性进行核验&#xff0c;确保用户为真人且为本人。以下是关于人脸身份证实名认证的详细解析&#xff1a; 一、认证流…...

Android 上下滑隐藏显示状态栏

一、DisplayPolicy类中监听滑动事件&#xff0c;然后发送广播事件 Android12类路径&#xff1a; frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.javamSystemGestures new SystemGesturesPointerEventListener(mUiContext, mHandler,new SystemGest…...

USBCAN-II/II+使用方法以及qt操作介绍

一.USBCAN-II/II介绍 USBCAN-II/II 是一款常用的 USB-CAN 转换器&#xff0c;广泛应用于汽车电子、工业自动化等领域。以下是使用该设备的一般步骤和方法&#xff1a; 1. 硬件连接 连接设备&#xff1a;将 USBCAN-II/II 的 USB 接口连接到计算机的 USB 端口。 连接 CAN 网络…...

笔记-系统规划与管理师-案例题-2022年-IT服务部署实施

【说明】 某大型企业去年信息化投入大&#xff0c;完成了重点核心业务系统的建设。由于应急相应预案制定得不充分并且未开展演练&#xff0c;出现了系统性故障时&#xff0c;部分关键的应用系统不可用且在12小时内未能完成恢复业务&#xff0c;给企业带来了较大损失。 为加强该…...

Kubernetes 清理资源常用的 Kubernetes 清理命

清理特定状态的 Pod&#xff1a; 清理 Evicted 状态的 Pod&#xff1a; kubectl get pods --all-namespaces -o wide | grep Evicted | awk {print $1,$2} | xargs -L1 kubectl delete pod -n清理 Error 状态的 Pod&#xff1a; kubectl get pods --all-namespaces -o wide | g…...

【数据结构初阶】二叉树--基本概念

hello&#xff01; 目录 一、树 1.1 树的概念和结构 1.2 树的相关术语 1.3 树的表示 1.4 树形结构实际应用场景 二、二叉树 2.1 概念和结构 2.2 特殊的二叉树 2.2.1 满二叉树 2.2.2 完全二叉树 2.3 二叉树的存储结构 2.3.1 顺序结构 2.3.2 链式结构 …...

Pytorch添加自定义算子之(12)-开闭原则设计tensorrt和onnxruntime推理语义分割模型

一、开闭原则 开闭原则是SOLID原则中的一个,指的是尽量使用开放扩展,关闭修改的设计原则。 在C++中如何使用开闭原则导出动态库,可以按照以下步骤进行: 定义抽象基类:定义动态库中的抽象基类,该基类应该封装可扩展的接口。 实现派生类:实现基类的派生类,这些派生类将封…...

第二百零九节 Java格式 - Java数字格式类

Java格式 - Java数字格式类 以下两个类可用于格式化和解析数字: java.text.NumberFormatjava.text.DecimalFormat NumberFormat 类可以格式化一个数字特定地区的预定义格式。 DecimalFormat 类可以格式化数字以特定区域设置的自定义格式。 NumberFormat类的 getXXXInstance…...

LSI-9361阵列卡笔记

背景 要将raid0更改为JBOD直通模式 注意的点是要先将raid模式调整为JBOD之后重启机器&#xff0c;即可 备注&#xff1a;转换过程中硬盘中的数据未丢失。 步骤贴图 refer https://zhiliao.h3c.com/questions/dispcont/123250 https://blog.csdn.net/GreapFruit_J/article/…...

ArcGIS热点分析 (Getis-Ord Gi*)——基于地级市尺度的七普人口普查数据的热点与冷点分析

先了解什么是热点分析 ? 热点分析 (Getis-Ord Gi*) 是一种用于空间数据分析的技术&#xff0c;主要用于识别地理空间数据中值的聚集模式&#xff0c;可以帮助我们理解哪些区域存在高值或低值的聚集&#xff0c;这些聚集通常被称为“热点”或“冷点”&#xff0c;Gi* 统计量为…...

ASIACRYPT 2021

分类文章编号获奖论文1-3后量子密码4-9多方计算10-15物理攻击,泄露和对策16-21理论22-27公钥密码和鉴权密钥交换28-33高级加密和签名34-39对称密钥构建40-46量子安全47-53获奖论文54对称密码分析55-66增强型公钥加密和时间锁难题67-72同态加密和加密搜索73-77NIZK和SNARK78-80…...