前端面试常问面试题

411 阅读59分钟

想到了就增加 可以评论区说

Vue

Vue的优势?

Vue是一款轻量级框架、简单易学。

Vue的核心思想?

vue的核心只关注视图层。 核心思想:

  • 数据驱动(视图的内容随着数据的改变而改变)
  • 组件化(可以增加代码的复用性,可维护性,可测试性,提高开发效率,方便重复使用,体现了高内聚低耦合)

mvvm和mvc的区别?

区别: 总的来说:mvvm和mvc都是用来渲染页面的一种方式,不过mvvm是双向数据流就是数据的变化从视图层到模型层,再从模型层流回到视图层,而mvc包括三层结构就是视图,数据,控制层(中间桥梁),通过控制层来把数据传到视图层,更新视图,再通过控制层把数据的变化传给视图,实现分层开发,结构更清晰

两者的区别如下: 主要使用场景:

  1. mvc适用于需要大量操作dom的情况,渲染起来性能消耗较大,通过控制层来实现数据和页面的联动效果;
  2. mvvm主要用于vue项目的开发,减少dom的操作,数据和视图的数据双向传递的情况

data为什么是一个函数?

如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据)

Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

v-if和v-for哪个优先级更高?

v-for优先于v-if (解析如下)

  • 第一种<p v-for="child in childer" v-if="isFolder">{{child.tltle}}</p> 如果v-forv-if二者同时使用。第一种每次渲染都会执行先循环后判断。无论循环多少次都无法避免。(不推荐,浪费性能)
  • 第二种<template v-if="isFolder"><p v-for="child in childer">{{child.tltle}}</p></template>第二种情况就是在外层嵌套template,然后判读if条件,条件成立则渲染for循环,否则执行空函数。

你了解哪些Vue性能优化方法?

这里主要探讨Vue代码层面的优化

  • 路由懒加载

  • keep-alive缓存页面

  • 使用v-show复用DOM

  • v-for 遍历避免同时使用 v-if

  • 长列表性能优化 如果列表是纯粹的数据展示,不会有任何改变,就不需要做响应化 如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容

  • 事件的销毁 Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。

  • 图片懒加载 对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域

内的图片先不做加载, 等到滚动到可视区域后再去加载

  • 第三方插件按需引入
  • 无状态的组件标记为函数式组件
  • 子组件分割
  • 变量本地化

watch和computer的区别?

计算属性是有一个缓存的,即即便你重新渲染组件,但是计算属性的值没有发生改变时,就不会去执行

  这个改变基于计算属性中的被计算值最后是否发生

  watch是观察某一个属性的变化,重新计算属性值。computed是通过所依赖的属性的变化重新计算属性值。
大部分情况下watch和computed几乎没有差别。但如果要在数据变化的同时进行异步操作或者是比较大的开销,那么watch为最佳选择。

vue常用指令有那些?

常用的Vue指令

vue中v-for指令循环遍历中key属性的作用?

Key 属性的作用是在数据层和视图层之间建立一一对应关系, 方便后期对页面进行局部更新. 如果某一条数据发生改变, 只更新当前数据对应的DOM 元素。

v-show和v-if 在隐藏一个元素的时候有什么不同, 应该如何来选择?

v-show 是通过css 的方式来隐藏元素, 而v-if 是根据条件是否成立决定是否要创建元素. 如果某个元素需要频繁切换显示状态的话, 建议是使用v-show, 因为频繁创建销毁DOM 需要性能开销。

v-show和v-if指令的共同点和不同点?

相同点:

  • v-show和v-if都能控制元素的显示和隐藏。 不同点:
  • 实现本质方法不同v-show本质就是通过设置css中的display设置为none,控制隐藏v-if是动态的向DOM树内添加或者删除DOM元素
  • 编译的区别v-show其实就是在控制cssv-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
  • 编译的条件v-show都会编译,初始值为false,只是将display设为none,但它也编译了v-if初始值为false,就不会编译了
  • 性能比较v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一。 注意点:
  • 因为v-show实际是操作display:""或者none,当css本身有display:none时,v-show无法让显示 总结(适用场景):
  • 如果要频繁切换某节点时,使用v-show(无论true或者false初始都会进行渲染,此后通过css来控制显示隐藏,因此切换开销比较小,初始开销较大),如果不需要频繁切换某节点时,使用v-if(因为懒加载,初始为false时,不会渲染, 但是因为它是通过添加和删除dom元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)

指令v-el的作用是什么?

提供一个在页面上已存在的DOM元素作为Vue实例的挂载目标.可以是CSS选择器,也可以是一个HTMLElement实例

Vue中如何解决插值表达式闪烁问题?

使用v-html 或v-text 替代插值表达式; 使用v-clack 解决插值表达式闪烁, 第一步:声明属性选择器[v-clack]{display:none} 第二步:在插值表达式所在标签添加属性v-clack

Vue数据绑定的几种方式?

  • 单向绑定双大括号{{}}html内字符串绑定
  • v-bind绑定html属性绑定
  • 双向绑定v-model
  • 一次性绑定v-once依赖于v-model

vue生命周期?

对于vue生命周期的理解

第一次加载页面会触发哪几个钩子函数?

当页面第一次页面加载时会触发 beforeCreate,created,beforeMount,mounted 这几个钩子函数

异步请求适合在哪个生命周期调用?

官方实例的异步请求是在 mounted 生命周期中调用的,而实际上也可以在 created 生命周期中调用

DOM渲染在那个生命周期阶段内完成

DOM渲染在 mounted 周期中就已经完成只。执行一次,运行阶段可以执行多次

created和mount请求数据的区别?

前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态

说一说vuex使用及其理解?

  • vue中状态管理(登陆验证,购物车,播放器等) vuex 数据流程

image.png

1. vuex 介绍
Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更 改 State 中的数据时,必须通过 Mutation 提交修改信息, Mutation 同时 提供了订阅者模式供外部插件调用获取 State 数据的更新。 而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作 需要走 Action ,但 Action 也是无法直接修改 State 的,还是需要通过 Mutation 来修改State的数据。最后,根据 State 的变化,渲染到视图 上。
2. vuex 中核心概念

  • state : vuex 的唯一数据源,如果获取多个 state ,可以使用 ...mapState 。
  • getter : 可以将 getter 理解为计算属性, getter 的返回值根据他的依赖缓存起来,依赖发生变化才会被重新计算。
  • mutation :更改 state 中唯一的方法是提交 mutation 都有一个字符串和一个回调函数。回调函数就是使劲进行状态修改的地方。并且会接收 state 作为第一个参数 payload 为第二个参数, payload 为自定义函数, mutation 必须是同步函数。
  • action : action 类似 mutation 都是修改状态,不同之处,action 提交的 mutation 不是直接修改状态action 可以包含异步操作,而 mutation 不行action 中的回调函数第一个参数是 context ,是一个与 store 实例具有相同属性的方法的对象action 通过 store.dispatch 触发, mutation 通过 store.commit 提交
  • module :由于是使用单一状态树,应用的所有状态集中到比较大的对象,当应用变得非常复杂是, store 对象就有可能变得相当臃肿。为了解决以上问题, vuex 允许我们将 store分割成模块,每个模块拥有自己的 state,mutation,action,getter ,甚至是嵌套子模块从上至下进行同样方式分割。 3. vuex 中数据存储localStorage
    vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在 vuex 里数据改变的时候把数据拷贝一份保存到 localStorage 里面,刷新之后,如果localStorage 里有保存的数据,取出来再替换 store 里的 state 。 注意:vuex 里保存的状态,都是数组,而localStorage 只支持字符串。

