前端手写练习题及概念加深

通过举例和实际例子来加深前端的概念形式 

1. 手写reduce

用法:

// 手写 reduce
const a = [1, 3, 6, 8]const sum = a.reduce((accu, curr) => accu + curr, 0)
console.log('sum', sum )

在注释中解释 reduce 的手写方法

// 1. 明确参数累加函数,接受两个参数,回调函数和初始值
const sum = a.reduce((accu, curr) => accu + curr, 0)
console.log('sum', sum )// 用原型的方式来定义方法
Array.prototype.myReduce = function(callback, initialValue) {// 分清可能的边界情况if(typeof callback !== 'function') {throw `${callback} is not a function`}
// 如果没有定义 initialValue的话,初始为 0initialValue = initialValue ? initialValue : 0// reduce本质上是遍历数组的参数, this为调用的数组let arr = this// 定义最后返回的累加值let result = initialValuefor(let i = 0 ; i <  arr.length; i = i + 1) {// 传入的回调函数,接受参数为累加i值,当前数组数,index, 和 arrresult = callback(result, arr[i], i, arr)}return result}const sum2 = a.myReduce((accu, curr) => accu + curr, 0)
console.log('sum', sum2 )

2. 手写链式方法

题目

手写 LazyMan ,实现 sleep 和 eat 两个方法,支持链式调用。 代码示例:

const me = new LazyMan('tom')
me.eat('苹果').eat('香蕉').sleep(5).eat('葡萄') // 打印结果如下:// 'tom eat 苹果'
// 'tom eat 香蕉'
// (等待 5s)
// 'tom eat 葡萄'

题目分析:用 taskQueue来实现或者或 Promise     

class LazyMan {constructor(name) {this.name = namethis.promiseChain = Promise.resolve()}sleep(second) {this.promiseChain = this.promiseChain.then(() => {return new Promise((resolve, reject) => {setTimeout(() => {resolve()}, second * 1000)}) })  return this   }eat(name) {this.promiseChain = this.promiseChain.then(() => {return   new Promise((resolve, reject) => {resolve()console.log(`${this.name} eat ${name}`)})})return this}
}

用 Promise实现

class LazyMan {constructor(name) {this.name = namethis.promiseChain = Promise.resolve()}sleep(second) {this.promiseChain = this.promiseChain.then(() => {return new Promise((resolve, reject) => {setTimeout(() => {resolve()}, second * 1000)}) })  return this   }eat(name) {this.promiseChain = this.promiseChain.then(() => {return   new Promise((resolve, reject) => {resolve()console.log(`${this.name} eat ${name}`)})})return this}
}

3. 数组转树/树转数组

数组转树:文件列表是树形结构的时候,可能会遇到数组转树的情况

思路:首先定义一个 data 来生成一个 id 和对象的键值对的形式,然后用一个 result 来生成结果

function arrayToTree(arr) {
let data = {}, result = [];
arr.map((item)=> data[item.id] = item)for(let arritem of data) {
if(arritem.parentId) {
if(data[arritem.parentId].children {
data[arritem.parentId].children = []
}
data[arritem.parentId].children.push(arritem)
} else {
result.push(arritem)
}}

树转数组:类似二叉树的层序遍历

4.ES6新特性

https://juejin.cn/post/6844903959283367950

1)var, const, let区别

2)Map和 Set

  • 集合(Set) 和数组的区别
  • Map和对象的区别

实际应用场景:深入浅出JS—13 Set和Map应用场景_jsmap数据结构的使用场景-CSDN博客

3) WeakMap和 WeakSet

5.闭包

 定义:在一个函数中可以访问另一个函数中的变量

题目:

// 实现如下代码,只打印出 3 次前的调用的值var vote = before(3, fn)vote('tom')
vote('alice')
vote('carm')
vote('car')
vote('cai')
vote('ca2')

解法及讲解:

