八股文(二)
一、 实现深拷贝和浅拷贝
1.深拷贝
function checkType(any) {return Object.prototype.toString.call(any).slice(8, -1)
}//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
//如果获得的数据是可遍历的,就拿到对应的value,实现深拷贝
function clone(any){if(checkType(any) === 'Object') { // 拷贝对象let o = {};//遍历for(let key in any) {o[key] = clone(any[key])}return o;} else if(checkType(any) === 'Array') { // 拷贝数组var arr = []//遍历for(let i = 0,leng = any.length;i<leng;i++) {arr[i] = clone(any[i])}return arr;} else if(checkType(any) === 'Function') { // 拷贝函数return new Function('return '+any.toString()).call(this)} else if(checkType(any) === 'Date') { // 拷贝日期return new Date(any.valueOf())} else if(checkType(any) === 'RegExp') { // 拷贝正则return new RegExp(any)} else if(checkType(any) === 'Map') { // 拷贝Map 集合let m = new Map()any.forEach((v,k)=>{m.set(k, clone(v))})return m} else if(checkType(any) === 'Set') { // 拷贝Set 集合let s = new Set()for(let val of any.values()) {s.add(clone(val))}return s}return any;
}
2.浅拷贝
function shallowCopy(src) {var dst = {};for (var prop in src) {//只要还没读完就继续读,读到的话就直接把属性名返回就行,没有进入深层//hasOwnProperty:是用来判断一个对象是否有你给出的名称的属性或对象。有则返回true,没有返回false,不过需要注意的是,此方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身的一个成员。if (src.hasOwnProperty(prop)) {dst[prop] = src[prop];}}return dst;
}
二、 讲一下event loop
事件循环是js引擎执行js的机制,用来实现js的异步特性。事件循环的过程为:当执行栈空的时候,就会从任务队列中,取任务来执行。共分3步:
-
取一个宏任务来执行。执行完毕后,下一步。
-
取一个微任务来执行,执行完毕后,再取一个微任务来执行。直到微任务队列为空,执行下一步。
-
更新UI渲染。
1.EventLoop概念
Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
因为JavaScript就是单线程,也就是说,同一个时间只能做一件事。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)
2.同步任务和异步任务
同步任务:函数返回—>拿到预期结果 异步任务:函数返回—>拿不到预期结果,还要通过一定的手段获得结果 简单点说 : 同步任务:会立即执行的任务 异步任务:不会立即执行的任务(异步任务又分为宏任务与微任务)
在异步任务中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。
宏任务:由宿主对象发起的任务(setTimeout)。宏任务(定时器)包括 script, setTimeout,setInterval,setImmediate(Node.js),I/O,postMessage, MessageChannel,UI rendering(即I/O、定时器、事件绑定、ajax)
微任务:由js引擎发起的任务(promise)。微任务包括 process.nextTick(Node.js),promise.then(),promise.catch(),MutationObserver。(即Promise的then、catch、finally和process的nextTick)
注意:Promise的then等方法是微任务,而Promise中的代码是同步任务,并且,process的nextTick的执行顺序优先于Promise的then等方法,因为process.nextTick是直接告诉浏览器说要尽快执行,而不是放入队列
3.同步任务
当有多个同步任务时,这些同步任务会依次入栈出栈,如下图
同步任务1先入栈,执行完之后,出栈,接着同步任务2入栈,依此类推
4.异步任务
异步任务会在同步任务执行之后再去执行,那么如果异步任务代码在同步任务代码之前呢?在js机制里,存在一个队列,叫做任务队列,专门用来存放异步任务。也就是说,当异步任务出现的时候,会先将异步任务存放在任务队列中,当执行完所有的同步任务之后,再去调用任务队列中的异步任务
例如下图,现在存在两个同步任务,两个异步任务
js会先将同步任务1提至主线程,然后发现异步任务1和2,则将异步任务1和2依次放入任务队列
然后同步任务1执行完之后出栈,又将同步任务2入栈执行
当同步任务2执行完之后,再从任务队列中提取异步任务执行
5.总结
js中,微任务总是先于宏任务执行,也就是说,这三种任务的执行顺序是:同步任务>微任务>宏任务
6.案例
<script>console.log(1);setTimeout(function(){console.log(2)},0)new Promise((resolve,reject)=>{console.log(3)resolve()console.log(4)}).then(()=>{console.log(5)})console.log(6)
</script>
三、 js如何判断一个变量是数组
判断变量的类型是最经常使用的方法,但是判断的方式有很多
1.typeof
var ary = [1,2,3,4];
console.log(typeof ary); // 输出‘object’
很明显,typeof只能检测基本数据类型,并不能检测出来是否为数组。
2.instanceof
var ary = [1,2,3,4];
console.log(ary instanceof Array); //输出true
看起来挺好使的,实际上也确实挺好使的,但是要求变量必须在当前页面声明。
3.原型链
var ary = [1,2,3,4];
console.log(ary.__proto__.constructor==Array); //输出true
console.log(ary.constructor==Array) //输出true
两种方法都一样,但是在IE中“proto”没有定义。这种方法也存在和“instanceof”一样的问题,必须先声明变量。
4.isArray
let a = [2,543,32];
console.log(Array.isArray(a));//true
必须先声明变量
5.完美方法
var arr = [1,2,3,4];
console.log(Object.prototype.toString.call(arr)) //输出"[object Array]"
为了使用简便,我们可以封装成一个函数。
var ary = [1,2,3,4];
function isArray(o){
return Object.prototype.toString.call(o)=='[object Array]';
}
console.log(isArray(ary));
当然,这种方法不仅仅可以用来判断是否为数组,其他的也同样适用。
console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]
四、 JavaScript数据类型
JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt
其中 Symbol 和 BigInt 是ES6 中新增的数据类型:
Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。 BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。 这些数据可以分为原始数据类型和引用数据类型:
栈:原始数据类型(Undefined、Null、Boolean、Number、String) 堆:引用数据类型(对象、数组和函数)
五、 柯里化
1. 什么是函数柯里化
函数柯里化就是我们给一个函数传入一部分参数,此时就会返回一个函数来接收剩余的参数。 柯里化是一种函数的转换。是指将一个函数从可调用的 f(a, b, c)
转换为 f(a)(b)(c)
2. 简单的柯里化的实现
没有柯里化的实现
将其转化为柯里化的案例
上述代码可简写为
3.函数柯里化的好处
我们希望处理函数时,希望函数功能尽可能单一。如下面代码所示,我们希望第一个参数+2
,第二个参数*2
,第三个参数** 2
,最后再相加,此时我们可以使用函数的柯里化
function makeAdder(count) {return function(num) {return count + num}
}
// 在之后使用返回的函数时,我们不需要再继续传入count 了
var adder5 = makeAdder(5)
adder5(10)
adder5(14)
adder5(1100)
adder5(555)
4.柯里化的优点
柯里化是使函数变得更具体些,即作用范围更小
5.传入函数的柯里化执行
function currying(fn, ...rest) {return function(...args) {//...rest=3,4//...args=1,2return fn(...rest, ...args);}
}
function sum(a, b, c, d) {console.log(a + b + c + d)
}
//传入sum,即currying(fn,...rest)解析成sum,1,2
//add是接收currying返回的函数
const add = currying(sum, 1, 2);
//add(3,4)即function(3,4),这个function是sum(3,4),所以add(3,4)就会执行最后那个sum四个数相加的函数
add(3, 4);
// 执行结果
10
function add(a, b, c, d) {console.log(a + b + c + d);
}
const curriedAdd = currying(add);
//接收curry()()()()
curriedAdd(1)(2)(3)(4); // 10
curriedAdd(1, 2, 3)(4); // 10
curriedAdd(1, 2, 3, 4); // 10
function currying(fn) {
//一开始,curriedAdd传入一个参数1,len=add参数长度4const len = fn.length;
//_args=[]let _args = [];const curry = () => {
//...args=1return function (...args) {
//_args.length=0,args.length=1,小于len=4// 如果参数攒够了就执行if (_args.length + args.length >= len) {const result = fn(..._args, ...args);// 执行完重置_args_args = [];return result;}// 参数不够就继续攒else {//_args=[..._args,...args]=[1]_args = [..._args, ...args];//curriedAdd(1)返回值是一个curry函数,以此类推return curry();}}}return curry();
}
六、 如何理解闭包,为什么有这种特性?为什么需要闭包?闭包的缺点?
(1)什么是闭包?
闭包就是能够读取其他函数内部变量的函数。
由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。
所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
(2)如何生成闭包?
函数嵌套 + 内部函数被引用。
function outer() {var a = 1;function inner() {console.log(a);}return inner;
}
//这里的闭包就是返回的inner函数
var b = outer();
(3)闭包作用?
-
可以让内部的函数访问到外部函数的变量,避免变量在全局作用域中存在被修改的风险
-
可以读取函数内部的变量
-
让这些变量的值始终保持在内存中,不会在f1调用后被自动清除
(4)使用闭包的注意事项?
不用的时候解除引用,避免不必要的内存占用。
为什么有闭包的这种特性:如果形成闭包,外部函数执行完后,其中的局部变量可能被内部函数使用,所以不能销毁,因此内部函数能一致访问到这些局部变量,直到引用解除。
(5)闭包的优点?
-
隐藏变量,避免放在全局有被篡改的风险。
-
方便调用上下文的局部变量
(6)闭包的缺点?
-
使用时候不注意的话,容易产生内存泄漏。
-
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除
相关文章:

八股文(二)
一、 实现深拷贝和浅拷贝 1.深拷贝 function checkType(any) {return Object.prototype.toString.call(any).slice(8, -1) }//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝 //如果获得的数据是可遍历的&#…...

在CANoe/CANalyzer中观察CAN Message报文的周期Cycle
案例背景: 该篇博文将告诉您,如何直观的,图示化的,查看CAN网络中各CAN Message报文的周期变化。 优质博文推荐阅读(单击下方链接,即可跳转): Vector工具链 CAN Matrix DBC CAN M…...
Linux命令·ls
ls命令是linux下最常用的命令。ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单。 通过ls 命令不仅可以查看linux文件夹包含的文件而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息…...

Mysql InnoDB 存储引擎笔记
1 存储引擎 简介 Mysql 存储引擎有多种:包括 MyISAM、InnoDB 和 Memory。 其中MyISAM 和 INNODB 的区别: 事务安全(MyISAM不支持事务,INNODB支持事务);外键 MyISAM 不支持外键, INNODB支持外…...

智慧工地AI视频分析系统 opencv
智慧工地AI视频分析系统通过pythonopencv网络模型图像识别技术,智慧工地AI视频分析算法自动识别现场人员穿戴是否合规。本算法模型中用到opencv技术,OpenCV基于C实现,同时提供python, Ruby, Matlab等语言的接口。OpenCV-Python是OpenCV的Pyth…...

小红书「高效达人筛选攻略」
三八女神节降临,诸多品牌纷纷开启铺垫预热,在各大平台借势宣传。而聚集庞大年轻女性消费群体的小红书,对“她营销”的重要性不言而喻。节点序幕拉开,面对海量达人信息,如何提前积草屯粮、高效备战? 本期千瓜…...

大话数据结构-线性表
1 定义 线性表是零个或多个数据元素的有限序列。 2 抽象数据类型 ADT 线性表(List)Data:线性表的数据对象集合为{al,a2,a3,....an},每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素&…...

分布式缓存 Memcached Linux 系统安装
1.Memcached简介 Memcached是一个开源、高性能,将数据分布于内存中并使用key-value存储结构的缓存系统。它通过在内存中缓存数据来减少向数据库的频繁访问连接的次数,可以提高动态、数据库驱动之类网站的运行速度。 Memcached在使用是比较简单的&#…...

【数据结构】链表:看我如何顺藤摸瓜
👑专栏内容:数据结构⛪个人主页:子夜的星的主页💕座右铭:日拱一卒,功不唐捐 文章目录一、前言二、链表1、定义2、单链表Ⅰ、新建一个节点Ⅱ、内存泄漏Ⅲ、插入一个节点Ⅳ、销毁所有节点Ⅴ、反转一个链表3、…...

linux shell 入门学习笔记18 函数开发
概念 函数就是将你需要执行的shell命令组合起来,组成一个函数体。一个完整的函数包括函数头和函数体,其中函数名就是函数的名字。 优点 将相同的程序,定义,封装为一个函数,能减少程序的代码数量,提高开发…...
如何最巧妙回答HR面试“送命题”:你为什么离开上家公司?
一 HR面试存在“送命题”? 一个资深HR朋友聊到,他最近pass掉一个名校高材生。 其实洽谈过程还比较愉悦,小姑娘名校毕业,落落大方,薪酬要求比较合理,各方面都比较符合,最后就在决定要录用时,HR朋友随口问了句 “你为什么离开上家公司?”,小姑娘也是随口说了句“我不喜…...

注意力机制详解系列(五):分支与时间注意力机制
👨💻作者简介: 大数据专业硕士在读,CSDN人工智能领域博客专家,阿里云专家博主,专注大数据与人工智能知识分享,公众号:GoAI的学习小屋,免费分享书籍、简历、导图等资料&…...

创宇盾重保经验分享,看政府、央企如何防护?
三月重保已经迫近,留给我们的准备时间越来越少,综合近两年三月重保经验及数据总结,知道创宇用实际案例的防护效果说话,深入解析为何创宇盾可以在历次重保中保持“零事故”成绩,受到众多部委、政府、央企/国企客户的青睐…...
软件测试面试汇总
在浏览器中输入 URL,回车后发生了什么? 在浏览器中输入URL并按下回车键后,大致流程如下: 1、浏览器解析 URL,提取出协议(例如HTTP、HTTPS)、主机名和路径等信息。 2、浏览器查找该URL的缓存记录࿰…...

空指针,野指针
空指针在C/C中,空指针(null pointer)是指向内存地址0的指针变量。NULL在C/C中的定义为:#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif #endif从上面的代码定义中,我们可以发现在C…...

Mysql Nested-Loop Join算法和MRR
MySQL8之前仅支持一种join 算法—— nested loop,在 MySQL8 中推出了一种新的算法 hash join,比 nested loop 更加高效。(后面有时间介绍这种join算法) 1、mysql驱动表与被驱动表及join优化 先了解在join连接时哪个表是驱动表&a…...

Spark 广播/累加
Spark 广播/累加广播变量普通变量广播分布式数据集广播克制 Shuffle强制广播配置项Join Hintsbroadcast累加器Spark 提供了两类共享变量:广播变量(Broadcast variables)/累加器(Accumulators) 广播变量 创建广播变量…...

飞天云动,站在下一个商业时代的门口
ChatGPT的爆火让AIGC再度成为热词,随之而来的是对其商业化的畅想——不是ChatGPT自身如何盈利,而是它乃至整个AIGC能给现在的商业环境带来多大改变。 这不由得令人想起另一个同样旨在改变世界的概念,元宇宙。不同的是,元宇宙更侧…...

上海分时电价机制调整对储能项目的影响分析
安科瑞 耿敏花 2022年12月16日,上海市发改委发布《关于进一步完善我市分时电价机制有关事项的通知》(沪发改价管〔2022〕50号)。通知明确上海分时电价机制,一般工商业及其他两部制、大工业两部制用电夏季(7、8、9月)和冬季&#x…...
产品新人如何快速上手工作
三百六十行,行行出产品经理:上至封神的乔布斯,下至卖鸡蛋罐饼的阿姨,他们对如何打造自己的产品都会有一套完整的产品思路,这也是为什么说“人人都是产品经理”。这个看似光鲜的“经理”有时也会被戏称产品汪࿰…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...