总结:

  • 首先说明Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所
  • 有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • vuex核心概念 重点同步异步实现 action mutation
  • vuex中做数据存储 --------- local storage
  • 如何选用vuex

computed和watch有什么区别?

computed:

  1. computed 是计算属性,也就是计算值,它更多用于计算值的场景
  2. computed 具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算
  3. computed 适用于计算比较消耗性能的计算场景 watch:
  4. 更多的是「观察」的作用,类似于某些数据的监听回调,用于观察 props $emit 或者本组件的值,当数据变化时来执行回调进行后续操作
  5. 无缓存性,⻚面重新渲染时值不变化也会执行 小结:
  6. 当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
  7. 如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化

axios 封装 API接口

axios 封装 API接口

vue-router路由有哪几种路由?

  • Hash:  使用URL的hash值来作为路由。支持所有浏览器。
  • History:   以来HTML5 History API 和服务器配置。参考官网中HTML5 History模式
  • Abstract: 支持所有javascript运行模式。如果发现没有浏览器的API,路由会自动强制进入这个模式。

vue双向绑定原理?

  1. 实现一个监听者Oberver来劫持并监听所有的属性,一旦有属性发生变化就通知订阅者
  2. 实现一个订阅者watcher来接受属性变化的通知并执行相应的方法,从而更新视图
  3. 实现一个解析器compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相对应的订阅者

Vue 实现路由跳转的方式?

Vue路由跳转方式

Vue 如何清除浏览器缓存?

  • 在HTTP协议中,只有后端返回 expires 或 Cache-Control:max-age=XXX, 前端才缓存。但在浏览器中,默认会对 html css js 等静态文件、以及重定向进行缓存,
  • 最常用的方法就是,在打包的时候给每个打包文件加上hash 值,一般是在文件后面加上时间戳或者随机数
  • 在脚本加载时加入一个时间戳,修改 webpack.prod.conf.js 文件。(未使用过该方法,需要实践)

讲讲全局守卫?

全局守卫分为全局前置守卫,全局解析守卫。全局后置钩子三个。

  • 全局前置守卫 当一个导航触发时,全局前置守卫按照创建的顺序调用。守卫可以是异步解析执行,此时,导航在所有守卫执行完之前一直处于挂起状态。全局前置守卫使用router.beforeEach注册。

在使用全局前置守卫的时候,一定要确保next函数的正确调用。

  • 全局解析守卫 全局解析守卫使用router.beforeResolve注册。它和全局前置守卫类似,区别在于,在导航被确认之前,在所有组件内守卫和异步路由组件被解析之后,全局解析守卫才被调用。

  • 全局后置钩子 全局后置钩子使用router.afterEach注册,在导航确认之后调用。

与守卫不同的是,全局后置钩子不接受next函数,也不会改变导航。

vue的插槽怎么使用?

1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。 2. 分类:默认插槽、具名插槽、作用域插槽

vue怎么实现页面跳转?

一、router-link标签跳转

在html标签内使用router-link跳转,相应于超链接标签,使用方式如下:

<router-link to="/">xxx</router-link>

1

但是a标签和router-link还有一点区别的:

  • a标签

W3C中的解释:a标签定义超链接,用于从一个页面链接到另一个页面

个人理解:通过a标签进行跳转,页面会被重新渲染,即相当于重新打开一个新的网页,会有视觉上的“闪烁”(如果是本地的项目可能看不出来)

  • router-link

通过router-link进行跳转不会跳转到新的页面,也不会重新渲染,它会选择路由所指的组件进行渲染,避免了重复渲染页面,只更新变化的部分,减少DOM性能消耗

二、代码内部跳转
实际项目中,很多时候都是通过在JS代码内部进行导航的跳转,

三、其他常用方法\

  • //  后退一步记录,等同于 history.back() this.$router.go(-1)
  • // 在浏览器记录中前进一步,等同于 history.forward() this.$router.go(1)

组件间的传值?

父子组件传值比较简单,父给子传值使用props,子给父传值使用$emit;

兄弟及其他没有关系的组件传值使用eventBus(事件总线),它是一个通讯桥梁和调度中心,组件A传值给eventBus,eventBus再传值给组件B。

如果项目比较大,安全考虑还是使用Vuex来处理,Vuex是一种状态管理工具,就是vue当中的状态管理模式。

vue的代码优化?

1、设置productionSourceMap为false

如果不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。

设置为false打包时候不会出现.map文件

2、代码压缩

3、图片资源压缩

3、 开启gzip压缩

封装过组件?

● 首先,使用Vue.extend()创建一个组件

● 然后,使用Vue.component()方法注册组件

● 接着,如果子组件需要数据,可以在props中接受定义

● 最后,子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法

vue自定义组件和自定义指令?

自定义组件:

每个组件都有属于自己的模板,js和样式。如果将一个页面比喻成一间房子的话,组件就是房子里的客厅、卧室、厨房、厕所。如果把厨房单独拿出来的话,组件又可以是刀、油烟机...等等。就是说页面是由组件构成的,而组件也可以是组件构成的。这样就可以非常的灵活,耦合性也非常的低。

什么是自定义指令
我们看到的v-开头的行内属性,都是指令,不同的指令可以完成或实现不同的功能,对普通 DOM元素进行底层操作,这时候就会用到自定义指令。除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。

vue 单页应用与多页应用的区别?

首先多页开发,肯定是一个页面就是一个单独文件,每个文件也有自己的.vue .js 和compoent自身组件,如下page里的一个文件就是一个页面。

 那这么多页面之间如果有参数需要互相传递,这时就只能借用localStorage本地存储了,或者封装一个全局传参方法,挂载注册到main.js里,我是封装的localStorage方法。

如果页面之间相互跳转,没有单页面路由了,那就只能是window.location.href了,alertDialog里的哪个app.openView是安卓跳转方法,其实就相当于下面的注释。

 那么这些页面最终也需要打包,最核心的就是下面方框里的代码了,chunk最终就是每个页面的文件名,对应的就是文件名.html.

glob是打包多页面的一个方案插件,最后把pages对象抛出就行了。

vue组件之间通讯?

父传子 父组件向子组件通过props接收数据

子传父 因为是单向数据流所以只能通过触发父组件的方法改变数据
子组件 父组件

兄弟组件传值中央事件总线
1、 main.js文件创建一个vue实例

2、引入main.js文件使用$emit传值

vuex
state存放属性、getters计算属性、mutations同步修改数据、actions异步修改数据的方法modules当数据量大时可以把单个属性拆分成一个模块
直接访问 state和getters 在compute或者在模板上直接访问 模板上访问 访问mutations和action

Proxy与Object.defineProperty的优劣对比?

Proxy的优势如下:

  • Proxy可以直接监听对象而非属性
  • Proxy可以直接监听数组的变化
  • Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty 不具备的Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改
  • Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利 Object.defineProperty的优势如下:

兼容性好,支持IE9

既然Vue通过数据劫持可以精准探测数据变化,为什么还需要虚拟DOM进行diff检测差异?

现代前端框架有两种方式侦测变化,一种是pull一种是push

pull: 其代表为React,我们可以回忆一下React是如何侦测到变化的,我们通常会用 setState API显式更新,然后React会进行一层层的Virtual Dom Diff操作找出差异,然后Patch到DOM上,React从一开始就不知道到底是哪发生了变化,只是知道「有变化了」,然后再进行比较暴力的Diff操作查找「哪发生变化了」,另外一个代表就是Angular的脏检查操作。