const before = (n , fn) => {let times = 0return function(...args) {if(times < n) {fn(args)times = times + 1}}
}var vote = before(3, (name) => {console.log(`This is ${name}`)
})vote('tom')
vote('alice')
vote('carm')
vote('car')
vote('cai')
vote('ca2')

1)在外部函数定义了一个 times 的变量,新生成的函数没有自己的变量,它可以访问外部函数的变量,词法作用域根据源代码中声明变量的位置来确定该变量在何处可用

2)vote作为一个外部函数来返回了这个定义的函数,JS 函数形成闭包,闭包是由函数以及声明该函数的词法环境组合而成的,该环境包含了这个闭包创建时的任何局部变量,vote为返回函数的引用,返回函数维护了一个词法环境,所以 vote 被调用时,times 依然可用

3)如果要传入参数,即在返回的函数的参数中去实现这个参数

实际应用:

1)为响应事件而执行的函数

2)闭包模拟私有方法

在其他函数中创建函数其实是不明智的,创建新的对象或类时,应该关联于对象的原型,而不是对象的构造器中

参考:闭包 - JavaScript | MDN

6. Promise

用 Promise来实现具体例子,手写 Promise.all等方法

1) 实现一个 sleep 函数,实现如下条件

const testSleep = async () => {const currentTime = Date.now()await sleep(1000)console.log(Date.now() - currentTime)
}testSleep()

知识点 1:事件循环

先执行同步任务,再执行宏任务,再执行所有的微任务,再执行一个宏任务,再执行所有的微任务

宏任务有:

微任务有:

(async () => {console.log(1);setTimeout(() => {console.log(2);
}, 0);
await new Promise((resolve, reject) => {console.log(3);
}).then(() => {console.log(4);
});console.log(5);
})();

 参考:牛客最新前端 JS 笔试百题

以上程序的输出结果是什么

输出结果是 1,3,Promise(pending), 2, 这里 async 里的内容应该执行,await 之后的内容应该等 await 有返回值后再执行,但是 promise 并没有产生 resolve 或是 reject 的结果,所以是 pending 状态,await 之后的值也不会执行

知识点 1.1 异步函数的解决方案

如果是同步代码,需要暂停等待返回值,而异步代码不需要暂停等待返回值,而是立即执行后面的代码,服务器返回信息后再执行回调函数

知识点 1.2 Promise和 async/await区别

1.ES6/ES7的区别

2. await 是写法上和同步状态类似

 sleep解法

const sleep = (times) =>  {return new Promise((resolve) => {setTimeout(() => {resolve()}, times)})
}

这里await等待 promise 返回成功的值,然后再执行后面的函数

知识点 2: Promise 的解决方法

Promise是在处理多个异步任务后的结果, 参数是 promise 数组,返回值是 promise结果

Promise.all()

Promise.race()

Promise.allSettled()

手写 Promise.all()

PromiseMyAll = (promises) => {// return a Promisereturn new Promise((resolve, reject) => {const result = [];let promiseCount = 0;promises.forEach((promiseItem) => {// Resolve the given valuePromise.resolve(promiseItem).then((res) => {result[promiseCount] = res;promiseCount = promiseCount + 1;if (promiseCount === promises.length) {// 这里是定义 Promise 来生成的resolve(result);}}).catch((err) => reject(err));});});
};

7. 深拷贝和浅拷贝

浅拷贝:对基础数据类型的准确拷贝,对复杂数据类型只拷贝第一层

深拷贝:对基础数据类型还是复杂数据类型都是准确拷贝

题目:

let obj = {name: '祁纤',person: [20, '男', { demo: { name: '沉香', age: '18' } }, null],obj: {sex: '男',age: 20,bar: ['red', 'bule']}
}let bar = {}
deepClone(obj, bar)
bar.person.push('我@bar变了')
console.log('@bar', bar)
console.log('@obj', obj)

for...in 是可枚举对象,for..of..是可迭代对象

深拷贝的实现代码:

