1、闭包?
JS 中的闭包是什么?
(1)什么是闭包?
函数和函数内部可以访问的变量组合一起就叫做闭包
<!DOCTYPE html>
<html>
<body>
闭包
<button onclick="window.b()">++</button>
<button onclick="window.c()">--</button>
<script>
!function(){
var a = 1;
window.b = function (){ //函数
a++; //变量a:函数内部可以访问的变量
console.log(a);
}
window.c = function (){
a--;
console.log(a);
}
}()
</script>
</body>
</html>
方法二:
<!DOCTYPE html>
<html>
<body>
闭包
<button onclick="window.test()">++</button>
<script>
!function(){
function A(){
var a = 1;
return function B(){
a++;
console.log(a);
}
}
window.test = A();
}()
</script>
</body>
</html>
(2)闭包有什么作用?
-
闭包是用来间接访问一个变量
在某些需求条件下,如果用全局变量容易被误改,如果用局部变量则外界无法访问。这种情况就需要一个可以访问内部局部变量的函数,通过函数去修改局部变量。利用函数去形成间接访问变量。
-
闭包可以保护命名冲突,解决循环绑定引发的索引问题
前端面试题2021及答案
(3)闭包的应用:
- 设计模式中的单例模式(唯一一个实例作为局部变量,通过其他函数对其进行访问)
- for循环中的保留i的操作
- 防抖和节流
- 函数柯里化
- map函数
(4)闭包的缺点:
会出现内存泄漏问题。因为正常函数调用完后会被释放掉,而闭包函数在程序某个地方有引用,即没有执行结束,则不会被释放
-
什么是内存泄漏
指不再用的内存没有被及时释放出来,导致该段内容无法被使用
-
为什么会导致内存泄漏
指我们无法通过js访问某个对象,而垃圾回收机制却认为该对象还在被引用,因此垃圾回收机制不会释放对象,导致该块内存永远无法释放,积少成多,系统会越来越卡以至于崩溃
-
垃圾回收机制都有哪些策略
- 标记清除法
垃圾回收机制获取根并标记他们,然后访问并标记所有来自它们的引用,然后在访问这些对象并标记它们的引用…如此递进结束后若发现有没有标记的(不可达的)进行删除,进入执行环境的不能进行删除
- 引用计数法
当声明一个变量并给该变量赋值一个引用类型的值时候,该值的计数+1,当该值赋值给另一个变量的时候,该计数+1,当该值被其他值取代的时候,该计数-1,当计数变为0的时候,说明无法访问该值了,垃圾回收机制清除该对象
4、不同框架的区别
(1)跨端框架区别对比
5个主流跨端框架区别对比
Flutter介绍 - Flutter,H5,React Native之间的对比
Flutter介绍 - Flutter,H5,React Native之间的对比
对比平台–React Native与Flutter之间的区别
1)原生代码开发App:
优点:
- 可访问手机所有功能(如GPS、摄像头等)、可实现功能最齐全;
- 运行速度快、性能高,绝佳的用户体验;
- 支持大量图形和动画,不卡顿,反应快;
- 兼容性高,每个代码都经过程序员精心设计,一般不会出现闪退的情况,还能防止病毒和漏洞的出现;
- 比较快捷地使用设备端提供的接口,处理速度上有优势
缺点:
- 开发时间长,成本高;
- 可移植性比较差,一款原生的App,Android和IOS都要各自开发,同样的逻辑、界面要写两套;
- 内容限制(App Store限制)
- 每次更新需要应用商店审核,过程长
2)H5:网页+js
- 渲染差体验感差
- 调用硬件设备需要原生配合
3)React Native
优点:
- 使用JavaScript语言,由于JS被广泛地使用,所以RN也很容易被接受。
- RN依赖JS的运行时环境,也就是JS桥接技术。其使用Facebook的Flux架构。
- RN仅提供了UI渲染和设备访问的API,很多功能必须依赖第三方库来实现对本地组件的使用。
- 生态目前比较完善,使用的公司也比较多,特别是对JS比较熟悉的同学容易上手。
- 支持热部署,开发过程中可以节约很多时间。
缺点:
- 它的渲染方式还是调用各个平台的原生控件,有时需要针对不同的平台做不同的优化。
- 其性能相对于H5有很大的提高,但是并没有完美解决,白屏,丢帧问题依然存在。
4)Flutter
Flutter渲染及性能优化
优点:
- 它将代码编译成原生代码,并且直接在各个平台中使用其高效渲染引擎Skia进行渲染,没有桥接,不调用平台相关控件。
- 使用谷歌自己的Skia渲染引擎,Android自带Skia引擎,iOS平台上Flutter也会把Skia引擎打包到APP中,实现高效渲染。
- 目前有非常丰富的视图组件,可以点击这里查看其组件目录,包括Android上常用的材料设计(Material Design)的UI风格,和iOS风格(Cupertino)。由于其渲染不依赖各平台相关组件,所以运行在不同平台上的效果是一致的。
- 同样支持热部署,开发时可以像网页开发一样实时看到效果。
- 在Flutter的响应式框架中,控件树中的控件直接通过可移植的图形加速渲染引擎、高性能的本地ARM代码进行绘制,不再需要通过虚拟DOM或虚拟控件、真实DOM或平台控件这些中间对象来绘制。Flutter响应式框架通过“无中间商赚差价”的方式直接利用硬件的所有性能,
5)详解单向数据流与双向数据绑定
-
单向数据流优缺点:
优点:
- 所有状态的改变可记录、可跟踪,源头易追溯;
- 所有数据只有一份,组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于应用的可维护性;
缺点:
- 手动更新视图
- 代码量上升,数据流转过程变长,出现很多类似的样板代码;
- 同时由于对应用状态独立管理的严格要求(单一的全局store),在处理局部状态较多的场景时(如用户输入交互较多的“富表单型”应用),会显得啰嗦及繁琐。
-
双向数据绑定的优缺点:
优点:
- 无需手动修改视图
- 在表单交互较多的场景下,会简化大量业务无关的代码。
缺点:
- 无法追踪局部状态的变化;
- “暗箱操作”,增加了出错时 debug 的难度;
-
由于组件数据变化来源入口变得可能不止一个,数据流转方向易紊乱,若再缺乏“管制”手段,血崩。
6、Flutter是怎么接收数据的,与H5对比有那些不一样
参考资料:Flutter 学习 - 网络请求和数据解析
Flutter为何需解析后台所返回JSON?
在向服务器请求数据后,服务器往往会返回一段json字符串。而我们要想更加灵活的使用数据的话需要把json字符串转化成对象。由于flutter只提供了json to Map,因此需要手动json反序列化。
7、CSS
(1)垂直方向水平
CSS实现水平垂直居中的1010种方式
10种水平垂直居中对齐方式(史上最全)
如何实现一个元素的水平垂直居中
(2)属性overflow属性
1)overflow:scroll,必会出现滚动条。
2)overflow:auto,子元素内容大于父元素时出现滚动条。
3)overflow:visible,溢出的内容出现在父元素之外。
4)overflow:hidden,溢出隐藏。
(3)ie6-ie8不支持opacity透明度的解决方法
opacity 是css3属性, IE8以下浏览器不支持CSS3,而IE8只支持非常小的一部分、
解决方法:IE8 以及更早的版本支持替代的 filter 属性。例如:filter:Alpha(opacity=50)
(4)IE8下兼容background-size
background: url(./images/item-img.png) no-repeat;
background-size: cover;
background-size:100% 100%; //部分浏览器对cover不起作用,因此添加多一个100%,确保图片可以填充整个盒子大小
/* 此处加上-ms前缀,让IE识别 */
-ms-filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/item-img.png',sizingMethod='scale');
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/item-img.png',sizingMethod='scale');
/* \9 是 IE的CSS hack,IE9以下识别,不包括IE 9 */
background: none\9;
(5)请说明px,em,rem,vw,vh,rpx等单位的特性
1)px 像素
2)em 当前元素的字体大小
3)rem 根元素字体大小
4)vm 100vm是总宽度
5)vh 100vh是总高度
6)rpx 750rpx是总宽度
rpx 尺寸单位
- rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素
(6)first-of-type和first-child有什么区别
1) first-of-type
- 匹配的是从第一个子元素开始数,匹配到的那个的第一个元素(是第一个符合条件的子元素,不一定是父元素下的第一个子元素)
2)first-child
- 必须是第一个子元素
(7)BFC
什么是BFC?看这一篇就够了
1)BFC是一个独立渲染区域,它丝毫不会影响到外部元素
2)BFC特性
- 同一个BFC下margin会重叠
- 计算BFC高度时会算上浮动元素
- BFC不会影响到外部元素
- BFC内部元素是垂直排列的
- BFC区域不会与float元素重叠
3)如何创建BFC
- position设为absolute或者fixed
- float不为none
- overflow设置为hidden
- display设置为inline-block或者inline-table或flex
4)清除浮动
1)将父元素设置为BFC,因为BFC计算高度时会加上浮动元素
2)clear:both (同层块有浮动元素)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>清除浮动</title>
</head>
<style>
.par {
border: 5px solid rgb(91, 243, 30);
width: 300px;
overflow: hidden;
}
.child {
border: 5px solid rgb(233, 250, 84);
width:100px;
height: 100px;
float: left;
}
</style>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
</html>
页面:
clear参数值说明:
- none : 允许两边都可以有浮动对象
- both : 不允许有浮动对象
- left : 不允许左边有浮动对象
- right : 不允许右边有浮动对象
3)使用after(推荐),在父级元素设置
<style>
.clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden;
}
.clearfix{
*zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/
}
</style>
<body>
<div class="fahter clearfix">
<div class="big">big</div>
<div class="small">small</div>
<!--<div class="clear">额外标签法</div>-->
</div>
(8)css盒子模型
1)盒子模型包括:marign、border、padding、content
2)盒子宽高计算:border+padding+content
在chorme F12控制台element里计算的宽高是不包括margin,但实际我们清楚margin会占据位置
3)标准模式(content-box)、怪异模式(border-box)1
css盒模型content-box和border-box
-
当box-sizing:content-box时,我们使用的是标准盒模型,
真正总宽度 = width(设置的总宽度) + padding(左右) + border(左右)
-
当box-sizing:border-box时,我们使用的是怪异模式盒模型,
设置的总宽度 = width = content宽度+padding(左右)宽度 + border(左右)宽度。
(9)定义好图片的尺寸,在加载时可以预留指定空间,减少闪烁
<img src="html5.gif" alt="HTML5" style="width:128px;height:128px">
9、性能优化
(1)白屏问题
引起白屏现象:
- 面加载了大量的 CSS 或者是 JavaScript 文件
(2)浏览器运行性能优化
前端性能优化 24 条建议(2020)
1)减少 HTTP 请求:请求量大的文件可以做缓存或者存放在项目public中
2)将 CSS 放在文件头部,JavaScript 文件放在底部
- CSS 执行会阻塞渲染,阻止 JS 执行
- JS 加载和执行会阻塞 HTML 解析,阻止 CSSOM 构建
3)使用字体图标 iconfont 代替图片图标;小图标可以用精灵图代替
4)压缩文件
5)图片懒加载,图片滚动到可视区位置再加载
6)使用防抖(重在清零)、节流(重在加锁)的方法减少用户快速多次操作引起的问题
(3)JS性能优化的方式
- 垃圾回收
- 闭包中的对象清楚
- 防抖节流
- 分批加载(setInterval,加载10000个节点)
- 事件委托
- 少用with
- requestAnimationFrame的使用
- script标签中的defer和async
- CDN
(4)说一说性能优化有哪些性能指标,如何量化?
1)常用的性能优化指标:
- 页面加载时间
- 首次渲染
- 交互动作的反馈时间
- 异步请求完成时间
2)使用性能测量工具进行量化
- Chrome DevTools
- 开发调试、性能评测
- Throttling 调整网络吞吐
- Performance 性能分析
- Network 网络加载分析
(5)工作中如何进行前端性能优化(21种优化+7种定位方式)
- 减少http请求,缩短http请求时间
- 添加loading效果,优化页面初始化白屏情况,提高用户体验感
- 节流、防抖
- 规范化代码命名、做相关的注释
- 代码压缩打包
11、html
(1)html文件引用less文件失效
//如果用css,rel="stylesheet"
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
//如果用less,rel="stylesheet/less"
<head>
<link rel="stylesheet/less" type="text/css" href="style.css">
</head>
(2)script标签中defer和async都表示了什么
众所周知script会阻塞页面的加载,如果我们要是引用外部js,假如这个外部js请求很久的话就难免出现空白页的问题,好在官方提供了defer和async
1)defer
- 不会阻止页面解析,并行下载对应的js文件
- 下载完之后不会执行
- 等所有其他脚本加载完之后,在DOMContentLoaded事件之前执行对应d.js、e.js
<script src="d.js" defer></script>
<script src="e.js" defer></script>
3) async
4. 不会阻止DOM解析,并行下载对应的js文件
5. 下载完后立即执行
<script src="b.js" async></script>
<script src="c.js" async></script>
4)补充:DOMContentLoaded事件
6. 是等HTML文档完全加载完和解析完之后运行的事件
7. 在load事件之前不用等样式表,图像等完成加载
(3)doctype标签和meta标签
1)doctype
- 告诉浏览器以什么样的文档规范解析文档
- 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。如果DOCTYPE不存在会导致文档以兼容模式呈现
- 标准模式和兼容模式
- 标准模式–>正常,排版和js运作模式都是以最高标准运行
- 兼容模式–>非正常
- **声明必须是 HTML 文档的第一行**,位于 标签之前。
2)meta
- 素可提供有关页面的元信息,比如针对搜索引擎和更新频度的描述和关键词。
- 标签位于文档的头部,不包含任何内容
<meta http-equiv="charset" content="iso-8859-1">
<meta http-equiv="expires" content="31 Dec 2008">
(4)link标签和import标签引入css的区别
- link属于html,而@import属于css
- 页面被加载时,link会同时被加载,而@import引用的css会等到页面加载结束后加载。
- link是html标签,因此没有兼容性,而@import只有IE5以上才能识别。
- link方式样式的权重高于@import的。
- 模块加载命令import 时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,
13、Redux
(1)起源:
React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两个方面,它没涉及。对于大型的复杂应用来说,这两方面恰恰是最关键的。因此,只用 React 没法写大型应用。
1)代码结构
2)组件之间的通信(可以类比Vue组件间的通信)
(2)Redux 中核心就是一个单一的 state。state 通过闭包的形式存放在 redux store 中,保证其是只读的。如果你想要更改 state,只能通过发送 action 进行,action 本质上就是一个普通的对象。
Redux 是一个有用的架构,但不是非用不可。以下情况可以考虑用redux。
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
(3)工作流程
1)reducer :更新store
保持 reducer 纯净非常重要。永远不要在 reducer 里做这些操作:
修改传入参数;
执行有副作用的操作,如 API 请求和路由跳转;
调用非纯函数,如 Date.now() 或 Math.random()。
(4)注意点
Redux一个用于应用程序状态管理的开源JavaScript库,本质是管理组件数据状态的。刷新浏览器,相当于重新开启应用,必定会从最初的状态重新开始。
state更新后,页面也会被刷新
解决方法:
1)向后台发送请求
2)将值本地存储(local storage、session storage)
3)redux-persist持久化数据存储
(5)dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
dva官方文档
浅析dva (史上最全的dva用法及分析)
1)如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State
(6)Redux一个用于应用程序状态管理的开源JavaScript库,本质是管理组件数据状态的。刷新浏览器,相当于重新开启应用,必定会从最初的状态重新开始。
17、小程序
(1)特点:
- 即插即用,
- 拥有 native 和跨端(不同操作系统)的能力
- 性能比 H5 好
- 无跨域问题:因为小程序请求是小程序后台去访问我们自己设置好的api地址,并非像浏览器那种直接客户端请求服务端。
(2)小程序架构
1)基本原理
- 微信小程序多线程模型
- 小程序有一个 JS 线程和若干个 webview,我们称之为 view 层, view 不能够执行 JS 代码,而是负责 UI 显示,它由开发者编写的 wxml 和 wxss 转换后代码以及微信提供相关辅助模块组成。
-
一个 view 模块对应一个 webview 组件(也就是我们常规理解的一个页面), 小程序支持同时多个 view 存在。view
模块通过 WeixinJSBridge 对象来跟后台通信
-
微信 Native 程序会预先加载一个 WebView,当打开指定页面时,无需加载额外资源直接渲染,这样会感觉 小程序会很快。
-
小程序也会与 CDN 和 web server 进行一些交互,具体为: 小程序初始化时,先从微信的 CDN 下载小程序的完整的包,然后在微信内部进行解包初始化。
2)不足:
json 格式的数据传递和解析相比与原生 API 都是损耗不菲的,如果频繁调用很可能损耗 过多性能,进而影响用户体验。
3)总结
- 提前新建 Web View,准备新页面渲染
- View 层和逻辑层分离,通过数据驱动,不直接操作 DOM
- 使用 Virtual DOM,进行局部更新
- 全部使用 https,确保传输过程中安全
- 前端组件化开发
- 加入 rpx 单位,隔离设备尺寸,方便开发
- rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素
- 根据不同的手机屏幕,rpx的比例不一样。移动端看自身需求去判断使用rpx还是px
(3)小程序简介:
小程序简介
1)小程序与普通网页开发的区别:
同:主要开发语言是 JavaScript
异:
4. 网页开发渲染线程和脚本线程是互斥的。小程序中二者是分开的
-
网页可以使用DOM、BOM。小程序无完整浏览器对象无法使用部分DOM、BOM,因此也无法使用部分前端库,npm包
网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作。小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API.
这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
-
网页需要兼容各种浏览器。小程序只要面对iOS 和 Android以及辅助开发的小程序开发者工具
2)框架
- 框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
3)小程序运行机制
-
小程序的生命周期
-
微信小程序之生命周期(三)
注意事项
(1)每当小程序可能被销毁之前,页面回调函数 onSaveExitState 会被调用。如果想保留页面中的状态,可以在这个回调函数中“保存”一些数据,下次启动时可以通过 exitState 获得这些已保存数据。
(2)在小程序存活期间, onSaveExitState 可能会被多次调用,此时以最后一次的调用结果作为最终结果。
18、原生通信
1) h5 与原生 app 交互的原理
20、包管理
(1)npm、yarn、tink区别
1)npm(node package manager)是一个node包管理工具,我们可以方便的从npm服务器下载第三方包到本地使用。
2)cnpm:使用淘宝镜像,下载速度比npm快
21、Typescript
(1)TS 是 JS 的超集,提供了很多 JS 没有的特性,尤其是 ES6 之前。ES6+的很多东西也是借鉴了 TS。
(2)TS 对于构建大型系统有着得天独厚的优势,主打大型项目
22、单页面、多页面
(1)Vue、react他们都是负责开发视图层,单页多页关系不大,如果讨论单多页还要结合路由来看,比如 vue-router, react-router。
(2)如果需要做多页面,在webpack上添加多个入口
23、正则表达式
正则表达式讲解
常用正则表达式
(1)匹配中文正则
https://www.jb51.net/article/102253.htm
<script>
var pattern1 = /[\u4e00-\u9fa5]+/g;
var pattern2 = /\[[\u4e00-\u9fa5]+\]/g;
var contents = "[微笑][撇嘴][发呆][得意][流泪]";
var content = contents.match(pattern1);
alert(content);
content = contents.match(pattern2);
alert(content);
</script>
(2)实现千分位展示
//实现千分位展示
num.replace(/(\d)(?=(\d{3})+(?!\d))/, $1 => $1 + ",");
//千分位转数字
str.replace(/,/g, '');
//或
str.replace(/[^\d\.]/g, '');
24、antd 2.x版本
(1)inputNumber:
1)配置parser后,onChange函数会拿到格式化之后的值,但onFocus、onBlur事件获取到当前对象,它只能获取到页面展示的文本而非格式化后的数据
25、Ajax
Aiax常见面试题
(1)什么是ajax?
AJAX === 异步 JavaScript 和 XML。 AJAX 是一种用于创建快速动态网页的技术。 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。(即通过XML异步获取数据,利用js修改Dom。局部刷新页面)
因为在没有Ajax技术之前,网页通过form(表单)方式请求数据,用户点击提交后等待服务器响应,页面重新加载。
(2)为什么要用ajax:
异步请求数据,局部刷新页面,提高用户体验,优化了浏览器和服务器之间的传输,减少了带宽占用。
(3)Ajax的核心是JavaScript对象XmlHttpRequest
XmlHttpRequest它是一种支持异步请求的技术
1)XMLHttpRequest对象的常用方法和属性
- open(“method”,”URL”) 建立对服务器的调用,第一个参数是HTTP请求方式可以为GET,POST或任何服务器所支持的您想调用的方式。 第二个参数是请求页面的URL。
- send()方法,发送具体请求
- abort()方法,停止当前请求
- readyState属性 请求的状态 有5个可取值0=未初始化 ,1=正在加载 2=以加载,3=交互中,4=完成
- responseText 属性 服务器的响应,表示为一个串
- reponseXML 属性 服务器的响应,表示为XML
- status 服务器的HTTP状态码,200对应ok 400对应not found
(4)AJAX技术体系的组成部分有哪些。
HTML,css,dom,xml,xmlHttpRequest,javascript
(5)ajax请求有几个步骤:(5~6个)
//1、创建 XMLHttpRequest 对象
var ajax = new XMLHttpRequest();
//2、规定请求的类型、URL 以及是否异步处理请求。
ajax.open('GET',url,true);
//3、发送信息至服务器时内容编码类型
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//4、发送请求
ajax.send(null);
//5、接受服务器响应数据
ajax.onreadystatechange = function () {
if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) {
}
};
//使用JavaScript和DOM实现局部刷新
(6)ajax几种请求方式:
1)常用的post,get(http默认的请求方法),delete,put
2)get与post的区别,什么时候使用post?
- get请求相对来说更简单、快速,效率高些;因此主要用于搜索,获取,而post多用于创建/更新
- get有缓存,post一般不缓存
- get体积小(url的长度由浏览器来限制),post也有服务器对它的限制,只是限制的长度比较大,满足了平常的需求
GET请求中URL的最大长度限制总结
- get大部分使用ASCII字符,中文字出现在url上用百分号(%)编码;post没有限制
- get请求参数会保留历史记录,post中参数不会保留
- get会被浏览器主动catch,post不会,需要手动设置
- get在浏览器回退时无害,post会再次提交请求
- 传参
- get传参,参数是在url中的,可见
- 准确的说get传参也可以放到body中,只不过不推荐使用
- post传参,参数是在请求体中,不可见
- 准确的说post传参也可以放到url中,只不过不推荐使用
- 安全性
- get较不安全
- post较为安全
- 准确的说两者都不安全,都是明文传输的,在路过公网的时候都会被访问到,不管是url还是header还是body,都会被访问到,要想做到安全,就需要使用https
- 发送数据
- post传参发送两个请求包,一个是请求头,一个是请求体,请求头发送后服务器进行验证,要是验证通过的话就会给客户端发送一个100-continue的状态码,然后就会发送请求体
(7)ajax如何解决浏览器缓存问题
- 在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,“0”)
- 在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,“no-cache”)
- 在URL后面加上一个随机数: “fresh=” + Math.random();
- 在URL后面加上时间戳:“nowtime=” + new Date().getTime()
- 在jq ajax下,使用 $.ajaxSetup({cache:false}) 这样就不会保存缓存记录
(8)简述ajax的优缺点
优点:
- 无刷新更新数据(在不刷新整个页面的情况下维持与服务器通信)
- 异步与服务器通信(使用异步的方式与服务器通信,不打断用户的操作)
- 前端和后端负载均衡(将一些后端的工作交给前端,减少服务器与宽度的负担)
- 界面和应用相分离(ajax将界面和应用分离也就是数据与呈现相分离)
缺点:
- ajax不支持浏览器back按钮
- 安全问题 Aajax暴露了与服务器交互的细节
- 对搜索引擎的支持比较弱
- 破坏了Back与History后退按钮的正常行为等浏览器机制
(9)axios和Ajax的区别
axios是对Ajax的封装
26、axios
27、 什么是执行栈,什么是执行上下文
(1)执行上下文分为:
1)全局执行上下文
- 创建一个全局的window对象,并规定this指向window,执行js的时候就压入栈底,关闭浏览器的时候才弹出
2)函数执行上下文
-
每次函数调用时,都会新创建一个函数执行上下文
-
执行上下文分为创建阶段和执行阶段
- 创建阶段:函数环境会创建变量对象:arguments对象(并赋值)、函数声明(并赋值)、变量声明(不赋值),函数表达式声明(不赋值);会确定this指向;会确定作用域
- 执行阶段:变量赋值、函数表达式赋值,使变量对象编程活跃对象
3)eval执行上下文
(2)执行栈:
-
首先栈特点:先进后出(类似水桶)
- 当进入一个执行环境,就会创建出它的执行上下文,然后进行压栈,当程序执行完成时,它的执行上下文就会被销毁,进行弹栈。
- 栈底永远是全局环境的执行上下文,栈顶永远是正在执行函数的执行上下文
- 只有浏览器关闭的时候全局执行上下文才会弹出
4、作用域
(1)作用域:规定变量和函数的可使用范围称作作用域
(2)作用域链:每个函数都有一个作用域链,包括所有的父级变量对象和当前函数自己的变量对象。当查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链。
29、算法
(1)冒泡排序
//左右对比,将最大值放置到数组最后面
function bubbleSort(arr) {
let len = arr.length;
if (!len) return arr;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let val = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = val;
}
}
}
return arr;
}
console.log(
bubbleSort([3, 5, 74, 64, 64, 3, 1, 8, 3, 49, 16, 161, 9, 4])
);
(2)快速排序
/**
* 1.取一个基准值
* 2.以基准为中间,将比基准小的放在左边数组
* 比基准大放在右边数组
* 3.以此类推,使用递归函数再将左右函数继续做此处理
*/
function quickSort(arr) {
let len = arr.length;
if (len <= 1) return arr;
let mid = Math.floor(len / 2);
//splice() 方法会改变原始数组。
let midData = arr.splice(mid, 1)[0];
let leftArr = [];
let rightArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < midData) {
leftArr.push(arr[i]);
} else {
rightArr.push(arr[i]);
}
}
return quickSort(leftArr).concat([midData], quickSort(rightArr));
}
var Arr = [3, 5, 74, 64, 64, 3, 1, 8, 3, 49, 16, 161, 9, 4];
console.log(Arr, "before");
var newArr = quickSort(Arr);
console.log(newArr, "after");
(3)插入排序
//插入排序
/**
* 从第二个元素开始排序,在交换位置之后,
* 需要在交换的当前位置往前对比,只要找到比
* 交换元素大的,数据就往后移,空出个位置给
* 交换元素
*/
function InsertionSort(arr) {
if (arr.length <= 1) return arr;
for (let i = 1; i < arr.length; i++) {
if (arr[i - 1] > arr[i]) {
let val = arr[i];
arr[i] = arr[i - 1];
let j = i - 1;
while (j >= 0 && arr[j] > val) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = val;
}
}
return arr;
}
var Arr = [3, 5, 74, 64, 64, 3, 1, 8, 3, 49, 16, 161, 9, 4];
console.log(InsertionSort(Arr));
(4)回文
//是否回文
/**
* 回文:内容正反读取都一样
*/
function isHuiWen(str) {
return str == str.split("").reverse().join("");
}
console.log(isHuiWen("mnm"));
(5)千分位分隔符
function numberThousands(number, thousandsSeperator = ",") {
return String(number).replace(
/(\d)(?=(\d\d\d)+(?!\d))/g,
"$1" + thousandsSeperator
);
}
console.log(numberThousands(123456789));//123,456,789
console.log(numberThousands(12345.6789));//12,345.6,789
(6)斐波那契数列
//斐波那契数列 f(n) = f(n-1)+f(n-2)
function Fibonacci(n, num1 = 1, num2 = 1) {
if (n <= 0) return 0;
if (n == 1) return num1;
if (n == 2) return num2;
return Fibonacci(n - 1, num2, num1 + num2);
}
console.log(Fibonacci(9));
//使用while方法
function Fibonacci(n, num1 = 1, num2 = 1) {
if (n <= 0) return 0;
if (n == 1) return num1;
if (n == 2) return num2;
let i = 3;
let sum = 0;
while (i <= n) {
sum = num1 + num2;
num1 = num2;
num2 = sum;
i++;
}
console.log(sum);
return sum;
}
console.log(Fibonacci(9));
(7)数组去重
//数组去重的方式
function unique(arr) {
if (arr.length <= 1) return arr;
let newArr = [];
arr.map((item) => {
//if (newArr.indexOf(item) == -1) newArr.push(item);
if (!newArr.includes(item)) newArr.push(item);
});
return newArr;
}
let arr = [1, 2, 1, 1, 1, 2, 3, 3, 3, 2];
console.log(unique(arr));
//方法二:
let newArr4 = arr.reduce(
(prev, curr) => (prev.includes(curr) ? prev : [...prev, curr]),
[]
);
console.log(newArr4);
(8)数组扁平化
function flatten(arr) {
return arr.reduce((result, item) => {
return result.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
30、Ref
(1)利用props传递给子组件执行的渲染函数,函数内部的组件定义的ref无法被生成
React -父组件获取子组件的值-以及方法
/**
* 在renderFooter()里定义的 <Popup.Form>组件,
* 加上ref后,page里的this.refs没有对应的数据
* */
//Page.js
renderFooter() {
console。log(this.refs); //undefined
return (
<div>
<Popup.Form ref={'test'} title={'选择审核人'}/>
</div>
);
}
//src\components\Page\Form.js
render() {
const spinning = this.isSpinning();
return <Content spinning={spinning} renderFooter={this.renderFooter.bind(this)}>
<div>123</div>
</Content>;
}
//src\components\Layout\Content.js
class PageContent extends react.Component {
static defaultProps = {
renderFooter(){
return null;
}
};
render(){
const footer = this.props.renderFooter();
return (
<Spin spinning={this.props.spinning||false}>
<div className={classnames("common-page",this.props.className)}>
{footer?(
<div className="page-action">
{footer}
</div>
):null}
</div>
</Spin>
)
}
}
解决方法:
//方法1:不通过多层props去渲染,直接在第一层子组件的render里渲染
render() {
const spinning = this.isSpinning();
return <Content spinning={spinning}>
<div style={{paddingTop:10}}>
{this.renderFooter}
</div>
</Content>;
}
//方法2:使用onRef
//page.js
renderFooter() {
return (
<div>
<Popup.Form title={'选择审核人'}onRef={(ref)=>this.popupChild=ref}/>
</div>
);
}
//Popup.Form组件
componentDidMount() {
/**
* Form组件使用Content包裹renderFooter,renderFooter的ref
* 无法绑定在page的refs上,改用onRef返回子组件实例
* */
if(this.props && this.props.onRef){
if(typeof this.props.onRef == 'function')this.props.onRef(this);
}
}
(2)$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。
访问子组件实例或子元素
(3)ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例(指向实例)
vue中的 ref 和 $refs
(4)this.refs打印出来是一个Proxy对象
31、vite
(1)vite和webpack的区别
Vite当前可用于生产吗,对比webpack有什么不足吗?
- webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。(先打包编译再启动服务器)
- 而vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。(先启动服务器,模块按需加载)
- 由于vite在启动的时候不需要打包,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度(注:是启动服务器快而不是编译快)非常快。当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。
- 当需要打包到生产环境时,vite使用传统的rollup(也可以自己手动安装webpack来)进行打包,因此,vite的主要优势在开发阶段。
32、数据结构
(1)(数据结构)十分钟搞定时间复杂度(算法的时间复杂度)
33、前端工程化