push: Vue的响应式系统则是push的代表,当Vue程序初始化的时候就会对数据data进行依赖的收集,一但数据发生变化,响应式系统就会立刻得知,因此Vue是一开始就知道是「在哪发生变化了」,但是这又会产生一个问题,如果你熟悉Vue的响应式系统就知道,通常一个绑定一个数据就需要一个Watcher,一但我们的绑定细粒度过高就会产生大量的Watcher,这会带来内存以及依赖追踪的开销,而细粒度过低会无法精准侦测变化,因此Vue的设计是选择中等细粒度的方案,在组件级别进行push侦测的方式,也就是那套响应式系统,通常我们会第一时间侦测到发生变化的组件,然后在组件内部进行VirtualDom Diff获取更加具体的差异,而Virtual Dom Diff则是pull操作,Vue是push+pull结合的方式进行变化侦测的.

Vue为什么没有类似于React中shouldComponentUpdate的生命周期?

根本原因是Vue与React的变化侦测方式有所不同

React是pull的方式侦测变化,当React知道发生变化后,会使用Virtual Dom Diff进行差异检测,但是很多组件实际上是肯定不会发生变化的,这个时候需要用shouldComponentUpdate进行手动操作来减少diff,从而提高程序整体的性能.

Vue是pull+push的方式侦测变化的,在一开始就知道那个组件发生了变化,因此在push的阶段并不需要手动控制diff,而组件内部采用的diff方式实际上是可以引入类似于shouldComponentUpdate相关生命周期的,但是通常合理大小的组件不会有过量的diff,手动优化的价值有限,因此目前Vue并没有考虑引入shouldComponentUpdate这种手动优化的生命周期

Vue中的key到底有什么用?

key 是为Vue中的vnode标记的唯一id,通过这个key,我们的diff操作可以更准确、更快速

diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的 key 与旧节点进行比对,然后超出差异

diff程可以概括为:oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一个已经遍历完了,就会结束比较,这四种比较方式就是首、尾、旧尾新头、旧头新尾

  1. 准确: 如果不加 key ,那么vue会选择复用节点(Vue的就地更新策略),导致之前节点的状态被保留下来,会产生一系列的bug.
  2. 快速: key的唯一性可以被Map数据结构充分利用,相比于遍历查找的时间复杂度O(n),Map的时间复杂度仅仅为O(1)

Vue2和vue3的区别

  • vue3的template支持多个根标签,vue2不支持
  • vue3有createApp(组件)vue2是new vue({template,render})
  • v-model代替以前的v-model和.Sync
  • vue3的v-model的用法
  • Props属性名任意,假设为x
  • 事件名必须为updata
  • < Switch  : value**="y" @update : value=**"y=$event" />
  • vue2中的写法
  • < Switch  : value.sync**=**"y" />
  • vue3中的写法
  • < Switch v**-model : value=**"y" />
  • context.emit
  • 新增context.emit,与this.$emit(vue3中只能在methods里使用)作用相同

Vue3的属性绑定
默认所有属性都绑定到根元素使用inheritAttrs: false可以取消默认绑定使用attrs或者context.attrs获取所有属性使用v-bing="$attrs"批量绑定属性使用 const {size, level, ...rest} = context.attrs 将属性分开
使用场景
在vue2中我们在父组件绑定ckick事件,子组件必须内部触发click
而vue3中在父组件绑定子组件的根元素上也会跟着绑定

//Vue2和vue3的区别 以上来自前端大白话公众号

JavaScript

为什么会有BigInt的提案?

JavaScript中Number.MAX_SAFE_INTEGER表示最大安全数字,计算结果是9007199254740991,即在这个数范围内不会出现精度丢失(小数除外)。
但是一旦超过这个范围,js就会出现计算不准确的情况,这在大数计算的时候不得不依靠一些第三方库进行解决,因此官方提出了BigInt来解决此问题。

null与undefined的区别是什么?

null表示为空,代表此处不应该有值的存在,一个对象可以是null,代表是个空对象,而null本身也是对象。
undefined表示『不存在』,JavaScript是一⻔动态类型语言,成员除了表示存在的空值外,还有可能根本就不存在(因为存不存在只在运行期才知道),这就是undefined的意义所在。

0.1+0.2为什么不等于0.3?

JS 的 Number 类型遵循的是 IEEE 754 标准,使用的是 64 位固定⻓度来表示。
IEEE 754 浮点数由三个域组成,分别为 sign bit (符号位)、exponent bias (指数偏移值) 和 fraction (分数值)。64 位中,sign bit 占 1 位,exponent bias 占 11 位,fraction 占 52 位。

通过公式表示浮点数的值value = sign x exponent x fraction

当一个数为正数,sign bit 为 0,当为负数时,sign bit 为 1.以 0.1 转换为 IEEE 754 标准表示为例解释一下如何求 exponent bias 和 fraction。转换过程主要经历 3 个过程:

  1. 将 0.1 转换为二进制表示
  2. 将转换后的二进制通过科学计数法表示
  3. 将通过科学计数法表示的二进制转换为 IEEE 754 标准表示

将 0.1 转换为二进制表示

回顾一下一个数的小数部分如何转换为二进制。一个数的小数部分,乘以 2,然后取整数部分的结果,再用计算后的小数部分重复计算,直到小数部分为 0

通过科学计数法表示

0.00011...(无限重复 0011) 通过科学计数法表示则是 1.10011001...(无线重复 1001)*2

转换为 IEEE 754 标准表示

当经过科学计数法表示之后,就可以求得 exponent bias 和 fraction 了。

exponent bias (指数偏移值) 等于双精度浮点数固定偏移值 (2-1) 加上指数实际值(即 2 中的 -4) 的11 位二进制表示。为什么是 11 位?因为 exponent bias 在 64 位中占 11 位。

因此 0.1 的 exponent bias 等于 1023 + (-4) = 1019 的11 位二进制表示,即 011 1111 1011。

