前端已经不再是5年前刚开始火爆时候的那种html+css+js+jquery的趋势了,现在需要你完全了解前端开发的同时,还要具备将上线、持续化、闭环、自动化、语义化、封装......等概念熟练运用到工作中的一个职业,甚至用人部门还希望你了解并掌握深度学习及机器学习的相关概念。在面试过程中,各部门交叉面试的时候会提问一些关于后端的知识。
假如你想要拿到2.5w+月薪,你的能力应该达到掌握以下全部知识点并有过开发后端接口与数据处理(node、java、c......必须掌握一种)的经验。本文就是结合自己的工作、面试经验,同时为那些想要冲击2w+薪资的1-3年新手们准备的。
需要注意的是,所有大厂的社招会按照你当前工作经验进行+1,+2的难度提升(假设你工作一年,会按照三年工作经验进行招聘,同时二三面会按照你的项目经验进行择优筛选)所以起步是互联网公司的同学占了很大的优势,有些小伙伴在国企工作一年~三年,项目经验的欠缺导致竞争力不足,没别的办法,建议早日跳出自己的舒适圈,之后你会体会到不一样的前端开发。以下是面试时高频出现且必须要掌握的知识点:
学习资料
公众号:中台架构之家
每日一题:题目传送门
前端电子书大全:电子书
基础知识点
1、mock
在前后端分离的开发中,Mock 数据是前端开发中很重要的一个环节,前端可以不必强依赖后端接口,只需要约定好对应的数据接口,前端可以通过 Mock 模拟数据先行开发,在后端接口开发完成后,只需要切换对应的接口地址即可,可以保证项目的同步开发。
本地内容:在mock文件夹下中的index文件中定义好自有的接口路径,再到根目录的service文件夹下生成对应业务模块的js文件。文件内将相应微服务的接口匹配好。暴露出去供业务功能调用。
2、网络请求编码表示
会从你是否关注Request head的哪些内容入手,一般关注点放在statusCode和method上就够用,重点200,304。同时掌握了基础后希望注意的点为文件上传的内容(百度问过断点续传的实现)
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
304:'协商缓存'
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。'
3、axios工作流程
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它本身具有以下特征:
1.从浏览器中创建 XMLHttpRequest
2.支持 Promise API
3.客户端支持防止CSRF
4.提供了一些并发请求的接口(重要,方便了很多的操作)
5.从 node.js /java创建 http 请求
6.拦截请求和响应
7.转换请求和响应数据
8.取消请求
9.自动转换JSON数据
防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。
/**
*
*
* @param {*} params mmsi
* @param {*} callback
*
*
*/
getship_cargo_detail:function(params,callback){
axios.get(server.portAddress+"newshipcargo/newship_pos_detail",{params})
.then(function(res){
callback(res.data);
})
.catch(function(error){
console.log("get_ship_cargo_data_error");
})
},
//调用方法
shipcargoserver.getship_cargo_detail({mmsi:mmsi},data=>{
if(data){
this.setState({
pageNumber:data.,,,,,,,
})
}
})
4、ElementUI(ElementReact)与antdesign和ice-work的比较
使用Element的原因是通过学习饿厂的 Element
其设计原则可以兼容三大框架 (三大框架各有实现):
- Vue Element
- React Element
- Angular Element
整体上 UI 都是一套,但在不同框架中实现方式各异,API 变更较小,如果需要多个框架保持一套风格, Element 是非常好的选择。为了减少学习变更后项目api
antdesign功能极强,主要用来学习并模仿其语法及代码风格,主要基于React组件库的支持。感觉唯一的不足时在于当时使用时缺少一些在线预览的功能,最近又出了antdvue
飞冰最有意思的是钉钉群实时答疑让p7给你答疑(前提是混入群中)。500+ ICE 使用者在群里问任何层级的前端问题 React 组件。基础组件使用 Fusion,此外根据业务特性等开发了 40+ 业务组件
Playground:可复用模板,用于快速展示效果的业务。
5、WebRequest
API 可以让插件监控 Chrome 的网络请求,甚至重定向请求。例如:临时替换hotfix分支的图片
// background.js
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
const url = details.url;
if (url === 'http://n.sinaimg.cn/news/1_img/upload/7b577cec/576/w778h598/20180820/lSSg-hhxaafy9194151.jpg') {
console.log(22)
return {
redirectUrl: 'https://github.com/welearnmore/chrome-extension-book/raw/master/doc/images/logo_google_developers.png'
}
}
return {cancel: false}
},
{urls: ["<all_urls>"]},
["blocking"]
)
6、减少reflow的方法
不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className:
// 不好的写法
var left = 10, top = 10; el.style.left = left + "px"; el.style.top = top + "px";
// 推荐写法
el.className += " theclassname";
把 DOM 离线后修改。如:
-
a> 使用 documentFragment 对象在内存里操作 DOM。
-
b> 先把 DOM 给 display:none (有一次 repaint),然后你想怎么改就怎么改。比如修改 100 次,然后再把他显示出来。
-
c> clone 一个 DOM 节点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。不要把 DOM 节点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。尽可能的修改层级比较低的 DOM节点。当然,改变层级比较底的 DOM节点有可能会造成大面积的 reflow,但是也可能影响范围很小。
-
为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是会大大减小 reflow 。千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。
参考:
7、微任务与宏任务与eventloop
重点记住promise在.then之前是同步任务,.then/.catch/.finally是微任务,执行完同步任务后,在异步中最先执行的就是promise
执行顺序:同步任务--->微任务--->宏任务
8、隐式转换全部情况
!![] == true //结果是true [] == true //结果是false ![] == [] //结果是true
针对[] == true 与!![]的解释参考:
记忆方式
[] 转为字符串是 "" // String([]) 返回""
[] 转为数字是 0 // Number([]) 返回0
[] 转为布尔值是 true // Boolean([]) 返回true
true 转为数字是 1 // Number(true) 返回1
false 转为数字是 0 // Number(false) 返回0
9、webstorage
着重点在于sessionstorage与localstorage的数据存储机制及处理机制。
10、如何使用sessionID判别用户状态
将cookie中放入响应头中携带相应sessionID通过post方式向后端发请求,后端返回结果为用户独特的sessionID与前端匹配,则不用创建新的sessionID,假若不匹配则需要创建一个新的sessionID,归根结底还是由于HTTP的无状态性,web容器生成一个sessionid来标识用户,以便获取该用户对应的session信息。 后台生成一个新sessionid的可能原因:
这是一个新用户的第一次请求后端存在清空session的逻辑前端没有将sessionid放到cookie或其他约定的地方传给后端前端传了,但后端没有匹配到对应的sessionid(如果是个分布式服务,负载均衡后,后端服务没有做session同步)
11、OAuth2原理及应用
允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。
应用场景:
原生app授权:app登录请求后台接口,为了安全认证,所有请求都带token信息,如果登录验证、请求后台数据。
前后端分离单页面应用(spa):前后端分离框架,前端请求后台数据,需要进行oauth2安全认证,比如使用vue、react后者h5开发的app。
流程:
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
12、socket.io的前端使用
客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript的任何 SocketIO 官方客户端库或任何兼容的客户端来建立与服务器的永久连接。
引入http://socket.io的依赖在react框架中进行使用,自己尝试实现了一个聊天室:
testconnect=()=>{
let socket = sockjs("ws://localhost:3900", {
transports: ['websocket']
})
// /不间断尝试重连接
socket.on('reconnect_attempt',()=> {
console.log("reconnect")
socket.transports = ['websocket','polling', 'flashsocket'];
});
// 重连接时出错
socket.on('reconnect_error',(attemptNumber)=> {
console.log(attemptNumber)
});
//连接成功走这个方法
socket.on('connect',()=>{
console.log(socket.connected)
})
//报错时走这个方法
socket.on('connect_error', (error) => {
console.log(error)
});
//连接存活验证
socket.on('ping', (error) => {
console.log('ping_include')
});
// 连接成功的connect方法
socket.on("connect",function(){
// console.log(socket.broadcast)
socket.emit('join',prompt('what is your nickname'));
$('#chat').css('display','block');
socket.on('announcement',(msg)=>{
if(msg){
console.log("announcement did right")
let li = `<li class="announcement">${msg}</li>`
$("#messages").append(li);
}
})
})
// 添加获取信息的方法
$("#form").submit(()=>{
let inputan =$('#input');
console.log("submit success")
this.addmessage('me',inputan.val()) ;
socket.emit('text',inputan.val());
inputan.attr('value');
inputan.focus();
return false
} )
//不要自执行,要在调用后再执行
socket.on('text',this.addmessage)
}
// 将聊天记录添加到首页的每一个字段上
addmessage=(from,text)=>{
if(text){
let li = `<li class="message"><b>${from}</b>:${text}</li>`
$("#messages").append(li);
}
}
13、webpack的作用及核心配置
webpack配置中需要理解几个核心的概念Entry 、Output、Loaders 、Plugins、 Chunk
-
Entry:指定webpack开始构建的入口模块,从该模块开始构建并计算出直接或间接依赖的模块或者库
-
Output:告诉webpack如何命名输出的文件以及输出的目录
-
Loaders:由于webpack只能处理javascript,所以我们需要对一些非js文件处理成webpack能够处理的模块,比如sass文件
-
Plugins:Loaders将各类型的文件处理成webpack能够处理的模块,plugins有着很强的能力。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。但也是最复杂的一个。比如对js文件进行压缩优化的UglifyJsPlugin插件
-
Chunk:coding split的产物,我们可以对一些代码打包成一个单独的chunk,比如某些公共模块,去重,更好的利用缓存。或者按需加载某些功能模块,优化加载时间。在webpack3及以前我们都利用CommonsChunkPlugin将一些公共代码分割成一个chunk,实现单独加载。在webpack4 中CommonsChunkPlugin被废弃,使用SplitChunksPlugin
参考
进阶(具备手撸一个loader、plugins的能力):
干货!撸一个webpack插件(内含tapable详解+webpack流程)
14、==与===的比较,===的使用情况
===的使用情况我回答是,一般在比较字符串时来使用。
权威解释:
15、闭包的应用场景
函数防抖,通过立即执行函数在循环中的异步执行能够取到正确的值
权威解答:
16、敏捷开发的全部流程
每次迭代都必须依次完成以下五个步骤。
- 需求分析(requirements analysis)
- 设计(design)
- 编码(coding)
- 测试(testing)
- 部署和评估(deployment / evaluation)
每个迭代大约持续2~6周。
17、webpack+glup/FIS
gulp是基于流的自动化构建工具,但不包括模块化的功能,如果要用到的话,就需要引入外部文件,比如require.js等;而webpack是自动化模块打包工具,本身就具有模块化,并且也具有压缩合并的功能。
【彻底理解】
三者的比较
定位不同,webpack定位是一个打包工具,模块化。其实自动化的工具更好用gulp之类解决。fis3直接定位为一个全功能工具,官方文档介绍中:解决性能优化,模块化,自动化,甚至包括代码规范,部署等问题。
个人喜欢用webpack,可以更灵活的搭配其它工具使用,且生态系统强大,当然最近比较火的可能是rollup,它打包的文件体积更小。glup+webpack自动化部署参考:
18、git常用的基本命令
最最基础的去参考我自己的文章 进阶版看这篇
19、jar包查看项目进程
到xxx.jar目录下执行:
nohup java -jar xxx.jar > people.log 2>&1 &
-- 运行jar包并包日志写入到people.log中
tail -f people.log
--查看运行日志
20、mvc与mvvm的区别
mvc
Model(模型)
View(视图)
Controller(控制器)
简单的理解:视图请求数据,将请求发送至控制器,控制器再将请求发送给模型,模型去查找数据,找到之后传给控制器,控制器再传给视图进行渲染。
mvvm
Model 代表数据模型
View 代表UI视图
ViewModel 负责监听 Model 中数据的改变并且控制视图的更新(桥梁,可以理解成mvc中的控制器) 简单理解:视图请求数据,将请求发送至控制器,在控制器的两端具有监听机制,直接调用模型的数据,一端改变全部改变,利用数据劫持,结合订阅者和发布者模式,实现数据的双向绑定
mvvm优点
MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也观察不到View,这种低耦合模式提高代码的可重用性
双向绑定的定义
一般只有UI表单控件才存在双向数据绑定,非UI表单控件只有单向数据绑定。单向数据绑定是指:M的变化可以自动更新到ViewModel,但ViewModel的变化需要手动更新到M(通过给表单控件设置事件监听)双向数据绑定是指念:M的变化可以自动更新到ViewModel,ViewModel的变化也可以自动更新到M双向绑定 = 单向绑定 + UI事件监听。双向和单向只不过是框架封装程度上的差异,本质上两者是可以相互转换的。
优缺点:在表单交互较多的情况下,单向数据绑定的优点是数据更易于跟踪管理和维护,缺点是代码量较多比较啰嗦,双向数据绑定的优缺点和单向绑定正好相反。
MVVM模式在react中的对应关系
- M(odel):对应组件的方法或生命周期函数中实现的业务逻辑和this.state中保存的本地数据,如果React集成了redux +react-redux,那么组件中的业务逻辑和本地数据可以完全被解耦出来单独存放当做M层,如业务逻辑放在Reducer和Action中。
- V(iew)-M(odel):对应组件中的JSX,它实质上是Virtual DOM的语法糖。React负责维护 Virtual DOM以及对其进行diff运算,而React-dom 会把Virtual DOM渲染成浏览器中的真实DOM
- View:对应框架在浏览器中基于虚拟DOM生成的真实DOM(并不需要我们自己书写)以及我们书写的CSS绑定器:对应JSX中的命令以及绑定的数据,如className={ this.props.xxx }、{this.props.xxx}等等
21、html语义化,css模块化
语义化
就是尽可能的理解要表达的内容,选择适合的标签,将内容转换成浏览器认识的语言,通过浏览器传达给用户。从这个角度来说,我们更像是“翻译”。
除了专业的人外,没人会去看我们的标签是否使用得有语义HTML的标签还不足以表达所有可能的语义语义化会需要增加一些额外的代码
HTML5新增的几个标签,更多的补充了目前HTML标签语义上的不足,这点也可以看出语义化是以后发展的一个方向,当然更大的目标是统一的实现标准,语义化只是为了这个目标所使用的一个方法。这可能需要相当的一段时间,而我们正经历着这个过程。
模块化
模块化就是为了减少循环依赖,减少耦合,提高设计的效率。为了做到这一点,我们需要有一个设计规则,所有的模块都在这个规则下进 行设计。良好的设计规则,会把耦合密集的设计参数进行归类作为一个模块,并以此划分工作任务。而模块之间彼此通过一个固定的接口(所谓的可见参数)进行交互,除此之外的内部实现(所谓的隐参数)则由模块的开发团队进行自由发挥。
程序模块化的目的:
1.减少循环依赖
2.减少耦合
3.提高设计效率
css模块化原则
分离结构和表现分离容器和内容
22、标准化的javascript
JavaScript 的核心 ECMAScript 描述了该语言的语法和基本对象; DOM 描述了处理网页内容的方法和接口; BOM 描述了与浏览器进行交互的方法和接口。
23、前端兼容性问题总结
24、前端性能优化
25、loadash的使用
26、前端预处理器sass的使用
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
27、leetcode算法最优解
找不到想要的解答,从这上面搜一下
九章算法 - 帮助更多中国人找到好工作,硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧
28、很重要的三种函数写法
一篇文章搞懂toString()和valueOf() - html/css语言栏目:html.css - 红黑联盟
29、react源码总结
react在使用时总结不出这么多优点,他帮你解决了面试提问的难题:
30、Flex布局,position,垂直水平居中三种必问前端常识
CSS 中,position:absolute、float、display:inline-block 都能实现相同效果,区别是什么?
31、破碎浮点型数据的解决办法
过长的纯数字数组不能通过Number或者parseInt进行转化,这样会产生错误,要使用BigInt来解决。想要计算二元运算需要在二元运算的另一个项上加上n,参考例子与讲解均在里面:
32、中级前端所有手写内容
- 防抖、
- 节流深浅拷贝数组乱序、
- 数组去重(各种时间空间复杂度)
- 数组filter数组flat(平展一层到多层)
- 手写call、bind、apply(及了解这三种的区别)
- 八种继承及各种继承之间的特点
- 实现instanceof
- 实现new的过程
- lazyman
- jsonp的实现
- 函数的柯力化
- promise、promise.all、promise.retry (其中大厂不排除让你手写ajax的封装(百度),头条(promise.retry)有点变1态了)
参考地址:
“寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之手写题(一) - 掘金
“寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之手写题(二) - 掘金
33、大厂常问的React全家桶
必须掌握、必须掌握、必须掌握!
react-router:
redux、react-redux:
一篇文章总结redux、react-redux、redux-saga - 掘金
拓展(强烈建议能手写出来)、几家大厂都在问:
让react用起来更得心应手--(react-router原理简析) - 掘金
34、三分钟记牢原型,原型链,继承
function Animal(){
this.type = "animal";
}
Animal.prototype.getType = function(){
return this.type;
}
function Dog(){
this.name = "dog";
}
Dog.prototype = new Animal();
Dog.prototype.getName = function(){
return this.name;
}
var xiaohuang = new Dog();
//原型链关系
xiaohuang.__proto__ === Dog.prototype
Dog.prototype.__proto__ === Animal.prototype
Animal.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null
35、解释下Promise与Promise.all及扩展
promise是什么? Promise是异步编程的一种解决方案,比传统的回调函数和事件更合理和强大。 所谓Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事情(通常是一个异步操作)。从语法上说,Promise是一个对象,从他可以获取异步操作的消息。
特质:
一:对象的状态不受外部影响
二:一旦状态改变,就无法再被改变。
缺点:
一旦创建promise就会立即执行
使用:
const newPromise = new promise((resolve,reject)=>{
if(success){
resolve()
}else{
reject()
}
}).then((data)=>{console.log(data)},(error)=>{console.log(error})
.catch(null,(error)=>{console.log(error)})
then方法可以接受两个回调函数作为参数,
第一个回调函数是promise对象的状态变为resolved的时候调用,
第二个回调函数是promise对象的状态变为rejected时调用。
其中第二个函数是可选的,不一定需要提供。
catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
promise.all是什么?
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
result = arr.map(i => {
...
const rowPromise = filtered
.sort({ create_time: -1 }) //-1降序 1升序
.skip(offset > -1 ? offset : 0)
.limit(limit <= 200000 ? limit : 200000)
.toArray()
return rowPromise
})
promise.all(result)
.then(total => resolve(total))
.catch(err => reject(err))
promise.all中传入的result一定要是一个数组。返回的是个promise实例,机制与promise一致
详细的promise.all&promise.race参考
36、ES6中export与export default差异总结
- export default在一个模块中只能有一个,但是export可以有多个。
- 通过export导出的(属性或者方法)可以修改,但是通过export default导出的是不可修改的。
- export var e1='...' 是合法语句,但是export default var e2='...'是不合法的(let和const也一样)。
- export default可以直接添加标识符导出,例如export default e2;
- export如果要导出已经声明的表示符,必须使用{},例如export {e1},注意:这里{}不是声明一个对象。
- ES6中模块通过export和export default暴露出来的属性或者方式并不是普通的赋值或者引用,它们是对模块内部定义的标志符类似指针的绑定。
- 对于一个导出的属性或者方法,在什么地方导出不重要,在什么时候导入也不重要,重要的是:访问这这个绑定的时候的当前值。
ES6 export && export default 差异总结
37、简述Generator函数的基本语法
Generator (生成器)函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象。
特征一:function关键字与函数名之间有一个号(*写在之间的任何位置都可以通过,不区分有几个空格)
特征二:函数体内有yield(产出)表达式,定义了不同的内部状态
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
函数执行.next()后返回的也不是函数运行结果,而是一个指向内部状态的指针对象。每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
function* gen() {
yield 123 + 456;
}
上面代码中,yield后面的表达式123 + 456,不会立即求值,只会在next方法将指针移到这一句时,才会求值。
yield表达式与return语句既有相似之处,也有区别。相似之处在于,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。正常函数只能返回一个值,因为只能执行一次return;Generator 函数可以返回一系列的值,因为可以有任意多个yield。
for...of循环,扩展运算符(...)、解构赋值和Array.from方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数
function* numbers () {
yield 1
yield 2
return 3
yield 4
}
// 扩展运算符
[...numbers()] // [1, 2]
// Array.from 方法
Array.from(numbers()) // [1, 2]
// 解构赋值
let [x, y] = numbers();
x // 1
y // 2
// for...of 循环
for (let n of numbers()) {
console.log(n)
}
// 1
// 2
前端大群
微信核心500人群:群内不定期会有赞助商送书活动,同时与腾讯云+社区合作(过节福利相送),BAT大厂资深大牛定期推送面经与源码分析,各平台大牛优秀文章推荐,更有内推跳槽咨询、视频资源共享、学习资料文章pdf面经网盘资源等等福利。加入我们一起进步。
群内人数过多,扫描二维码添加客服小柠,备注「加群」即可加入我们。
持续更新中~~~
公众号:Andh666[中台架构之家]
欢迎一起交流,一起进步。
对于自己职业规划不够清晰的小伙伴,我为大家梳理了一篇职业规划手册,用以参考。充实不甘平凡的自己