说一下生命周期
vue生命周期是指一个vue实例从创建到销毁的过程,通常在发送请求,清除定时器时都会用到。 vue生命周期分为八个阶段: beforecreated(创建前),created(创建后),beforeMounted(加载前),monted(加载后),beforeupdate(更新前),updated(更新后),beforedestroy(销毁前),destroied(销毁后)
说一下组件通信
6种方式
- props和$emit
父组件通过props向子组件传递数据,子组件通过$emit触发事件向父组件传递数据
- attrs和listeners
第一种方式的缺陷在于如果组件间存在多层嵌套关系,a的子组件是b,b的子组件是c,那么a该如何传递数据给c,如果还使用props就会很复杂,所以使用attrs和listeners a可以直接传递数据给c
- v-model
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,子组件可以通过$emit('input',val)直接更改v-model绑定的值
- provide和inject
父组件通过provide提供变量,子组件通过inject注入变量,不论子组件有多深,只要调用了inject,都可以使用provide中的数据,而不是局限于只能从当前父组件的props属性中获取数据,只要在父组件的生命周期内,不管多深的子组件都可以调用
- 中央事件总线eventBus
兄弟之间组件通信就使用中央事件总线eventBus,创建一个vue事件bus对象,使用bus.emit触发事件bus.on监听触发的事件
- 使用vuex
通常需要多个组件同时处理数据,就需要用到vuex状态管理工具,将公共数据单独抽离出来,然后其他组件就可以对公共数据进行读写操作
说一下vuex
vuex是vue中提供的状态管理工具,将公共数据单独抽离出来,其他组件可以对公共数据进行一系列操作
- state()存储基本数据类型
- getters()计算属性
- mutation()通过$store.commit方法更改state中的数据
- action()通过 dispatch提交mutation,更改state中的数据
说一下双向绑定的原理
错误: v-bind:绑定data中的数据 oninput事件:绑定input事件
1. v-bind绑定响应式数据 2. 触发oninput事件并传递数据
知道哪些vue指令
v-html:插入一段html片段 相当于innerhtml v-text:会覆盖原先的字符串,插入文字 v-if:配合v-else和v-else-if使用控制显示隐藏,频繁显示隐藏时使用 v-show:控制绑定元素的显示隐藏,相当于display v-model:双向绑定 v-bind:给属性绑定值 v-on:@ 绑定事件 v-for:用来遍历数组对象,字符串
说一下自定义指令
自定义指令:自己定义的指令,可以封装一些dom操作,扩展额外功能
一.自定义指令的使用
1) 可以使用Vue.directive( dir_name , {} ) 来定义全局自定义指令
2) 也可以使用 directives{ dir_name : {} } 来定义局部自定义指令
二.构造函数 1) bind
只调用一次, 当指令第一次绑定在元素上时.用来做一次性初始化操作.
2) inserted
当绑定元素已插入到父节点时调用.也就是说 必定存在父节点.但是它及它的父节点未必存在文档中.
3) update
在包含该组件的VNode更新后调用该函数.可能在其子级更新前调用.指令的值可能已更改,可能未更改.最好通过判断新旧值来过滤掉不必要的操作.
4) componentUpdated
在包含该组件的VNode 以及 其子节点的VNodes已更新之后 调用.
5) unbind
指定从元素上解绑时,调用一次.局部的自定义指令,只能在当前组件的模板中去用
三.钩子函数的参数
1)el
绑定了该指令的元素.可以直接操作DOM元素.
2)binding ( 包含以下属性 ) name,刨除’v-'前缀的指令名
3)value
传递给指令的值. e.g. v-s="1+1", value就是2
4)oldValue
旧值 , 只在 钩子函数 update 以及 componentUpdated 中可用. 无论值是否改变都可用
5)expression
表达式的字符串形式.
6)arg
传递给指令的参数 . e.g. v-s:foo , arg就是 foo
7)modifiers
包含修饰符的对象.e.g. v-s.a.b 意味着 modifiers 为 {a : true , b:true}
8)vnode
vue编译器提供的虚拟节点对象. 详见 VNode API
9)oldVnode
之前的虚拟节点对象. 只在钩子函数 update 和 componentUpdated 中可用.
说一下路由传参
-
路由是什么? 路由传参是指在前端路由中通过URL传递参数的方式,用于在不同页面之间传递数据和状态信息
-
路由跳转的两种方式?
①声明式导航:通过router-link实现(必须要有to属性),实现路由跳转
②编程式导航:利用的是组件实例的router.replace方法,实现路由的跳转,同时也可在里面书写一些其他业务,比如路由传参 -
路由传参的三种写法:
params传参:属于路径当中的一部分,在配置路由的时候需要占位
query传参:不属于路径当中的一部分,比如/home?k=v&k=v,不需要占位
props传参:路由组件传参(有三种方式)
说一下防抖节流
防抖:一定时间内(定时器延时间),用户频繁地去触发一个事件,只执行最后一次的触发--比如输入框的input事件,每输入一个文字就会触发一次,这样频繁的触发会消耗性能,使用防抖之后,只会在你输入完成后才会触发
节流:控制触发事件的次数,控制多久才能触发一次,分为首节流和尾节流 节流可以理解为游戏中的技能,释放一个技能会有技能cd,等cd事件结束才可以再次释放技能 首节流:使用时间戳实现,触发事件之后能立即执行 尾节流:使用定时器实现,触发事件后要经过延时才会执行
说一下this
this指向调用者,谁调用的this就指向谁, 箭头函数中this指向windows
怎么阻止默认事件
prevent.default()
怎么阻止事件冒泡
1. 使用 event.stopPropagation() 方法:
2. Vue 提供了一种更简洁的方式来阻止事件冒泡,那就是使用 .stop 修饰符。(@click.stop)
数组常用的方法
带~符号的方法会改变原数组
- array.push() :表示向数组末尾进行追加~
- array.pop() :从数组的末尾开始删除,并且返回这个元素~
- array.length():获取当前数组的长度
- array.include():用来判断一个数组是否包含一个指定的值
- array.slice():用来截取某一个片段 浅拷贝
- array.splice() :删除替换插入~
- array.filter() :过滤
- array.unshift():表示向数组最前面进行追加~
- array.shift():删除数组的第一个元素,并返回这个数组~
- array.sort():排序~
- array.reverse():可以将数组进行翻转~
- array.concat():做合并,拼接
- array.join()
- array.map():表示映射,对数组中的每个元素进行处理,返回新的数组,数组中的元素为原始数组元素调用函数处理后的值
- array.forEach():对数组进行遍历循环,这个方法没有返回值
- array.isarray():判断类型是否为数组
- array.every():根据一个条件判断当前数组是不是都满足这个条件
- array.reduce():为数组提供一个累加器,合并为一个值
- array.find():找某个符合条件的数据
- array.findIndex():找某一个符合条件的数据的索引
- array.some();根据一个条件判断当前数组是不是有一个满足这个条件
数组去重知道哪些方法
-
for循环+findIndex
主要利用
findIndex的特性,查找元素找不到就返回-1, 接下来就需要判断,如果是-1,说明没找到,就往新数组里面添加元素。
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法2: for + indexof
function newArrFn (arr) {
let newArr = []
for(let i = 0;i<arr.length;i++){
newArr.indexOf(arr[i]) === -1 ? newArr.push(arr[i]) : newArr
};
return newArr
}
console.log(newArrFn(arr));
-
sort排序
首先利用
sort 方法进行排序。进行循环,如果原数组的第 i 项和新数组的i - 1项不一致,就push进去。
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法3: for + sort
function newArrFn (arr) {
arr = arr.sort()
let newArr = []
for(let i = 0;i<arr.length;i++){
arr[i] === arr[i-1] ? newArr : newArr.push(arr[i])
};
return newArr
}
console.log(newArrFn(arr));
-
Set
ES6中新增了数据类型Set,Set的一个最大的特点就是数据不重复,Set函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重。
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法4: set
function newArrFn (arr) {
// .new Set方法,返回是一个类数组,需要结合 ...运算符,转成真实数组
return ([...new Set(arr)])
}
console.log(newArrFn(arr));
- filter + indexOf indexOf,可以检测某一个元素在数组中出现的位置,找到返回该元素的下标,没找到返回 -1
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法6 :filter + findIndex
function newArrFn (arr) {
// 利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,
// 如果相等,说明数组中没有重复的
return Array.prototype.filter.call(arr, function (item, index) {
return arr.indexOf(item) === index
})
}
console.log(newArrFn(arr));
-
includes
利用
includes检查新数组是否包含原数组的每一项。 如果不包含,就push进去
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法7 :for + includes
function newArrFn (arr) {
// 利用includes 检查新数组是否包含原数组的每一项
// 如果不包含,就push进去
let newArr = []
for(let i = 0;i<arr.length;i++){
newArr.includes(arr[i]) ? newArr: newArr.push(arr[i])
};
return newArr
}
console.log(newArrFn(arr));
-
Map
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法11 :Map
function newArrFn (arr) {
let newArr = []
let map = new Map()
for(let i = 0;i<arr.length;i++){
// 如果 map里面不包含,就设置进去
if (!map.has(arr[i])) {
map.set(arr[i], true)
newArr.push(arr[i])
}
};
return newArr
}
console.log(newArrFn(arr));
- reduce
var arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
// 数组去重:
// 方法12 :reduce
function newArrFn (arr) {
let newArr = []
return arr.reduce((prev, next,index, arr) => {
// 如果包含,就返回原数据,不包含,就把新数据追加进去
return newArr.includes(next) ? newArr : newArr.push(next)
}, 0)
}
console.log(newArrFn(arr));
字符串操作方法
查找
- find():检测某个子串是否包含在这个字符串中,如果在返回这个子串 开始的位置下标,否则返回-1
- index():检测某个子串是否在这个字符串中,如果在,返回这个子串开始的位置下标,否则就报错
- count():返回某个子串在字符串中出现的次数
修改
- replace():替换
- split():按照指定字符分割字符串
判断(返回的结果都是布尔类型)
- startwith():检查字符串是否以指定子串开头
- ends with():检查字符串是否以指定子串结尾
- isalpha():如果字符串至少有一个字符,并且所有字符都是字母true
- isdigit():如果字符串只包含数字就返回true
怎么判断一个数是不是素数,逻辑怎么写?
// 判断一个数是不是素数(质数)。(只能被1和自身整除的数,或者说:除了1和它自身以外,再没有其它数能整除它)
//方法一:
function test(){
//1、输入
var num = parseInt(document.getElementById("num").value);//9
//2、业务逻辑
for(var i=2;i<=num-1;i++){//i=7 num=7
if(num%i==0){
break;
}
}
if(i>num-1){
alert(num+"是素数");
}else{
alert(num+"是合数");
}
}
//方法二:
function test(){
//1、输入
var num = parseInt(document.getElementById("num").value);//9
//2、业务逻辑
var isSu=true;//isSu:表示是否为素数;假设是素数;
for(var i=2;i<=num-1;i++){
if(num%i==0){
isSu = false;
break;
}
}
if(isSu==true){
alert(num+"是素数");
}else{
alert(num+"是合数");
}
}
//方法三:
function test(){
//1、输入
var num = parseInt(document.getElementById("num").value);//9
//2、业务逻辑
var count=0;//记录整除的次数
for(var i=2;i<=num-1;i++){//
if(num%i==0){
count++;
break;
}
}
if(count==0){
//3、输出
alert(num+"是素数");
}else{
alert(num+"是合数");
}
}
怎么清除浮动
页面布局当中,在无法确定子元素的高度时,我们无法给父级标签一个固定的高度,我们想要的是通过子元素的高度来确定父元素的高度,所以当子元素设置了浮动的属性之后,父元素的高度没有进行设置,这样就会导致父元素的高度塌陷(原本的height被重置为0),这就涉及到了浮动的重要性
- 额外标签法:该方法就是在浮动元素末尾添加一个空的标签,在给空标签添加一个清除浮动的样式
<div class="app">
<div class="app1">手机</div>
<div class="app2">电脑</div>
<div class="clear" style="clear: both;"></div> <!-- 添加一个空的标签 -->
</div>
- 给父元素添加overflow:hidden
html
<div class="app">
<div class="app1">手机</div>
<div class="app2">电脑</div>
</div>
css
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
.app{
overflow: hidden; /* 父元素添加 overflow 属性清除浮动 */
width: 500px;
margin: 0 auto;
border: 1px solid #409EFF;
}
.app1{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: skyblue;
}
.app2{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: pink;
}
</style>
- :after伪元素法
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
/* --------以下两行样式代码为固定写法-------- */
.clearfix:after{
content: '';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix{
/* 为 IE6、IE7浏览器设置的清除浮动 */
*zoom: 1;
}
/* --------以上两行样式代码为固定写法--------- */
.app{
width: 500px;
margin: 0 auto;
border: 1px solid #409EFF;
}
.app1{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: skyblue;
}
.app2{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: pink;
}
</style>
- :after和:before双伪元素清除浮动
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
/* --------以下两行样式代码为固定写法-------- */
.clearfix:after,.clearfix:before{
content: '';
display: table;
}
.clearfix:after{
clear: both;
}
.clearfix{
/* 为 IE6、IE7浏览器设置的清除浮动 */
*zoom: 1;
}
/* --------以上两行样式代码为固定写法--------- */
.app{
width: 500px;
margin: 0 auto;
border: 1px solid #409EFF;
}
.app1{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: skyblue;
}
.app2{
float: left; /* 子元素向左浮动 */
width: 200px;
height: 100px;
background-color: pink;
}
</style>
后面都是固定写法,记住即可
div怎么垂直居中
- 使用外边距属性来使div水平垂直居中
- 绝对定位:只要让容器开启绝对定位,并且left,right,top,bottom全为0,margin:auto就能实现div水平居中了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>绝对定位</title>
<style>
*{
margin: 0;
padding: 0;
}
/* 父容器 */
.container{
height: 700px;
position: relative;
background-color: black;
}
/* 子容器 */
.son{
width: 300px;
height: 300px;
background-color: white;
position:absolute;
/* 水平垂直居中 */
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<div class="container">
<div class="son"></div>
</div>
</body>
</html>
- 子元素绝对定位,父元素相对定位---给父容器开启相对定位,子元素开启绝对定位。水平据中:left:50%;margin-left:-150px;垂直居中:top:50%;margin-top:-150px
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子绝父相</title>
<style>
*{
margin: 0;
padding: 0;
}
/* 父容器 */
.container{
height: 700px;
background-color: black;
/* 父容器开启相对定位*/
position: relative;
}
/* 子容器 */
.son{
width: 300px;
height: 300px;
background-color: white;
/* 子容器开启绝对定位*/
position:absolute;
/* 水平垂直居中 */
top: 50%;
margin-top: -150px;
left: 50%;
margin-left: -150px;
}
</style>
</head>
<body>
<div class="container">
<div class="son"></div>
</div>
</body>
</html>
- flex布局:给父容器开启flex布局,父容器就变成flex容器了,子容器就变成flex项目了,利用flex布局控制项目水平方向和垂直方向排列的属性,使div垂直水平据中
justify- content:center;水平据中
align-items:center;垂直居中
怎么画0.5px的线
- box-shadow :box-shadow允许小数点,该属性可设置的值包括阴影的x轴偏移量,模糊偏移量,y轴偏移量,模糊半径,扩散半径和颜色,所以我们可以设置他的扩散半径来实现0.5px的线
- transform:缩放实现的思路,transform:scaleY(0.5);
- 线性渐变 linear-grandient background:linear-grandient(0deg,#fff,#000);边框线性渐变的答案,同样设置任意大小的边框,通过渐变属性改变一部分边框的颜色效果,比如将一部分边框融入背景,这样就能得到想要的效果
说一下盒模型
- 盒模型是css布局的基石,规定了网页元素如何显示以及元素之间相互关系,css定义所有的元素都可以拥有像盒子一样的外形和平面空间,即都包含内容区,内填充,边框,外边距,这就是盒模型
盒模型的组成=content+padding+border+margin
- 内填充:padding,在设定页面中一个元素内容到元素的边缘之间的距离,也称补白,padding不可以写负值。padding的作用:改变元素在父元素的位置,改变内容在容器中的位置,padding会把盒子撑大,如果想让盒子保持原有的大小:在宽高的值基础上减掉
padding值的设定:先上下后左右,一个值表示上下,两个值表示一个上下,一个左右,三个值:上 左右 下,四个值:上 右 下 左;还可以单独设定单独方向的padding,padding-top,padding-bottom,padding-left,padding-right
-
外边距margin,margin可以写负值!作用:控制元素跟元素之间的间距,margin在元素外围,不会撑大元素的大小。说明:可单独设置某一方向边界。margin:0 auto 元素水平居中
-
盒模型:标准盒模型中,width(height)=content;ie盒子模型中(怪异盒模型)中,width(height)= border+padding+content;box-sizing:border-box(怪异盒模型);box-sizing:contnt-box(标准盒模型)
两个异步请求数据操作怎么合并
- 使用promiseAll().then(()=>{}).catch(()=>{});并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.all( [p1,p2,p3] ) .then ( (result) => {consoleog (result)
})
- Promise.race().then().catch();并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.race ( [p1,p2,p3] ).then ( (result)=>{
console. log (result)
})
v-model是谁的语法糖
语法糖:对语言功能并没有语法,但是更方便程序员使用,简而言之,语法糖让程序更加简洁,有更高的可读性 相当于:<mycom ;value="xxx" @input="新值=>xxx=新值"/>
总结:v-model做两件事:
- 向自组件传来一个名为value的属性
- 在子组件监听input事件,这个事件的回调中修改value所绑定的值
一个值实现两个功能,子传父(input事件),父传子(value属性)
query和params的区别
vue怎么获取dom
- 使用dom API直接找元素
这种方法足够简单直观,vue组件在patch阶段结束时会把this.el的querySelector,querySelectorAll等方法获取匹配元素
- refs
使用组件实例的$refs即可拿到组件上ref属性对应的元素。如果ref属性加在一个组件上,那么拿到的是这个组件的实例,否则拿到的就是dom元素了。值得注意的是包含v-for循环模版指令的情况,其循环元素和子元素上ref属性对应的都是一个数组(就算动态生成ref,也是数组)
- 使用自定义指令
vue提供了自定义指令,el就是dom元素的引用
flex布局怎么把元素搞到右上角
display:flex justify-content:flex-end 设置水平线上的元素靠右 justify-content:center 设置水平线上的元素居中 元素默认靠左,第一行第一个 align-items:center 元素垂直居中 flex-end垂直向下对齐 复杂的在csdn收藏中看
promise有几种状态,会不会改变
三种状态,同一时间只能存在一种状态,且状态一旦改变就不能再变,promise是一个构造函数,promise对象代表一项只有两种可能结果的任务,他还持有多个回调,出现不同结果时发出不同相应回调函数
- pending(待处理)
初始化之后状态就是待处理状态pending
- fulfilled(成功)
当调用resolve时,即为成功,状态由pending=>fulfilled
- rejected(失败)
当调用reject 时,即为失败,状态pending=>rejected
优点:
- promise分离了一部数据获取和业务逻辑,有利于代码复用
- 可以采用链式写法
- 一旦promise的值确定为fulfilled或者rejected之后,不可改变
缺点:
- 代码冗余,语义不清
async和await解决什么问题?
async和await是一种建立在promise之上的编写异步或阻塞代码的新方法,被普遍认为是js异步操作的最终且最优雅的解决方案。相对于promise和回调,他的可持续性和简洁度都更高。一直.then()也不好看
所以从语义上就很好理解async用于声明一个function是异步的,而await用于等待一个异步方法执行完成,一个函数如果加上async,那么函数返回的是一个promise对象,如果在async函数中追额return一个量,async会把这个量通过promise.resolve()封装成promise对象返回
let和const区别
相同点:
- let只在声明所在的块级作用域内有效
- 没有变量提升,同时存在暂时性死区,只能在声明的位置后面使用
- 不可以重复声明
不同点:
- let声明的变量可以改变,值和类型都可以改变;const声明的常量不可以改变,这意味着,const一旦声明,就必须立即初始化,不能以后再赋值
let和var比较是比较声明问题,let和const比较是比较值的修改问题
const定义对象里面的属性能不能改?
const定义的对象属性可以修改,但是const定义的基本数据类型string,number等,定义后不可修改,如果修改会报错。
const定义中的不变指的是指向对象的指针不变,因为修改对象中的属性并不会让指向对象的指针发生改变,所以可以改变const定义对象的属性。
常见状态码
当我们访问一个网页时,浏览器会向网页所在服务器发出请求,当服务器收到请求后,就会解析请求并作出响应,同时服务器会返回一个包含http状态码的信息头用以响应浏览器的请求。但是这个过程并不百分百成功,并且情况也很复杂,所以状态码就起到了至关重要的作用。 状态码共分为五种类型:
- 1**:信息,服务器收到请求,需要请求者继续执行操作
- 2**:成功,操作被成功接受并处理
- 3**:重定向,需要进一步的操作以完成请求
- 4**:客户端错误,请求包含语法错误或者无法完成请求
- 5**:服务器错误,服务器错误,服务器在处理请求的过程中发生了错误
对同步和异步的理解
同步:同步是指一个进程在执行某个请求时,如果该请求需要一段时间才能返回信息,那么这个进程会一直等待下去,知道收到返回信息才会继续执行下去
异步:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态,当有信息返回的时候会通知进程进行处理,这样就提高了执行的效率,即异步是我们发出的一个请求,该请求会在后台自动发出并获取数据,然后对数据进行处理,在此过程中,我们可以继续做其他操作,不管他怎么发送请求,不关心她怎么处理数据。
- 为什么要在js中使用异步
由于js是单线程的,自己能在js引擎的主线程上运行的,所以js代码只能一行一行执行,不能在同一时间执行多个js代码任务,这就导致如果有一段耗时较长的计算,或者是一个ajax请求等io操作,如果没有一部的存在,就会出现用户长时间等待,并且由于当前任务还未完成,所以这时候其他操作都会没有响应
- 为什么js不设计成多线程的?
这主要和js的历史有关,js最开始只是为了处理一些表单验证和dom操作而被创造出来的,所以主要为了语言的轻量和简单采用了单线程的模式,多线程相比于单线程要复杂很多,比如多线程要处理线程间资源共享的问题,还要解决状态同步等问题。如果js是多线程的话,当你要执行往div中插入一个dom的操作的同时,另一个线程执行了删除这个div操作,这个时候就会出现很多的问题,我们还需要为此增加解锁机制等
- 常见的异步模式有哪些呢?
回调函数,事件监听,发布订阅模式(观察者模式),promise
js是如何实现异步操作呢?
就是js的事件循环机制
什么是js事件循环机制?
当js解析执行时,会被引擎分为两类任务,同步任务和异步任务,对于同步任务来说,会被推倒执行栈按顺序去执行这些任务,对于异步任务来说,当其可以执行时,会被放到一个任务队列中等待js引擎去执行。当执行栈中所有的同步任务完成后,js引擎才会去任务队列中查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又回去任务队列中查看是否有已经可以执行的任务。这种检查的机制就叫做事件循环
常见的宏任务,微任务?
对于任务队列,其实有更细的分类,其被分为微任务队列和宏任务队列
宏任务:setTimeout,setInterval等,会被放在红任务队列中
微任务:promise的then,Mutation Observer等会被放在微任务队列中
EventLoop的执行顺序是:首先执行执行栈里的任务,执行栈清空后,检查微任务队列,将可执行的微任务全部执行。取宏任务队列中的一项执行。回到第二步。注意:微任务队列每次全部执行,红任务队列中每次只取一项执行。
怎么判断两个数组相等?
通过把数组转成字符串的形势判断 arr.toString() ===arr2.toString()
es6遍历数组的方法?
- for in :以任意字段遍历一个对象的可枚举属性,遍历数据组时,key为下标字符串;遍历对象时,key为对象字段名
for in缺点:
- 迭代顺序依赖于执行环境,不一定保证顺序
- 不仅会遍历当前对象,还包括愿原型链上的可枚举属性
- 没有break中断
- 不适合遍历数组,主要应用为对象
- for of
ES6新引入的语法,在可迭代的对象上(包括Array,Map,Set,String,TypedArray,arguments对象,nodeList对象)创建一个迭代循环,调用自定义迭代勾子,并为并为每个不同属性的值执行语句
let arr = [{age: 1}, {age: 5}, {age: 100}, {age: 34}]
for(let {age} of arr) {
if (age > 10) {
break // for of 允许中断
}
console.log(age)
}
// 打印
// 1
// 5
for of优点:
- 有和for in一样的简介语法,但没有他的缺点
- 保证顺序且不会仅仅遍历当前的对象
- 可以与break,continue,return配合
- forEach提供回调函数,不能使用break语句中跳出循环,也不能使用return语句从闭包函数中返回
- map :map可以改变当前循环的值,返回一个新的被改变过值之后的数组,需要return,一般用来处理需要修改某一个数组的值
- filter:filter方法有返回值,返回值是一个新的数组,过滤筛选数组
- some和every:some返回布尔值,只要找到一项为真值,即返回true,只要找到第一个满足条件的元素,就终止循环,不再继续查找;every只要有一项为假,就返回为false,即使找到了符合的元素也会继续查找,every不会对空数组进行检测
- reduce和findIndex(返回第一个符合条件的)
- 基础的for循环
前端怎么给数据加密?
- Basse64加密:Base64是一种用来将二进制数据编码可读文本形式的编码规范。 调用window.btoa()方法进行加密,调用window.atob()方法进行解密
- MD5是一种常用的密码散列函数,通常用于对一段数据产生唯一的“指纹”,以便于验证数据的完整性和一致性。使用md5()方法进行MD5加密操作。
两个html文件怎么传值?
1、url携带参数
优点:取值方便,可以跨域,利于页面分享,没有环境限制。
缺点:url携带参数值的长度有限制。
2、cookie方式
优点:可以在同源内的的任意网页中访问,存储数据的周期可以自由设置。
缺点:有长度限制。
3、设置窗口之间的父子关联关系
优点:取值方便.只要window.opener指向父窗口,就可以访问所有对象.不仅可以访问值,还可以访问父窗口的方法.值长度无限制。
缺点:两窗口要存在着关系.就是利用window.open打开的窗口。不能跨域。
4、h5技术,window.localStorage存储数据
优点:储存空间大,有5M存储空间。
缺点:不是所有浏览器都支持。
个人倾向第一种方式,主要是自己做的网页可以分享,在任何的地方都可以打开,其他的方式都有环境的要求。如果是做大型项目,架构是实现客户端与服务端的分离,建议还是引入客户端框架,框架实现了路由、参数的传递、以及安全问题,可以大大的提高开发效率。