再来获取 0.1 的 fraction,fraction 就是 1.10011001...(无线重复 1001) 中的小数位,由于 fraction 占 52位所以抽取 52位小数,1001...(中间有 11 个 1001)...1010 (请注意最后四位,是 1010 而不是 1001,因为四舍五入有进位,这个进位就是造成 0.1 + 0.2 不等于 0.3 的原因

什么是闭包使用场景?

  1. 闭包是指有权访问另一个函数作用域中的变量的函数
  2. 函数对象可以通过作用域关联起来,函数体内的变量都可以保存在函数作用域内,这在计算机科学文献中称为“闭包”,所有的javascirpt函数都是闭包

怎么实现递归?

递归做为一种算法在程序设计语言中广泛应用.是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。

递归算法一般用于解决三类问题:

  • a.数据的定义是按递归定义的。(Fibonacci(斐波那契)函数)
  • b.问题解法按递归算法实现。(回溯)
  • c.数据的结构形式是按递归定义的。(树的遍历,图的搜索)

什么是防抖和节流?

- 防抖 是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间
应用场景:用户注册时候的手机号验证和邮箱验证;搜索框
- 节流 指连续触发事件但是在N秒中只执行一次函数,即每间隔某个事件去执行某个函数,避免函数的过多执行
应用场景:window对象的resize、scroll事件;拖拽时候的mousemove;文字输入、自动完成的keyup事件

promise的使用场景?

Promise可以用来避免异步操作函数里的嵌套回调(callback hell)问题,因为解决异步最直接的方法是回调嵌套,将后一个的操作放在前一个操作的异步回调里,但如果操作多了,就会有很多层的嵌套。 promise的知识点

1.Promise实例的then方法作用是为Promise实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数。
2.then方法返回的是一个新的Promise实例,(注意:不是原来那个Promise实例)。因此可以采用链式写法。
3.Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。即错误总会被下一个catch语句捕获。
4.一般,不要在then 方法中定义rejected状态的回调函数(即then的第二个参数),而应总是使用catch方法。因为catch更接近同步写法。
5.catch方法返回的还是一个Promise对象,可接着调用then方法。
6.在 JavaScript 函数中,只有 return / yield / throw 会中断函数的执行,其他的都无法阻止其运行到结束的,这也是所谓的Run-to-completion 特性。

promise的优点

  1. Promise 的一大优点,就是结果不变性,一旦 Promise 的值确定为fulfilled 或者 rejected 后,无论过多久,获取到的 Promise 对象的值都是一样的。 对不变性的理解:
    像 resolve/reject 不过只是一个回调而已,而所谓的不变性只是说,当遇到第一个 resolve/reject 后,便根据其结果给此 Promise 打上了一个 tag,并且不能更改,而后面的该干啥继续干,不干本 Promise 的事儿了。
    使用promise注意事项
    1.始终在Promise 构造器中书写逻辑的话,即使出现了意外的输入,也能绝大部分情况下返回一个Rejected 的 Promise
    2.在 Promise 构造器中,除非你明确知道使用 throw 的正确姿势,否则都请使用 reject。
    3。能够兼容 Promise 和 Callback 确实是件很棒的事情,用第三方代码前请尽量理解其原理,短小的话完全可以自己写一个。Promise虽好,可不要乱用哦,实时牢记它会吞没错误的风险。\

Promise三个状态:pending、fulfilled、rejected

两个过程:pending->fulfilled、pending->rejected

什么时候会进入catch当pending为rejectd时,会进入catch

setTimeout和Promise区别?

Promise是一个micro task  主线程是一个task  micro task queue会在task后面执行
setTimeout返回的函数是一个新的task macro task queue\

所以Promise会先于新task执行 根据html标准  一个task执行完后 ui会重渲染 

vue源码:    nextTick异步更新dom操作先判断是否支持Promise  再判断是否支持MutationObserve 最后是set macroTask Queue(宏任务队列) : setTimeout  setInterval   setImmediate   requestAnimationFrame  NodeJS的I/O microTask Queue(微任务队列):promise   (独立回调)其成功/失败回调函数相互独立 复合回调: Object.observe, MutationObserver 和NodeJs中的 process.nextTick ,不同状态回调在同一函数体  requestAnimationFrame是html5的api  有兼容性问题 但是精度比较高

它的时间间隔是系统决定的  保证屏幕刷新一次  回调函数只执行一次 比如屏幕刷新的频率是60hz 间隔1000ms/60hz执行一次回调

get和post什么区别?

  • get是获取数据的,而post是提交数据的。
  • GET 用于获取信息,是无副作用的,是幂等的,且可缓存, 而POST 用于修改服务器上的数据,有副作用,非幂等,不可缓存。

说一下浏览器垃圾回收机制?

1、引用计数 对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。

限制:循环引用
2、标记清除

这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。

这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进

相比【引用计数】的好处:循环引用不再是问题了

限制: 那些无法从根对象查询到的对象都将被清除

异步和同步的区别?

同步就是在一个操作完成后才能继续下一个操作

异步则是一个操作没有完成就可以进行下一个操作

async/await是什么?

async 函数,就是 Generator 函数的语法糖,它建立在Promises上,并且与所有现有的基于Promise的API兼容。

  1. Async—声明一个异步函数(async function someName(){...})
  2. 自动将常规函数转换成Promise,返回值也是一个Promise对象
  3. 只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
  4. 异步函数内部可以使用await
  5. Await—暂停异步的功能执行(var result = await someAsyncCall();)
  6. 放置在Promise调用之前,await强制其他代码等待,直到Promise完成并返回结果
  7. 只能与Promise一起使用,不适用与回调
  8. 只能在async函数内部使用

async/await相比于Promise的优势?

  • 代码读起来更加同步,Promise虽然摆脱了回调地狱,但是then的链式调用也会带来额外的阅读负担
  • Promise传递中间值非常麻烦,而async/await几乎是同步的写法,非常优雅错
  • 误处理友好,async/await可以用成熟的try/catch,Promise的错误捕获非常冗余
  • 调试友好,Promise的调试很差,由于没有代码块,你不能在一个返回表达式的箭头函数中设置断点,如果你在一个.then代码块中使用调试器的步进(step-over)功能,调试器并不会进入后续的.then代码块,因为调试器只能跟踪同步代码的『每一步』。

聊一聊如何在JavaScript中实现不可变对象?

实现不可变数据有三种主流的方法

  1. 深克隆,但是深克隆的性能非常差,不适合大规模使用
  2. Immutable.js,Immutable.js是自成一体的一套数据结构,性能良好,但是需要学习额外的API
  3. immer,利用Proxy特性,无需学习额外的api,性能良好

JavaScript的基本类型和复杂类型是储存在哪里的?

基本类型储存在栈中,但是一旦被闭包引用则成为常住内存,会储存在内存堆中。复杂类型会储存在内存堆中

js冒泡排序?

原理:依次比较相邻的两个值,如果后面的比前面的小,则将小的元素排到前面。依照这个规则进行多次并且递减的迭代,直到顺序正确。

var examplearr=[8,94,15,88,55,76,21,39];
function sortarr(arr){
    for(i=0;i<arr.length-1;i++){
        for(j=0;j<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
                var temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
    return arr;
}
sortarr(examplearr);
console.log(examplearr);

jsonp的原理?

jsonp是一种跨域通信的手段,它的原理其实很简单:

1. 首先是利用script标签的src属性来实现跨域。

2. 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。

3.由于使用script标签的src属性,因此只支持get方法

ajax的实现原理?

通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面

js的setTimeout和setInterval的区别?

  • setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式,
  • setInterval()则是在每隔指定的毫秒数循环调用函数或表达式,直到clearInterval把它清除。
  • 也就是说setTimeout()只执行一次,setInterval()可以执行多次。

js的宏任务和微任务,js去重,js操作数组的方法?

  • 宏任务 (macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
  • 微任务 microtask,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。

js操作dom的方法?

  • var div1 = document.getElementById("box1");      //方式一:通过id获取单个标签
  • var arr1 = document.getElementsByTagName("div1");     //方式二:通过 标签名 获得 标签数组,所以有s
  • var arr2 = document.getElementsByClassName("hehe");  //方式三:通过 类名 获得 标签数组,所以有s
  • document.getElementsByTagName("div1")[0];    //取数组中的第一个元素
  • document.getElementsByClassName("hehe")[0];  //取数组中的第一个元素

创建节点

格式如下:

新的标签(元素节点) = document.createElement("标签名");

插入节点

插入节点有两种方式,它们的含义是不同的。

方式1:  父节点.appendChild(新的子节点);

解释:父节点的最后插入一个新的子节点。

方式2: 父节点.insertBefore(新的子节点,作为参考的子节点);

解释:

· 在参考节点前插入一个新的节点。

· 如果参考节点为null,那么他将在父节点最后插入一个子节点。

删除节点

格式如下:

  父节点.removeChild(子节点);

解释:用父节点删除子节点。必须要指定是删除哪个子节点。

如果我想删除自己这个节点,可以这么做:

node1.parentNode.removeChild(node1);

复制节点(克隆节点)

格式如下:

  要复制的节点.cloneNode();       //括号里不带参数和带参数false,效果是一样的。

  要复制的节点.cloneNode(true);

括号里带不带参数,效果是不同的。解释如下:

不带参数/带参数false:只复制节点本身,不复制子节点。

带参数true:既复制节点本身,也复制其所有的子节点。

js事件机制?

js的事件机制和flash差不多,都是三个阶段:捕获、目标和冒泡

事件冒泡

微软提出了名为事件冒泡的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。

因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document

事件捕获

网景提出另一种事件流名为事件捕获与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p

W3C事件阶段(event phase)

当一个DOM事件被触发的时候,他并不是只在它的起源对象上触发一次,而是会经历三个不同的阶段。简而言之:事件一开始从文档的根节点流向目标对象(捕获阶段),然后在目标对向上被触发(目标阶段),之后再回溯到文档的根节点(冒泡阶段)如图所示(图片来自W3C):

image.png

事件代理

事件代理用到了两个在JavaSciprt事件中两个特性:事件冒泡以及目标元素。使用事件代理,我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。

事件类型

之前写过一篇自定义事件的随笔,其中的createEvent方法有点意思,这里就来看下这些事件的一个大致关系

事件类型有:UI(用户界面)事件,用户与页面上元素交互时触发 ;焦点事件:当元素获得或失去焦点时触发 ; 文本事件:当在文档中输入文本时触发;键盘事件:当用户通过键盘在页面上执行操作时触发;鼠标事件:当用户通过鼠标在页面上执行操作时触发;滚轮事件:当使用鼠标滚轮(或类似设备)时触发。它们之间是继承的关系

js基本数据类型跟引用类型有什么区别?

 a 声明变量时不同的内存分配: 

  1)原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。

  2)引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。

  b 不同的内存分配机制也带来了不同的访问机制

  1)在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,

    首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。

  2)而原始类型的值则是可以直接访问到的。

  c 复制变量时的不同

  1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。

  2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,

    也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。

  d 参数传递的不同(把实参复制给形参的过程)