const deepClone = (originObj, copiedObj = {}) => {if (Array.isArray(originObj)) {copiedObj = [];}for (let key in originObj) {if (originObj.hasOwnProperty(key)) {if (typeof originObj[key] === "object") {copiedObj[key] = deepClone(originObj[key],Array.isArray(originObj[key]) ? [] : {} // 有可能是 array或是 object,因为复杂数据类型的 typeof都是 object);} else {copiedObj[key] = originObj[key];}}}return copiedObj;
};

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

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

相关文章

Django 和 Spring Boot

标题 Django (Python)Django提供的组件Django 的处理逻辑 Spring Boot (Java)Spring Boot 的特点Spring Boot 的处理逻辑 MVC设计模式模型&#xff08;Model&#xff09;视图&#xff08;View&#xff09;控制器&#xff08;Controller&#xff09;逻辑处理过程 Django 和 Spri…

Postman基础功能-Collection集合和批量运行

一、Collection&#xff08;集合&#xff09;介绍 当我们对一个或多个系统中的很多接口用例进行维护时&#xff0c;首先想到的就是对接口用例进行分类管理&#xff0c;同时还希望对这批接口用例做回归测试。 在 Postman 中也提供了这样一个功能&#xff0c;就是 Collec…

免费的GPT4终于要来了!OpenAI直播发布会详细解读!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

Docker下载镜像出现“missing signature key”如何解决?

“missing signature key” 通常与 Docker 配置有关&#xff0c;具体是 Docker 试图验证镜像的签名但未能找到相应的密钥。这种情况可能发生在启用了 Docker Content Trust (DCT) 的环境中&#xff0c;DCT 是一种安全功能&#xff0c;要求所有镜像必须有签名才能拉取。 原因 …

刚刚OpenAI发布ChatGPT-4o模型,免费使用GPT4o并免费提供更多功能

就在今日凌晨1点&#xff0c;OpenAI举行了春季发布会&#xff0c;发布了GPT-4o 并免费提供更多功能。 亲测GPT-4o已经可以免费试用&#xff0c;每个人都可以使用它并从中受益&#xff0c;GPT4终于不再是少部分人的玩物。 点击加入ChatGPT4交流群&#xff1a;https://www.aijour…

体彩、福彩中奖概率分析

体彩和福彩的中奖概率分析是一个涉及概率论、数理统计以及彩票玩法规则的复杂话题。 但我可以提供一个大致的框架和要点,供您参考和扩展。 一、引言 在引言部分,可以简要介绍彩票的起源、发展和在中国的影响。阐述彩票作为一种特殊的商品,其销售和购买过程中的中奖概率是吸…

微信小程序发送订阅消息sendMessage

微信小程序发送订阅消息sendMessage 请注意订阅消息一次性订阅只只能授权一次接受一条消息多次授权会累加接受次数&#xff0c;wx.requestSubscribeMessage调用授权 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放 //授权弹框&#xff0c;只弹出…

交通地理信息系统实习教程(二)

这篇文章服务于GIS背景用户以及有志于GIS的朋友 操作源数据位置&#xff1a;【免费】交通地理信息系统实习二源数据资源-CSDN文库 软件安装包位置&#xff1a;【免费】TransCad-交通地理信息系统软件资源-CSDN文库 一、最短路径分析 1.1软件启动说明 这里需要给出一个必要的…

硬件FMEA与软件FMEA的区别——FMEA软件

​免费试用FMEA软件-免费版-SunFMEA 在产品开发和制造过程中&#xff0c;失效模式与影响分析&#xff08;FMEA&#xff09;作为一种预防性的质量工具&#xff0c;对于确保产品性能和质量至关重要。然而&#xff0c;硬件FMEA和软件FMEA在应用和实践方面存在显著的区别。本文旨在…

基于阿里云向量检索 Milvus 版与 PAI 搭建高效的检索增强生成(RAG)系统

阿里云向量检索 Milvus 版现已无缝集成于阿里云 PAI 平台&#xff0c;一站式赋能用户构建高性能的检索增强生成&#xff08;RAG&#xff09;系统。您可以利用 Milvus 作为向量数据的实时存储与检索核心&#xff0c;高效结合 PAI 和 LangChain 技术栈&#xff0c;实现从理论到实…

java面试题:判断字符串包含字母、数字、空格、符号的数量

在Java中&#xff0c;你可以使用正则表达式来检查字符串中包含多少个字母、数字、空格和符号。也可以使用基础api来实现业务逻辑&#xff0c;方法如下&#xff1a; 1 使用Character类的静态方法 以下代码定义了一个countCharacters方法&#xff0c;它遍历字符串中的每个字符&a…

CSS美化网页:理论基础及示例

CSS&#xff08;层叠样式表&#xff09;是用于美化网页和控制网页布局的重要技术。通过CSS&#xff0c;你可以对网页的元素进行样式设计&#xff0c;包括字体、颜色、间距、边框、背景等。以下是一些关键的CSS属性和概念&#xff0c;用于美化网页&#xff1a; 1. 字体样式&…

Java基础教程大纲

Java基础教程大纲 1、Java概述 jdk和jre介绍,idea介绍; 第一个java程序; javase javaee 2、 java基本数据类型 3、java变量和常量 和关键字 数组 4、java String 和操作符 5、 java运算符 比较,逻辑,算术 6、条件语句和循环语句 7、Java面向对象类和接口一 8、Jav…

qt的http原理

#ifndef TURING_H #define TURING_H #include <QObject》 #include <QNetworkAccessManager》 #include <QNetworkRequest》 #include <QNetworkReply》 class Turing : public QObject { Q_OBJECT public: explicit Turing(QObject *parent 0);Q_INVOKABLE v…

解决:微信支付 由于商家传入的H5交易参数有误,该笔交易暂时无法完成,请联系商家解决

微信支付参数配置完成后请求报这个。在网上搜索后发现是ip配置的问题&#xff0c;我配置的是127.0.0.1。 而微信支付的时候需要获取用户的真实ip

Mysql关键字闭坑

Mysql关键字闭坑 INTERVAL 因为需求&#xff0c;所以数据设计时用到了一个INTERVAL字段,程序编译及启动都没有任何问题&#xff0c;但是到了查询的时候&#xff0c;直接控制台报语法异常&#xff0c;这就奇怪了&#xff0c;用的是MP插件作为查询&#xff0c;为啥报出语法错误&…

求职招聘平台小程序源码系统 附带源代码以及完整的安装部署教程

系统概述 求职招聘平台小程序源码系统是一款基于微信小程序的求职招聘平台&#xff0c;旨在为广大求职者和招聘企业提供一个高效、便捷的线上交流平台。该系统具备以下特点&#xff1a; 1.功能齐全&#xff1a;系统包含职位发布、简历投递、在线沟通、面试安排等求职招聘全流程…

Android Saving Activity State使用说明和注意事项

1、说明 在管理activity生命周期的简单介绍中提到当一个activity被暂停或停止时&#xff0c;该activity的状态被保留。因为当activity对象被暂停或停止时仍然保留在内存中&#xff0c;所有有关成员的信息和当前的状态仍然可用。这样&#xff0c;用户对该activity所做的任何更改…

笔记:完善python selenium 讯飞写作的整体自动化

昨天做得不太好,今天再来一次,我发现,只要写得多,一定会有发现。 1、加入本地目录,不要一直登录。 # 定义Edge浏览器的用户数据目录edge_user_data_dir = r"C:\Users\Administrator\AppData\Local\Microsoft\Edge\User Data\Default"# 设置Edge选项edge_optio…

Spire.PDF for .NET【文档操作】演示:将多个 PDF 文件中的选定页面合并为一个

使用 Spire.PDF&#xff0c;您不仅可以将多个 PDF 文件合并为一个文件&#xff0c;还可以从源文件中选择特定页面并将它们合并为一个 PDF 文档。以下代码片段演示了相同的内容。 Spire.PDF for .NET 是一款独立 PDF 控件&#xff0c;用于 .NET 程序中创建、编辑和操作 PDF 文档…