前端面试手撕编程之ES+算法

目录

ES6

防抖 

节流

防抖、节流应用

改变this

call

typeof this !== 'function'

context = context || window

context._this = this

delete context._this

bind: return _this.apply(context, [...arguments].slice(1));

深拷贝

!arr|| arr == null || typeof arr != 'object'

arr instanceof Array ?  [] :  {}

for (const key in arr)

result[key] = cloneDeep(arr[key])

setTimeout()

倒计时

setTimeout模拟实现setInterval

setInterval模拟实现setTimeout

new :Fn=[...arguments].shift()

*寄生组合式继承:call,create,constructor

Object.defineProperty(obj, prop, descriptor)

Object.create 

Object.freeze 

Object for of

*instance of

 算法

合法的URL

千位分割:num.slice(render, len).match(/\d{3}/g).join(',')

ES6

防抖 

触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,会重计算函数执行时间。

function debounce(fun,time) {let flag // 定义状态return function () {clearTimeout(flag)// 在执行之前 清除 定时器的 flag 不让他执行flag = setTimeout(() => {fun.call(this,arguments)//拿到正确的this对象,即事件发生的dom}, time)}}

节流

连续触发事件但是在 n 秒中只执行一次函数。两种方式可以实现,分别是时间戳版和定时器版。

function throttle(fun, time) {let flag // 定义一个空状态return function () { // 内部函数访问外部函数形成闭包if (!flag) { // 状态为空执行flag = setTimeout(() => {fns.apply(this, arguments) // 改变this指向 把 event 事件对象传出去flag = null // 状态为空}, time)}}}

防抖、节流应用

防止某一时间频繁触发

  • 防抖debounce:time内只执行一次
    • search搜索联想,用户在不断输入值时,用防抖来节约请求资源
    • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
  • 节流throttle: 间隔time执行
    • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
    • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

改变this

call

  1. typeof this !== 'function'
  2. context = context || window
  3. context._this = this
  4. delete context._this
    // 给function的原型上面添加一个 _call 方法Function.prototype._call = function (context) {//  判断调用者是否是一个函数  this 就是调用者if (typeof this !== 'function') {throw new TypeError('what is to be a function')}// 如果有 context 传参就是传参者 没有就是windowcontext = context || window// 保存当前调用的函数context._this = this   // 截取传过来的参数/*argumentsa: 1fn: ƒ fns()*/// 通过 slice 来截取传过来的参数const local = [...arguments].slice(1)// 传入参数调用函数let result = context._this(...local)// 删属性delete context._thisreturn result}let obj = { a: 1 }function fns(a, b) {console.log(a, b);console.log(this)}fns._call(obj, 23, 555)

bind: return _this.apply(context, [...arguments].slice(1));

深拷贝

  1. !arr|| arr == null || typeof arr != 'object'

  2. arr instanceof Array ?  [] :  {}

  3. for (const key in arr)

  4. result[key] = cloneDeep(arr[key])

 function cloneDeep(arr = {}) {// 终止递归 if (!arr|| arr == null || typeof arr != 'object' ) return arr// 用 instanceof 判断原型链上是否有该类型的原型 是 Array => [] ! Arrays =>{}let result=arr instanceof Array ?  [] :  {}// forin 循环对象的key值for (const key in arr) {//  对象 key 赋值 resultresult[key] = cloneDeep(arr[key])}return result}

setTimeout()

倒计时

​//返回值timeoutID是一个正整数,表示定时器的编号。
let timeoutID = scope.setTimeout(function[, delay]),//delay表示最小等待时间,真正等待时间取决于前面排队的消息
clearTimeout(timeoutID) //取消该定时器。

function timedCount() {c -=1;if(c===0){clearTimeout(t);return;}t = setTimeout(function() {timedCount()}, 1000);
}

setTimeout模拟实现setInterval

// 使用闭包实现
function mySetInterval(fn, t) {let timer = null;function interval() {fn();timer = setTimeout(interval, t);}interval();return {// cancel用来清除定时器cancel() {clearTimeout(timer);}};
}

setInterval模拟实现setTimeout

function mySetTimeout(fn, time) {let timer = setInterval(() => {clearInterval(timer);fn();}, time);
}// 使用
mySetTimeout(() => {console.log(1);
}, 2000);

new :Fn=[...arguments].shift()

"_new"函数,该函数会返回一个对象,

该对象的构造函数为函数参数、原型对象为函数参数的原型,核心步骤有:

  1. 创建一个新对象
  2. 获取函数参数
  3. 将新对象的原型对象和函数参数的原型连接起来
  4. 将新对象和参数传给构造器执行
  5. 如果构造器返回的不是对象,那么就返回第一个新对象
const _new = function() {const object1 = {}const Fn = [...arguments].shift()object1.__proto__ = Fn.prototypeconst object2 = Fn.apply(object1, arguments)return object2 instanceof Object ? object2 : object1
}

*寄生组合式继承:call,create,constructor

通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。要求如下:
1. 给"Human"构造函数的原型上添加"getName"函数,该函数返回调用该函数对象的"name"属性
2. 给"Chinese"构造函数的原型上添加"getAge"函数,该函数返回调用该函数对象的"age"属性

  1. 在"Human"构造函数的原型上添加"getName"函数
  2. 在”Chinese“构造函数中通过call函数借助”Human“的构造器来获得通用属性
  3. Object.create函数返回一个对象,该对象的__proto__属性为对象参数的原型。此时将”Chinese“构造函数的原型和通过Object.create返回的实例对象联系起来
  4. 最后修复"Chinese"构造函数的原型链,即自身的"constructor"属性需要指向自身
  5. 在”Chinese“构造函数的原型上添加”getAge“函数
function Human(name) {this.name = namethis.kingdom = 'animal'this.color = ['yellow', 'white', 'brown', 'black']
}
Human.prototype.getName = function() {return this.name
}function Chinese(name,age) {Human.call(this,name)//call函数借助”Human“的构造器来获得通用属性this.age = agethis.color = 'yellow'
}//返回的对象__proto__属性为对象参数的原型
Chinese.prototype = Object.create(Human.prototype)//使用现有的对象来作为新创建对象的原型
//修复"Chinese"构造函数的原型链,即自身的"constructor"属性需要指向自身
Chinese.prototype.constructor = ChineseChinese.prototype.getAge = function() {return this.age
}

Object.defineProperty(obj, prop, descriptor)

Object.create 

该函数创建一个新对象,使用现有的对象来提供新创建的对象的proto,核心步骤有:

  1. 创建一个临时函数
  2. 将该临时函数的原型指向对象参数
  3. 返回该临时对象的实例

Object.create法创建一个新对象,使用现有的对象来提供新创建的对象的proto。

const _objectCreate = proto => {if(typeof proto !== 'object' || proto === null) returnconst fn = function() {}fn.prototype = protoreturn new fn()
}

Object.freeze 

Object.freeze = writable: false + Object.seal = writable: false + Object.preventExtensions + configable: false

  • Symbol 类型作为 key 值的情况,也要冻结
  • 只冻结对象自有的属性(使用 for ... in 会把原型链上的可枚举属性遍历出来)。
  • 注意不可扩展性(不能添加新属性,使用 Object.preventExtensions() 或 Object.seal() 实现,同时也相当于把原型链冻结)。

key:

  1. Object.getOwnPropertyNames/Symbol
  2. forEach
  3. Object.defineProperty:configurable,writable
  4. Object.preventExtensions(object)
const _objectFreeze = object => {if(typeof object !== 'object' || object === null) {throw new TypeError(`the ${object} is not a object`)}const keys = Object.getOwnPropertyNames(object);const symbols = Object.getOwnPropertySymbols(object);[...keys, ...symbols].forEach(key => {Object.defineProperty(object, key, {configurable: false,writable: false,})})Object.preventExtensions(object)
}

Object for of

// 创建一个构造函数
function MyObject() {// 为构造函数的实例对象添加两个属性this.prop1 = 'Value 1';this.prop2 = 'Value 2';
}// 在原型上添加一个自定义的迭代器方法
MyObject.prototype[Symbol.iterator] = function () {// 获取实例对象的所有属性名并存储在数组 keys 中const keys = Object.keys(this);let index = 0;// 返回一个迭代器对象,包含 next 方法return {next: () => {// 如果还有属性未遍历完if (index < keys.length) {// 获取当前属性名 key,并递增索引 indexconst key = keys[index++];// 返回包含当前属性名和对应值的对象,并设置 done 为 false 表示未遍历完return { value: [key, this[key]], done: false };} else {// 如果所有属性都已遍历完,返回 done 为 true 表示遍历结束return { done: true };}},};
};// 创建一个实例对象
const instance = new MyObject();// 使用 for...of 遍历实例对象的属性
for (const [key, value] of instance) {// 打印属性名和对应值console.log(key, value);
}

*instance of

  1. 获取首个对象参数的原型对象
  2. 获取Fn函数的原型对象
  3. 进入死循环,当两个参数的原型对象相等时返回true
  4. 当两个参数的原型对象不相等时获取首个对象参数原型的原型并且循环该步骤直到null时返回false
const _instanceof = (target, Fn) => {let proto = target.__proto__let prototype = Fn.prototypewhile(true) {if(proto === Fn.prototype) return trueif(proto === null) return falseproto = proto.__proto__}
}const _instanceof = (target, Fn) => {return Fn.prototype.isPrototypeOf(target);}

 算法

合法的URL

URL结构一般包括协议、主机名、主机端口、路径、请求信息、哈希

  1. 域名不区分大小写:"www"子域名(可选)、二级域名、"com"顶级域名
  2. 只能包含字母(a-z、A-Z)、数字(0-9)和连字符(-)(但-不能再首尾)
https://www.bilibili.com/video/BV1F54y1N74E/?spm_id_from=333.337.search-card.all.click&vd_source=6fd32175adc98c97cd87300d3aed81ea
//开始:                     ^
//协议:                     http(s)?:\/\/
//域名:                     [a-zA-Z0-9]+-[a-zA-Z0-9]+|[a-zA-Z0-9]+
//顶级域名 如com cn,2-6位:   [a-zA-Z]{2,6}
//端口 数字:                (:\d+)?
//路径 任意字符 如 /login:   (\/.+)?
//哈希 ? 和 # ,如?age=1:    (\?.+)?(#.+)?
//结束:                      $
//     https://           www.bilibili                com    /video/BV1F54y1N74E  ?spm..            
/^(http(s)?:\/\/)?(([a-zA-Z0-9]+-[a-zA-Z0-9]+|[a-zA-Z0-9]+)\.)+([a-zA-Z]{2,6})(:\d+)?(\/.+)?(\?.+)?(#.+)?$/.test(url)

千位分割:num.slice(render, len).match(/\d{3}/g).join(',')

  const format = (n) => {let num = n.toString() // 拿到传进来的 number 数字 进行 toStringlet len = num.length // 在拿到字符串的长度// 当传进来的结果小于 3 也就是 千位还把结果返回出去 小于3 不足以分割if (len < 3) {return num} else {let render = len % 3 //传入 number 的长度 是否能被 3 整除if (render > 0) { // 说明不是3的整数倍return num.slice(0, render) + ',' + num.slice(render, len).match(/\d{3}/g).join(',')} else {return num.slice(0, len).match(/\d{3}/g).join(',')}}}let str = format(298000)console.log(str)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/138284.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【分布式计算】七、同步 synchronization 重难点

两个协议&#xff1a; 1、NTP&#xff08;Network Time Protocal)–>广泛使用    机器周期向时间服务器获取准确时间   2、没有协议名称 − > -> −>没有广泛使用    时间服务器周期扫描所有机器&#xff0c;计算时间平均值&#xff1b;导致时间服务器负载…

【数据结构】时间、空间复杂度

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 时间、空间复杂度 1. 算法效率3. 时…

应用程序处理:TCP模块的处理

1、应用程序处理 首先应用程序会进行编码处理&#xff0c;这些编码相当于 OSI 的表示层功能&#xff1b; 编码转化后&#xff0c;邮件不一定马上被发送出去&#xff0c;这种何时建立通信连接何时发送数据的管理功能&#xff0c;相当于 OSI 的会话层功能。 2、TCP 模块的处理 …

Acer宏碁暗影骑士5笔记本AN517-54原装出厂Win10系统工厂模式

宏基电脑原厂WINDOWS10系统自带所有硬件的驱动、NITROSENSE风扇键盘控制中心、Office办公软件、出厂主题壁纸LOGO、 Acer Care Center、Quick Access等预装程序 链接&#xff1a;https://pan.baidu.com/s/1Ovui_CvsUaF-TX0NbuhEVg?pwdcrmv 提取码&#xff1a;crmv 所需要工…

Hadoop-sqoop

sqoop 1. Sqoop简介及原理 简介&#xff1a; Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysq1.postgresql..)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如: MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop 的HDFS中&…

2、Window上的 虚拟机端口 暴露到 宿主机局域网教程

今天在公司的服务器主机上捣鼓虚拟机&#xff0c;要在虚拟机上安装一个oracle&#xff0c;虚拟机和主机能互相ping通的前提下&#xff0c;要将虚拟机上的端口号暴露在主机上&#xff0c;让项目组内的所有员工的电脑都能访问到该oracle数据库。 也就是电脑A 访问主机&#xff0…

计算机网络运维方向综合知识大全

一. 基础知识 1. 网络的组成 组成部分&#xff1a;硬件、软件、协议 硬件主要由主机&#xff08;也称端系统&#xff09;、通信链路&#xff08;如双绞线、光纤&#xff09;、交换设备&#xff08;如路由器、交换机等)和通信处理机&#xff08;如网卡)等组成。软件主要包括各种…

【SpringCloud】微服务技术栈入门1 - 远程服务调用、Eureka以及Ribbon

目录 远程服务调用RestTemplate Eureka简要概念配置 Eureka 环境设置 Eureka ClientEureka 服务发现 Ribbon工作流程配置与使用 Ribbon饥饿加载 远程服务调用 RestTemplate RestTemplate 可以模拟客户端来向另外一个后端执行请求 黑马给出的微服务项目中&#xff0c;有两个 …

【深度学习实验】前馈神经网络(六):自动求导

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 标量求导 2. 矩阵求导 3. 计算图 一、实验介绍 PyTorch提供了自动求导机制&#xff0c;它是PyTorch的核心功能之一&#xff0c;用于计算梯度并进行反向传播。自动求…

使用Java将PPT、PPTX和PDF转换为图片

从Office到图片—使用Java实现文件格式转换 PDF转图片1. 万事第一步2. 撸代码 PPT/PPTX转图片1. 万事第一步2. 撸代码验收一下 最近小雨遇到了一个需求&#xff0c;需要在前端小程序中嵌入展示Office文件的功能。然而&#xff0c;前端使用开源组件进行在线预览会导致性能消耗较…

windows下gvim的配置

一、vim配置文件 "查看自己的vimrc所在的目录 "在命令模式下 :echo $MYVIMRC"打开自己的vimrc文件 "在命令模式下 :e $MYVIMRC 二、排版 "查看自己当前的字体及大小 "在命令模式下 :set guifont?"设置默认的字体为仿宋_GB2312&#xff…

IDEA 2019 Springboot 3.1.3 运行异常

项目场景&#xff1a; 在IDEA 2019 中集成Springboot 3.1.3 框架&#xff0c;运行异常。 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…

R语言贝叶斯广义线性混合(多层次/水平/嵌套)模型GLMM、逻辑回归分析教育留级影响因素数据...

全文下载链接&#xff1a;http://tecdat.cn/?p24203 本教程使用R介绍了具有非信息先验的贝叶斯 GLM&#xff08;广义线性模型&#xff09; &#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 当前教程特别关注贝叶斯逻辑回归在二元结果和计数/比例结果场景中的…

Linux:冯诺依曼系统和操作系统的概念

文章目录 冯诺依曼体系结构冯诺依曼体系的理解 操作系统操作系统的基本定位操作系统的理解1 操作系统的理解2总结 本篇主要总结的是操作系统的基本认知和一些概念 冯诺依曼体系结构 那么上图表示的就是冯诺依曼体系结构&#xff0c;那这个体系结构是什么&#xff1f;为什么要先…

客户端和服务端信息交互模型

什么是客户端和服务端&#xff1f; 客户端&#xff1a;可以向服务器发请求&#xff0c;并接收返回的内容进行处理 服务器端&#xff1a;能够接收客户端请求&#xff0c;并且把相关资源信息返回给客户端的 当用户在地址栏中输入网址&#xff0c;到最后看到页面&#xff0c;中间都…

配置OSPFv3基本功能 华为笔记

1.1 实验介绍 1.1.1 关于本实验 OSPF协议是为IP协议提供路由功能的路由协议。OSPFv2&#xff08;OSPF版本2&#xff09;是支持IPv4的路由协议&#xff0c;为了让OSPF协议支持IPv6&#xff0c;技术人员开发了OSPFv3&#xff08;OSPF版本3&#xff09;。 无论是OSPFv2还是OSPFv…

服务器新建FTP文件备份的地址

步骤1&#xff1a;远程桌面连接 步骤2&#xff1a;输入服务器地址&#xff0c;账号&#xff0c;密码 服务器地址&#xff1a;IP地址 账号&#xff1a;Administrator 密码&#xff1a;123456 步骤3&#xff1a;点击这个一个小人的图标 步骤4&#xff1a;General–>Add–&g…

R语言进行孟德尔随机化+meta分析(1)---meta分析基础

目前不少文章用到了孟德尔随机化meta分析&#xff0c;今天咱们也来介绍一下&#xff0c;孟德尔随机化meta其实主要就是meta分析的过程&#xff0c;提取了孟德尔随机化文章的结果&#xff0c;实质上就是个meta分析&#xff0c;不过多个孟德尔随机化随机化的结果合并更加加强了结…

【数据链路层】网络基础 -- MAC帧协议与ARP协议

数据链路层认识以太网以太网帧格式(MAC帧)认识MAC地址对比理解MAC地址和IP地址认识MTUMTU对IP协议的影响MTU对UDP协议的影响MTU对于TCP协议的影响 再谈局域网转发原理&#xff08;基于协议&#xff09;ARP协议ARP协议的作用ARP协议的工作流程ARP数据报的格式 数据链路层 用于两…

《DevOps实践指南》- 读书笔记(九)

DevOps实践指南 25. 附录附录 1 DevOps 的大融合精益运动敏捷运动Velocity 大会运动敏捷基础设施运动持续交付运动丰田套路运动精益创业运动精益用户体验运动Rugged Computing 运动 附录 2 约束理论和核心的长期冲突附录 3 恶性循环列表附录 4 交接和队列的危害附录 5 工业安全…