js有几个内置对象?

数据封装类对象: Object 、 Array 、 Boolean 、 Number 和 String

其他对象: Function 、 Arguments 、 Math 、 Date 、 RegExp 、 Error、

js的作用域和作用域链?

作用域

1.全局作用域

2.函数作用域

3.块级作用域

作用域,就是变量或者是函数能作用的范围。

作用域链
当查找变量的时候,会先从当前作用域的变量对象中查找,如果没有找到,就会从父级作用域(上层环境)的变量对象中查找,一直找到全局作用域的变量对象,也就是全局对象。这样由多个作用域的变量对象构成的链表就叫做作用域链。它由当前环境与上层环境的一系列变量对象组成,保证了当前执行环境对符合访问权限的变量和函数的有序访问。

原型和原型链的区别?

原型理解:每一个对象创建的时候,都会关联另一个对象,这个对象就是原型对象,创建出来的对象会从原型对象中继承属性和方法。

原型链的理解: 当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。

深拷贝和浅拷贝的区别?

浅拷贝:相当于使两个数组指针指向相同的地址,任一个数组元素发生改变,影响另一个。

深拷贝:两数组指针指向不同的地址,数组元素发生改变时不会相互影响

js的缓存机制?

Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。浏览器和网站服务器是根据缓存机制进行缓存的(浏览器缓存机制)

node.js是什么?

简单的说 Node.js 就是运行在服务端的 JavaScript。

Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。

Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

Js怎么阻止事件冒泡?

w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true

什么是事件委托事件委托?

就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.在绑定大量事件的时候往往选择事件委托 优点:

  • 节省内存占用,减少事件注册
  • 新增子对象时无需再次对其绑定事件,适合动态添加元素局限性:
  • focus、blur 之类的事件本身没有事件冒泡机制,所以无法委托
  • mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,不适合事件委托DOM面试题

es系列问题?

网络相关

HTTP有哪些方法?

HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法 HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 这些方法的具体作用是什么?

  • GET: 通常用于请求服务器发送某些资源
  • HEAD: 请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致. 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源
  • OPTIONS: 用于获取目的资源所支持的通信选项
  • POST: 发送数据给服务器
  • PUT: 用于新增资源或者使用请求中的有效负载替换目标资源的表现形式
  • DELETE: 用于删除指定的资源
  • PATCH: 用于对资源进行部分修改
  • CONNECT: HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
  • TRACE: 回显服务器收到的请求,主要用于测试或诊

同样是重定向307,303,302的区别?

302是http1.0的协议状态码,在http1.1版本的时候为了细化302状态码又出来了两个303和307。

303明确表示客户端应当采用get方法获取资源,他会把POST请求变为GET请求进行重定向。 307会遵照浏览器标准,不会从post变为get。

HTTP的keep-alive是干什么的?

在早期的HTTP/1.0中,每次http请求都要创建一个连接,而创建连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重用连接。在后来的HTTP/1.0中以及HTTP/1.1中,引入了重用连接的机制,就是在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流。协议规HTTP/1.0如果想要保持⻓连接,需要在请求头中加上Connection: keep-alive。 keep-alive的优点:

  • 较少的CPU和内存的使用(由于同时打开的连接的减少了)
  • 允许请求和应答的HTTP管线化
  • 降低拥塞控制(TCP连接减少了)
  • 减少了后续请求的延迟(无需再进行握手)
  • 报告错误无需关闭TCP连

为什么有了HTTP为什么还要HTTPS?

https是安全版的http,因为http协议的数据都是明文进行传输的,所以对于一些敏感信息的传输就很不安全,HTTPS就是为了解决HTTP的不安全而生的。

http的状态码?

http状态码

浏览器的渲染过程?

  1. 浏览器会查询本地缓存的dns列表,以获取主机地址,若dns缓存未命中,则浏览器发出请求,进行查询,查询之后的结果缓存起来。
  2. 连接主机
  3. 发送请求
  4. 获得一个服务器的响应
  5. 进行渲染

http和https的作用和区别?

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

什么跨域,怎么解决?

跨域指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。 解决跨域的办法:

  • 通过jsonp跨域
  • document.domain + iframe跨域
  • location.hash + iframe
  • window.name + iframe跨域
  • postMessage跨域
  • 跨域资源共享(CORS)
  • nginx代理跨域
  • nodejs中间件代理跨域
  • WebSocket协议跨域 Vue解决跨越:
    (1)在Vue中最推荐的是CORS,全称为 Cross Origin Resource Sharing(跨域资源共享)。 这种方案对于前端来说没有什么工作量,和平时发请求写法上没有任何区别,工作量基本都在后端这里,使用CORS前端不需要配置proxytable。
    每一次请求,浏览器必须先以 OPTIONS 请求方式发送一个预请求,从而获知服务器端对跨源请求所支持 HTTP 方法。在确认服务器允许该跨源请求的情况下,以实际的 HTTP 请求方法发送那个真正的请求。
    (2)vue cli30修改配置信息需要新建vue.config.js文件,在module.exports方法的devServer对象中proxy 选项来添加代理配置,当前端没有匹配到当前路由时就会被代理到服务器接口地址。

列举出常见的浏览器兼容性问题?

HTML5,CSS3

sessionStorage,localStorage,cookies的区别?

  • Cookie特性 :一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 存放数据大小为4k左右与服务器端通信每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题
  • sessionStorage localStorage 共有特性:仅在客户端(即浏览器)中保存,不参与和服务器的通信为存放数据大小为5MB 易用性 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持
  • localStorage:除非被清除,否则永久保存
  • sessionStorage:仅在当前会话下有效,关闭页面或浏览器后被清除

cookie和session区别?

  1. 数据的声明周期:cookies一般由服务器生成,可设置失效时间。如果在浏览器生成,默认是关闭浏览器之后失效;LocalStorage除非被清除,否则永久保存
  2. 存放数据大小:cookies为4KB;LocalStorage一般为5MB
  3. 与服务端通信:cookies每次都会携带在HTTP头中,如果使用 cookie 保存过多数据会带来性能问题;LocalStorage仅在客户端中保存,不参与和服务器的通信。 也可有脚本选择性提交到服务器端
  4. 用途: cookies一般由服务器端生成,用于标识用户身份; LocalStorage用于浏览器端缓存数据

sass和less区别?

- 不同之处

  • 1、Less环境较Sass简单 Cass的安装需要安装Ruby环境,Less基于JavaScript,是需要引入Less.js来处理代码输出css到浏览器,也可以在开发环节使用Less,然后编译成css文件,直接放在项目中,有less.app、SimpleLess、CodeKit.app这样的工具,也有在线编辑地址。
  • 2、Less使用较Sass简单 LESS 并没有裁剪 CSS 原有的特性,而是在现有 CSS 语法的基础上,为 CSS 加入程序式语言的特性。只要你了解 CSS 基础就可以很容易上手。
  • 3、从功能出发,Sass较Less略强大一些 ①sass有变量和作用域。 variable,like php; #{variable}like ruby; 变量有全局和局部之分,并且有优先级。
    ②sass有函数的概念; @function和@return以及函数参数(还有不定参)可以让你像js开发那样封装你想要的逻辑。 -@mixin类似function但缺少像function的编程逻辑,更多的是提高css代码段的复用性和模块化,这个用的人也是最多的。-ruby提供了非常丰富的内置原生api。
    ③进程控制: -条件:@if @else; -循环遍历:@for @each @while -继承:@extend -引用:@import
    ④数据结构: -l i s t 类 型 = 数 组 ; − list类型=数组; -list类型=数组;−map类型=object; 其余的也有string、number、function等类型
  • 4、Less与Sass处理机制不一样 前者是通过客户端处理的,后者是通过服务端处理,相比较之下前者解析会比后者慢一点
  • 5、关于变量在Less和Sass中的唯一区别就是Less用@,Sass用$。

- 相同之处

  • Less和Sass在语法上有些共性,比如下面这些:
  1. 混入(Mixins)——class中的class;
  2. 参数混入——可以传递参数的class,就像函数一样;
  3. 嵌套规则——Class中嵌套class,从而减少重复的代码;
  4. 运算——CSS中用上数学;
  5. 颜色功能——可以编辑颜色;
  6. 名字空间(namespace)——分组样式,从而可以被调用;
  7. 作用域——局部修改样式;
  8. JavaScript 赋值——在CSS中使用JavaScript表达式赋值。

flex弹性布局?

弹性布局(flex container),页面中任何一个元素只要设置了display:flex属性,那么当前盒子都称为弹性盒子。弹性盒子默认有两条轴: 默认水平显示的主轴 和 始终要垂直于主轴的侧轴(也叫交叉轴),在弹性盒子中所有的子元素都是沿着主轴方向显示。

盒子模型?

在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区域。4个部分一起构成了css中元素的盒模型。

rem是什么,rem和px的转换,rem和百分比的区别?

rem 它的全称是 font size of the root element (根元素的字体大小) 它是CSS3中新增加的一个尺寸(度量)单位,根节点(html)的font-size决定了rem的尺寸,也就是说它是一个相对单位,相对于 (html)。

1rem等于html根元素设定的font-size的px值,假如我们在css里面设定下面的css。 那么后面的 CSS 里面的rem值则是以这个14来换算,例如设定一个div宽度为3rem,高度为2.5rem.则它换算成px为width:42px.height:35px,同理,假如一个设计稿为宽度42px,高度为35px,则换成成rem,则是42/14=3rem,35/14=2.5rem。

rem 在处理小数的时候会有误差, 百分比 要按照父级的尺寸去计算,不灵活

移动端适配、自适应、兼容问题?

  • flex弹性布局
  • 百分比
  • 用框架搭建页面
  • viewport适配
  • 媒体查询media
  • rem+viewport缩放(也成为1px适配)

css选择器的优先级?

!Important>行内>id>class>标签>外部样式

2、css3新特性?****

  •  阴影:使用box-shadow给逻辑框设置一个阴影,text-shadow文字加阴影

  •  圆角:使用border-image和它关联的普通属性,而且可以通过border-radius属性来支持圆角边框

  •  动画:为你的样式设置动画使用CSS Transitions以在不同的状态间设置动画,或者使用CSS Animations在页面的某些部分设置动画而不需要一个触发事件,你现在可以在页面中控制移动元素了

  •  flex布局:css多栏布局

  •  grid布局:网格布局

  •  线性渐变:使用gradient设置线性渐变

  •  媒体查询:根据显示设备的特性设置css

css的预编译器?

less、sass、stylus

css如何清除浮动?

Clear清除浮动、父级加overfolw:hidden、after伪类、浮动元素后加空div

css水平垂直居中?

  方法一:position定位(适用于子盒子有宽度和高度的时候)

  方法二:子元素绝对定位,距离顶部 50%,左边50%,然后使用css3 transform:translate(-50%; -50%)(子盒子有或没有宽高的时候都适用)

  方法三:flex布局(子盒子有或没有宽高的时候都适用

css动画效果?

@keyframes规定动画模式。
animation设置所有动画属性的简写属性。
animation-delay规定动画开始的延迟。
animation-direction定动画是向前播放、向后播放还是交替播放。
animation-duration规定动画完成一个周期应花费的时间。
animation-fill-mode规定元素在不播放动画时的样式(在开始前、结束后,或两者同时)。
animation-iteration-count规定动画应播放的次数。
animation-name规定 @keyframes 动画的名称。
animation-play-state规定动画是运行还是暂停。
animation-timing-function规定动画的速度曲线。

c3里面svg跟canvas的区别?

1、svg绘制出来的每一个图形的元素都是独立的DOM节点,能够方便的绑定事件或用来修改。canvas输出的是一整幅画布;

    2、svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会是真和锯齿。而canvas输出标量画布,就像一张图片一样,放大会失真或者锯齿

css3的伪类有哪些?

  • :root 选择文档的根元素,等同于 html 元素
  • :empty 选择没有子元素的元素
  • :target 选取当前活动的目标元素
  • :not(selector) 选择除 selector 元素意外的元素
  • :enabled 选择可用的表单元素
  • :disabled 选择禁用的表单元素
  • :checked 选择被选中的表单元素
  • :after 在元素内部最前添加内容
  • :before 在元素内部最后添加内容
  • :nth-child(n) 匹配父元素下指定子元素,在所有子元素中排序第n
  • :nth-last-child(n) 匹配父元素下指定子元素,在所有子元素中排序第n,从后向前数
  • :nth-of-type(n) 匹配父元素下指定子元素,在同类子元素中排序第n
  • :nth-last-of-type(n) 匹配父元素下指定子元素,在同类子元素中排序第n,从后向前数
  • :selection 选择被用户选取的元素部分
  • :first-line 选择元素中的第一行
  • :first-letter 选择元素中的第一个字符

块级元素和行内元素?

  • 块元素:独占一行,不与其他元素并列,有宽高,默认继承父级宽高
  • 行内:与其他元素并列,没有宽高

html5和html的区别?

  • 1、文档声明区别 HTML:超文本标记语言,一种纯文本类型的语言。

HTML5.0:文档声明HTML5方便书写,精简,有利于程序员快速的阅读和开发。

  • 2、结构语义区别 html:没有体现结构语义化的标签,如:<div id="nav"></div>

html5:添加了许多具有语义化的标签,如:<article>、<aside>、<audio>、<bdi>

  • 3、绘图区别 HTML:指可伸缩矢量图形,用于定义网络的基于矢量的图形。

HTML5:HTML5的canvas元素使用脚本(通常使用JavaScript)在网页上绘制图像,可以控制画布每一个像素。

html5新增的标签?

- 结构标签

  • header:一般网页头部信息/标题。
  • nav:导航条部分内容。section:独立内容区块,一般内容区。
  • article:特殊独立区块,表示页眉中核心内容。
  • aside:标签内容之外,与标签内容相关的辅助信息。
  • figure:独立单元,如有图文混合模块。
  • hgroup:头部信息/标题相关信息。
  • footer:底部信息。 - 表单元素
  • search:搜索框。应用非常广泛,与text的区别是有值的时候会有清空按钮。
  • email:邮箱地址,自动校验。
  • url:http地址,自动校验。
  • number:必须输入数值,通过min、max属性可以设置最小最大值。
  • range:必须输入一定范围内的数值。
  • color:颜色选择器。日期选择器:date:选取年月日。
  • month:选取年月。week:选择周和年。time:选取时间。
  • datetime:选取时间、年月日。示例:<input type="number" min="0" max="3"> - 媒体标签
    video:视频audio:音频embed:嵌入内容,包括各种媒体,flash,图片等。
    - 其他功能标签
  • progress:进度条。<progress max="100" min="1" value="20"></progress>
  • datalist:文本域下拉提示。
  • detail:展开菜单。
  • mark:标注。
  • time:数据标签,给搜索引擎使用,主要日期标签。
  • canvas:使用js进行图像绘制。
  • ruby:对某些内容进行注释。
  • command:按钮。

html渲染过程 ?

  • 获取的HTML文档并解析成DOM树。
  • 处理CSS标记,构成层叠样式表模型CSSOM
  • 将DOM和CSSOM合并为渲染树(rendering tree),代表一系列将被渲染的对象。
  • 通过js引擎来解析Javascript脚本
  • 重新计算各元素位置来布局页面,也称reflow(回流)
  • 将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting(重绘)

HTML5语义化?

根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析。

webpack

webpack与grunt、gulp的不同?

Grunt、Gulp是基于任务运行的工具:

它们会自动执行指定的任务,就像流水线,把资源放上去然后通过不同插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各种工作流。

Webpack是基于模块化打包的工具:

自动化处理模块,webpack把一切当成模块,当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

因此这是完全不同的两类工具,而现在主流的方式是用npm script代替Grunt、Gulp,npm script同样可以打造任务流

webpack怎么打包?

1.安装webpack

cnpm install webpack webpack-cli -g;

新建一个src文件,在其目录下新建一个main.js入口文件(如果都已经生成存在则不用管)

  1. 初始化项目包

npm init -y 生成package.json

  1. 本地安装webpack依赖

cnpm install webpack webpack-cli --save-dev

  1. webpack打包
webpack ./src/main.js -o ./dist/bundle.js --modedevelopment //开发模式
webpack ./src/main.js -o ./dist/bundle.js --modeproduction //生产模式
          //端口
          port:3000,
          //自动打开浏览器
          open:true,
       }   
       //安装cnpm install webpack-dev-server -g 进行启动,如果执行错误,查看package.json文件安装依赖,cnpm install                      
}

小程序、uniapp面试题

小程序的生命周期有哪些?

应用生命周期
App() 必须在 app.js 中调用,必须调用且只能调用一次,app.js中定义了一些应用的生命周期函数\

  1. onLaunch: 初始化小程序时触发,全局只触发一次\
  2. onShow: 小程序初始化完成或用户从后台切换到前台显示时触发\
  3. onHide: 用户从前台切换到后台隐藏时触发\
  4. onError: 小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
    后台: 点击左上角关闭,或者按了设备 Home 键离开微信,并没有直接销毁,而是进入后台
    前台:再次进入微信或再次打开小程序,相当于从后台进入前台

页面生命周期

  1. onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。\
  2. onShow:加载完成后、后台切到前台或重新进入页面时触发\
  3. onReady:页面首次渲染完成时触发\
  4. onHide:从前台切到后台或进入其他页面触发\
  5. onUnload:页面卸载时触发

微信小程序登录功能?

1.点击按钮出现授权提示框

2,点击取消给出提示并返回页面

3,点击确定调用 wx.login(Object object)获取凭证

4,获取到凭证后调用wx.getUserInfo获取用户信息并返回给后端存储

5,后端存储后返回一个自定义凭证,用于接口权限验证

小程序后台的配置,如果是后台数据的问题你会怎么处理?

 

小程序的白名单与黑名单了解吗?

利用Oenid实现白名单和黑名单
1.通过获取openid 存储到数据库中
2.结合数据库中额用户资料实现白名单和黑名单。

说一下微信小程序的优劣势 ,作用域插槽?

**优势: **

  1. 无需下载,通过搜索和扫一扫就可以打开。
  2. 良好的用户体验:打开速度快。
  3. 开发成本要比App要低。
  4. 安卓上可以添加到桌面,与原生App差不多。
  5. 为用户提供良好的安全保障。小程序的发布,微信拥有一套严格的审查流程,不能通过审查的小程序是无法发布到线上的

劣势:

  1. 限制较多。页面大小不能超过1M。不能打开超过5个层级的页面。
  2. 样式单一。小程序的部分组件已经是成型的了,样式不可以修改。例如:幻灯片、导航。
  3. 推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广。其中附近小程序也受到微信的限制。
  4. 依托于微信,无法开发后台管理功能

组件之间如何传值?

父组件向子组件传值 方式:WXML 数据绑定

1.父组件:直接绑定父组件的数据到子组件上

2.子组件:在properties内接收父组件的数据

子组件向父组件传值 方式:自定义事件

自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项

微信支付是怎么做的?

下单

这里是用户与页面交互,例如点击付款按钮,触发支付交互

向后端发出支付请求通过接口请求给后端系统提供参数:商品ID,总价totalPrice

后端系统与微信服务进行交互,换取参数

后端系统得到微信返回的相关数据后,经过解密处理返回前端需要的相关参数,即wx.requestPayment()需要的相关参数

发起微信支付

微信服务返回支付的结果 根据微信返回的结果(成功或失败),前端做出对应的提示

微信服务把支付结果通知给后端系

微信小程序怎么获取后台的数据?

使用wx.request进行网络数据请求

微信小程序的常用api?

wx.switchTab :只能跳转到导航页,并关闭其他的导航页

wx.reLaunch :关闭所有页面,打开到应用内的某个页面

wx.redirectTo :关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 导航 页面

wx.navigateTo :只保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面(最多10层)

wx.navigateBack :返回上一页,可以返回多级页面

数据缓存

wx.setStorageSync('key', 'value')

wx.getStorageSync('key')

微信小程序有几个文件?

1.WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式, js 逻辑处理,网络请求json小程序设置,如页面注册,页面标题及 tabBar。

2.app.json 必须要有这个文件,如果没有这个文件,项目无法运行,因为微信框架把这个作为配置文件入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的window 背景色,配置导航条样式,配置默认标题。

3.app.js 必须要有这个文件,没有也是会报错!但是这个文件创建一下就行 什么都不需要写以后我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。

4.app.wxss 配置全局 css

小程序赋值?

使用this.setData({})

小程序怎么获取用户信息的?

1.小程序js端调用框架登陆API,获取到一个临时code,拿着这个code去调用自己的服务端接口

2.在自己的服务器端,使用app_id app_secrect code可以获取到用户的openid,这个id是用户唯一的id并且不会改变,可以把这个id返回给小程序端
小程序端本地保存openid

3.获取用户信息很简单,并且不需要自己的服务器处理,只需要小程序端提供的API。
前端页面wxml使用一个按钮,按钮里增加几个属性,就可以回调到小程序js部分的方法上,并且带着用户的个人信息,如昵称 头像等

4.这个时候就可以把该用户的openid 和 昵称,头像,一块调用自己服务端接口,保存到数据库中

小程序里的数据缓存有哪些?******

wx.setStorageSync('key', 'value')存储数据

wx.getStorageSync('key')获取缓存中数据

小程序开发模式是怎样的?******

·  一个文件夹(包含html,css,js文件)包含一个页面的所有代码

·  路由仅仅需要两个值,一个页面的url,一个代码地址

· 一个文件夹包含一个组件的相关代码

·  整个系统,只需要写组件,页面(由组件堆砌起来),和路由配置文件即可,开发环境需要一行命令就可以安装完成,配置要几乎为0。

微信小程序和vuePC端有什么不同?

生命周期不同

数据绑定不同

vue动态绑定一个变量的值为元素的某个属性的时候,会在变量前面加上冒号:

小程序绑定某个变量的值为元素属性时,会用两个大括号括起来,如果不加括号,为被认为是字符串

列表渲染

Vue是v-for,小程序是wx:for

显示与隐藏元素

vue中,使用v-if 和v-show控制元素的显示和隐藏

小程序中,使用wx-if和hidden控制元素的显示和隐藏

事件处理

vue:使用v-on:event绑定事件,或者使用@event绑定事件

小程序中,全用bindtap(bind+event),或者catchtap(catch+event)绑定事件

h5怎么在小程序上运行?

使用wx.miniProgram.getEnv api

微信怎么获取蓝牙返回的数据?

使用wx.readBLECharacteristicValue api读取蓝牙低功耗设备特征值的二进制数据。注意:必须设备的特征支持 read 才可以成功调用。

微信怎么获取wifi返回的数据?

使用wx.startWifi api初始化wifi 获取相应信息

vx小程序中如何添加分包加载?

在app.json配置"subpackages"

在pages同级目录新建文件夹以及文件

打包原则

声明 subpackages 后,将按 subpackages 配置路径进行打包,subpackages 配置路径外的目录将被打包到 app(主包) 中

app(主包)也可以有自己的 pages(即最外层的 pages 字段)

subpackage 的根目录不能是另外一个 subpackage 内的子目录

tabBar 页面必须在 app(主包)内

引用原则

packageA 无法 require packageB JS 文件,但可以 require app、自己 package 内的 JS 文件

packageA 无法 import packageB 的 template,但可以 require app、自己 package 内的 template

packageA 无法使用 packageB 的资源,但可以使用 app、自己 package 内的资源

简述就是:

1.首先要配置好打包路径

2.其次subpageage的根目录不能再包含subpageage目录

3.tabBar页面,例如pages/index/index,pages/logs/logs必须在主包内

小程序怎么跳转页面?

 wx.navigateTo保留当前页面,跳转到应用内的某个页面

wx.redirectTo关闭当前页面,跳转到应用内的某个页面

wx.reLaunch关闭所有页面,打开到应用内的某个页面

直接写上navigator 标签,一个属性url里面,就是要跳转到的地址

 wx.navigateBack  delta: 1//默认值是1,返回的页面数,如果 delta 大于现有页面数,则返回到首页

wx.switchTab跳转到TabBar页面

小程序怎么获取值和提取值?

通过e.currentTarget.id获取设置的id值

提取值数据传递前,就已经被设置成全局变量在跳转后的js页面,接收传递过来的数据detail.js同样通过全局额方式取值出来

小程序有哪些参数传值方法?

跨页面传值用navigator标签或wx.navigateTo在url中拼接参数

页面内传值设置id或data-xxx传值

如何解决小程序异步请求?

wx-promise-request 是微信小程序 wx.request 方法的不支持 Promise 和并发数问题的解决方案

wx.request和uni.requeat的区别?

一个是uni-app的请求网络数据方式,一个是微信小程序的请求网络数据方式

uni-app和vue比起来的优势?

 div 改成 view

 span、font 改成 text

 a 改成 navigator

 img 改成 image

 input 还在,但type属性改成了confirmtype

 select改成 picker

 iframe 改成 web-view

 ul、li没有了,都用view替代

 有一些老标签其实还是可以使用的 它在运行的时候会自动转换成新标签  但不推荐这样使用因为这样调试H5端时容易混乱

uniapp自带路由和请求方式

uni.navigateTo 路由与页面跳转
uni.request 网络请求

uniapp上传文件时用到的api是什么?格式是什么?

uni.uploadFile、file

uniapp生命周期?

应用生命周期

  1. onLaunch :当uni-app 初始化完成时触发(全局只触发一次)App.vue里的onLaunch中option作用:获取用户进入小程序或退出小程序的场景值
  2. onShow :当 uni-app 启动,或从后台进入前台显示 //监听用户进入小程序
  3. onHide :当 uni-app 从前台进入后台 //监听用户离开小程序
  4. onError :当 uni-app 报错时触发
  5. onUniNViewMessage :对 nvue 页面发送的数据进行监听

页面生命周期

  1. onLoad (监听页面加载)\
  2. onShow (监听页面显示)\
  3. onReady (监听页面初次渲染完成)\
  4. onHide (监听页面隐藏)
  5. onUnload :监听页面卸载\
  6. onResize :监听窗口尺寸变化\
  7. onPullDownRefresh :监听用户下拉动作,一般用于下拉刷新
  8. onReachBottom :页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据\
  9. onTabItemTap :点击 tabBar 时触发\
  10. onShareAppMessage :用户点击右上角分享
  11. onPageScroll :监听页面滚动
  12. onNavigationBarButtonTap :监听原生标题栏按钮点击事件
  13. onBackPress :监听页面返回
  14. onNavigationBarSearchInputChanged :监听原生标题栏搜索输入框输入内容变化事件
  15. onNavigationBarSearchInputConfirmed :监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发
  16. onNavigationBarSearchInputClicked :监听原生标题栏搜索输入框点击事件

组件生命周期

  1. beforeCreate :在实例初始化之后被调用\

  2. created :在实例创建完成后被立即调用\

  3. beforeMount :在挂载开始之前被调用

  4. mounted :挂载到实例上去之后调用(该钩子在服务器端渲染期间不被调用)

  5. beforeUpdate :数据更新时调用,发生在虚拟 DOM 打补丁之前(该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行)

  6. updated :由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子(该钩子在服务器端渲染期间不被调用。)

  7. beforeDestroy :实例销毁之前调用。在这一步,实例仍然完全可用(该钩子在服务器端渲染期间不被调用。)

  8. destroyed :Vue 实例销毁后调用(该钩子在服务器端渲染期间不被调用。)