面试题

310 阅读21分钟

html

css

js

ES6新增了哪些特性

  • const、let关键字
  • map、set数据类型
  • 模板字符串
  • 对象数组解构赋值
  • 函数剩余参数(...arg)
  • 延展运算符(...)
  • 函数默认参数(fn(name='zs'))
  • 对象字面量的增强(属性名和属性值相同,可缺省)
  • Promise异步对象
  • class类的支持

模板字符串

用一对反引号标识,可以当作普通字符串使用,也可以用来定义多行字符串,也可以在字符串中嵌入变量、js表达式或函数,需要写在${}

箭头函数

是一种简洁的函数写法,当函数体中只有一个表达式时,{}和return都可以省略,当函数体中形参只有一个时,()可以省略。

箭头函数的this始终指向箭头函数定义时离this最近的一个函数,如果没有最近的函数就指向window

解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值

数组的解构赋值

数组中的值会自动被解析到对应接收该值的变量中,数组的解构赋值要一一对应,如果对应不上的就是undefined

可以通过解构赋值来快速交换两个变量的值

对象的解构赋值

对象的解构与数组有一个重要的不同,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

还可以通过冒号指定别名,也可以同时指定默认值

作用域

就是变量和函数的有效范围。

在ES6之前,ES的作用域只有两种:全局作用域和函数作用域。ES6时支持了块级作用域。

分类:全局作用域、局部作用域、块级作用域

全局作用域

其中的变量和函数在任何地方都能被访问,其生命周期伴随着页面生命周期

函数作用域

在函数内部定义的变量和函数,只能在函数内部被访问,函数执行结束后,函数内部定义的变量就会被销毁 在函数内部访问变量,优先找局部变量和形参,如果没有,则去定义该函数的环境中查找,直到全局为止

块级作用域

就是使用一个大括号{}包裹的一段代码,比如函数、判断语句、循环语句等,单独的一个{}都可以是一个块级作用域

什么是预解析

概念

JS代码在执行之前,解析引擎会对代码进行一个预先的检查,主要会对变量和函数的声明进行提升,将变量和函数的声明提到代码的最前面。通过var关键字声明的变量和通过function关键字声明的函数会被提前声明。

预解析之后,代码才会从上往下依次执行,但是预解析执行过的代码不会重复执行

函数声明提升的特点:在函数声明的前面,可以调用这个函数

注意

预解析时遇到重复的变量声明,会被忽略掉

遇到重复的函数声明,会保留后面声明的函数

遇到变量与函数重名的情况,会保留函数

什么是闭包,有什么作用,使用时需要注意什么?

闭包的概念

闭包是一个跟函数相关的概念,表现形式就是一个父函数内部,嵌套了一个子函数,子函数直接或间接的被返回给外部作用域,并且子函数会使用到父函数局部作用域中的变量。当我们在外部调用这个子函数时,就会发生闭包现象。

闭包的作用

闭包可以延展一个函数的作用域

注意

不能滥用闭包,会导致内存泄漏

什么是内存泄漏,哪些操作会引起内存泄漏?

什么是内存泄漏

本应该被垃圾回收机制回收的内存空间由于某种特殊原因没有被及时回收,称为内存泄漏

哪些操作会引起内存泄漏

滥用全局变量和滥用闭包都会导致内存泄漏

使用let声明的变量和var声明的变量有什么区别

let:使用let声明的变量有块级作用域,并且没有变量的声明提升(使用let声明的变量在声明之前调用会报语法错误)。

var:使用var声明的变量没有块级作用域,有声明提升(在声明之前调用会报undefined)

谈谈对Promise的理解

Promise是JS中专门用来存储异步代码的对象。是异步编程的一种解决方案,将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

它有三种状态,分别是 pending-进行中resolved-已完成rejected-已失败

Promise对象本身并没有提供任何的代码逻辑,他只是帮助我们改造和优化传统的使用回调函数实现的异步操作。最显著的一个特点是Prmise可以解决传统的回调地狱。代码层面Promise提供了一个构造函数,通过new关键字创建Promise实例,创建实例时需要传入一个匿名函数,匿名函数中需要有两个参数,resolve和reject,resolve是成功处理函数,reject是失败处理函数,什么时候触发这两个函数需要由具体的业务逻辑来决定,这两个函数需要通过Promise实例对象提供的then方法进行传递。

Promise还提供了两个静态方法,all方法和race方法,all方法可以一次执行多个Promise实例,返回的一个数组,只有所有Promise实例成功时才成功,只要有一个失败就直接失败。race方法也可以一次执行多个promise实例,第一个完成的Promise实例的结果状态就是最终的结果状态。

谈谈async/await的使用方式和场景

async是用来修饰函数的声明,使用async修饰的函数会变成一个异步函数。

await是来修饰函数的调用,使用await修饰的函数必须返回一个Promise对象,使用await修饰后,就会将Promise异步对象转换为同步操作

async一般是和await一起使用的

常见的HTTP状态码都有哪些

主要是五大类:

  • 1开头,1xx:信息响应类,表示接收到请求并且继续处理
  • 2开头,2xx:处理成功响应类,表示动作被成功接收
  • 3开头,3xx:重定向响应类,为了完成指定动作,必须接受进一步处理
  • 4开头,4xx:客户端错误,客户请求包含语法错误或是不能正常执行
  • 5开头,5xx:服务端错误,服务器不能正确执行一个正确的请求
状态码解释
100正在初始化(一般是看不到的)
101正在切换协议(websocket浏览器提供的)
200(或以2开头)代表响应主题的内容已成功返回
202表示接受
301永久重定向/永久转移
302临时重定向/临时转移(一般用来做服务器负载均衡)
304本次获取的内容是读取缓存的数据,会每次去服务器校验
400参数出现错误(客户端传递给服务器端的参数出现错误)
401未认证,没有登录网站
403禁止访问,没有权限
404客户端访问的地址不存在
500未知的服务器错误
503服务器超负荷(假设一台服务器只能承受10000人,当第10001个人访问的时候,如果没有做负载均衡,那么这个人的网络状态码就是503)
504(网关超时)服务器作为网关或代理,但是没有及时从上游服务器收到请求

http请求方式有哪些

方式作用
GET请求指定的页面信息,并返回实体主题
POST向指定资源提交数据(例提交表单或上传文件),数据被包含在请求体中。POST请求可能会导致新的资源的创建或已有资源的修改
PUT从客户端向服务器传送的数据取代指定的文档的内容
DELETE请求服务器删除指定的页面
HEAD类似于get请求,只不过返回的响应体中没有具体的内容,用于获取报头
TRACE回显服务器收到的请求,主要用于测试或诊断
OPTIONS允许客户端查看服务器的性能
CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
PATCH实体中包含一个表,表中说明与该url所表示的原内容的区别
MOVE请求服务器将指定的页面移至另一个网络地址
COPY请求服务器将指定的页面拷贝至另一个网络地址
LINK请求服务器建立链接关系
UNLINK断开链接关系
WRAPPED允许客户端发送经过封装的请求
LOCK允许用户锁定资源,比如可以在编辑某个资源时,将其锁定,以防别人同时对其进行编辑
MKCOL允许用户创建资源
Extension-mothed在不改动协议的前提下,可增加另外的方法

AJAX请求数据的步骤是什么?

  1. 通过XMLHttpRequest构造函数创建一个异步对象xhr

  2. 创建一个新的http请求,并指定该http请求的方法、url及验证信息

  3. 设置响应http请求状态变化的函数(xhr身上的onreadystatechange属性绑定事件函数)

  4. 发送http请求 send()方法

  5. 获取异步调用返回的数据

补充

readystate 是 xhr对象中的一个属性,表示状态,有五个值:0 1 2 3 4

0 表示未初始化,最开始readystate属性值就是0;1 表示open方法已经调用完毕;2 表示send方法已经调用完毕;3表示服务端返回的部分的结果;4表示服务端返回的所有结果

  • 0: XMLHttpRequest对象创建完成。——还没有调用open()方法
  • 1: XMLHttpRequest对象初始化完成。——已调用send()方法,正在发送请求
  • 2: 请求已经发送——send()方法完成,已经收到全部响应 内容
  • 3: 服务器返回了数据(但是还没有被解析,可能只一段http报文)——正在解析响应内容
  • 4: 数据解析完成——响应内容解析完成,可以在客户端调用了

性能优化

什么是页面的回流和重绘

回流

指当页面的结构或尺寸发生变化时,浏览器需要对页面进行重排,并重新渲染

重绘

当页面的标签的外观(比如字体颜色、背景颜色)发生改变时,浏览器需要重新对页面进行渲染

区别

回流是结构改变,重绘是样式改变结构。所以回流一定会引起重绘,重绘不一定会引起回流。

要提高页面性能,就要尽可能的减少页面的回流和重绘

针对页面性能优化,有哪些优化方案

资源加载方面

减少http请求次数。具体方案:代码合并、使用精灵图

减少http请求数据量。具体方案:代码压缩,合理设置缓存

启用CDN加速服务

代码层面

避免滥用全局变量、滥用闭包,

减少作用域查找(能用局部变量就不要用全局变量)

减少DOM操作,操作DOM的时候对已经查找到的DOM对象进行缓存,避免重复查找

使用图片懒加载,避免单次加载图片数量过多导致页面卡顿

script标签写在页面底部,因为js代码的加载会阻塞页面的渲染

不要在本地书写大量cookie,因为cookie会伴随每一次http请求

什么是CDN加速

CDN(Content Delivery Network)全称内容分发网络,是运营商所提供的一项增值服务,花钱就可以拥有这项加速服务。

原理:CDN系统能够实时的根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。

作用:CDN主要对网站的静态资源进行加速,CDN在全国会有很多个节点服务器(每个城市都有),当购买了一个CDN服务后,CDN服务会对你的网站的静态资源文件进行缓存处理,当第二次有人访问时,服务器就会从就近的CDN节点服务器上获取网站所需的静态资源。

由于CDN服务的性能比较高,并且距离客户端的物理距离比较近,所以就可以实现加速

启用CDN服务只需要在运营提供商提供的后台进行配置(配置要对哪个域名启用CDN服务),不需要对代码做任何修改

缓存(304缓存)

缓存:其实就是想减少服务器的访问次数

分为两类:强制缓存、协商缓存

强制缓存

Expires 响应头参数,表示过期时间。这个响应头就告诉我们这个资源要强制缓存

cache-control 响应头参数,有很多个值。常见的:private、public、no-cache、max-age、no-store等。Cache-Control优先级比Expires高。

private:

协商缓存

cache-control设置为no-cache就是不强制缓存

  1. Last-Modify / if-Modify-Since

Last-Modify:一个时间标识该资源的最后修改时间。(响应头)

if-Modify-Since:上次响应头last-Modify的时间。(请求头)

浏览器第一次请求一个资源时,服务器返回的Header中会加上Last-Modify字段,一个时间标识该资源的最后修改时间。

当浏览器再次请求该资源时,请求头中要包含if-Modify-Since字段,该字段的值就是上次响应头last-Modify的时间。服务器根据浏览器传递过来的修改时间与最后修改时间判断是否命中缓存,若完全相等则命中缓存,返回304状态码,浏览器去缓存中取资源;若不相同,则返回200状态码和最新资源

  1. ETag / if-None-Math

ETag字段(响应头):web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。是资源文件对应的hash值。ETag的生成会加大服务器的开销,影响服务器性能,

if-None-Math字段(请求头):发现资源具有ETag声明,则再次向web服务器请求时需要带上if-None-Match字段,值为上次ETag的hash值。服务器收到后再次计算资源文件的hash值与浏览器返回的值作比较,相同则资源文件没有改变,服务器返回304状态码;否则返回200状态码,重新发送完整最新资源文件。

vue

谈谈对vue中插槽的理解

vue中的插槽分为三种:匿名插槽、具名插槽、作用域插槽

作用:通过插槽可以动态指定某一组件中模板部分的渲染。当我们调用组件时,在组件的调用标签中间传递标签结构,那么该组件就会将我们传递的标签结构放在他的模板部分进行渲染

vue中如何实现给样式添加作用域?说明其实现原理

方法

vue中给样式添加作用域,只需要给style标签添加scoped属性即可

原理

添加scoped属性的style标签内部会被改写成一个交集选择器,会在原来类名的基础上添加一个随机属性,同时引用该类名的标签也会添加一个相同的属性,这样的话,这个类名可以对引用它的标签生效,同时不会影响其他同类名的标签。

什么是vuex,在哪种场景下使用

vuex是vue的一种状态管理工具,分为几个核心部分:

  • satate:存储状态数据
  • mutations:更新数据的方法
  • actions:调用mutations中的方法,更新state的数据
  • getters:对state中的数据进行预处理

当组件关系比较复杂时,可以使用vuex简化组件间的传值。

vuex的状态存储是响应式的,当vue组件从store中读取数据状态时,若store中的状态发生改变,那么相应的组件中的状态也会发生改变。

不能直接改变store中的状态

谈谈MVC、MVP、MVVM

它们的目标都是解耦,提升代码可维护性、可读性和复用性

好处

MVC

全称:model-view-controller(模型-视图-控制器)

介绍

用于应用程序的分层开发,主要作用是将业务逻辑和用户界面分离。model层是数据模型,提供要展示的数据等。view层是视图层,主要进行页面展示。controller是控制器,负责控制具体的业务逻辑,处理用户的输入,并将model数据层的数据交给view视图层进行展示。

MVP

全称:model-view-presenter(模型-视图-展示器)

介绍

5.jpg

MVVM

全称:model-view-viewmodel

是mvc的改进版。

  • model:数据层
  • view:视图层
  • viewmodel:视图模型层

介绍

是一种框架设计的思想,vue就是基于MVVM来设计的,其中model负责初始化数据,可以在model中定义数据修改和操作的业务逻辑;view负责页面展示,viewmodel是通过双向数据绑定把view层和model层连接了起来。

view和model之间并没有直接的联系,而是通过viewmodel层进行交互。

model和viewmodel之间的交互是双向的,所以view数据的变化会立即同步到model中,同时model中数据的变化也会立即反应到view中。

4.jpg

MVC和MVVM的区别

自适应和响应式

都是用于创建在不同屏幕大小和设备类型上都能良好呈现网站和应用程序的方法,只是在实现方式和灵活性等方面上存在一些差别

响应式

一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。即同一页面在不同的屏幕上有不同的布局,即只需要一套代码使页面适应不同的屏幕。为不同终端的用户提供更加舒适的界面和更好的用户体验。

目的:程序代码被动的去适应屏幕的宽度变化,能够在不同屏幕大小和设备上自动调整布局和样式。

方法:通过使用CSS媒体查询流式布局等技术,使用相对单位(如百分比,rem,em),使页面元素能够根据屏幕大小自动伸缩调整布局

自适应

目的:程序代码主动的去根据不同的屏幕大小实现不同的布局和样式。通过不同屏幕大小和设备创建多个固定布局,并根据用户的设备类型来选择加载适合的布局

对比

灵活性

  • 响应式设计更灵活一点,能够适应各种屏幕大小和设备类型;
  • 而自适应设计较为固定,需要创建多个固定布局来适应不同屏幕大小和设备类型

开发复杂性

  • 响应式在开发中需要考虑不同屏幕大小和设备类型的适应性,使用媒体查询等技术,需要较多的css代码

  • 自适应开发中需要创建多个固定布局,并通过检测用户设备类型来选择使用哪种布局,需要较多html和css代码

用户体验

  • 响应式通常能够提供较好的用户体验,因为页面会根据屏幕大小自动调整布局和样式,能适应不同设备的用户

  • 自适应能够在某些设备上提供很好的用户体验,因为它是为特定设备类型创建的特定的布局和样式

小程序

什么是分包,分包的好处

分包

把一个完整的小程序项目按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载

好处

  • 优化小程序首次启动的加载时间
  • 多团队共同开发时,可以更好的解耦协作

分包前项目构成

小程序项目中所有页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动时间

分包后

小程序项目由1个主包+多个分包组成

  • 主包:一般只包含项目的启动页面或TabBar页面、以及所有分包都需要用到的一些公共资源
  • 分包:只包含当前分包有关的页面和私有资源

分包的体积限制

  • 整个小程序所有分包大小不超过16M(主包+所有分包)
  • 单个分包/主包大小不能超过2M

分包的加载规则

  • 小程序启动时,默认会下载主包并且启动主包内页面
    • TabBar页面需要放到主包中
  • 当用户进入到分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
    • 非TabBar页面可以按照功能的不同,划分为不同的分包后,进行按需下载

使用分包

app.json中的subpackages节点中声明分包的结构

打包原则

  • 小程序会按subpackages的配置进行分包,subpackages之外的目录将被打包到主包中
  • 主包也可以有自己的pages(最外层的pages字段)
  • batBar页面必须在主包内
  • 分包之间不能互相嵌套

引用原则

  • 主包无法引用分包内的私有资源
  • 分包之间不能相互引用私有资源
  • 分包可以引用主包内的公共资源

独立分包

概念

本质上也是分包,只不过它可以独立于主包和分包而单独运行

独立分包与普通分包的区别

最主要区别:是否依赖于主包才能运行

普通分包必须依赖于主包才能运行

独立分包可以在不下载主包的情况下独立运行

应用场景

将某些具有一定特定功能独立性的页面配置到独立分包中,原因:

  • 当小程序从普通的分包页面启动时,需要首先下载主包
  • 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度

注意:一个小程序可以有多个独立分包

独立分包配置方法

通过在分包配置中的independent节点,为true时则为独立分包,没有则为普通分包

引用原则

独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源

  • 主包无法引用独立分包内的私有资源
  • 独立分包之间,不能相互引用资源
  • 独立分包和普通分包之间,不能相互引用资源
  • 特别注意 独立分包中不能引用主包内的公共资源

分包预下载

指的是:在进入小程序的某个页面时,由框架自动下载可能需要的分包,从而提示进入后续分包页面时的启动速度

配置分包预下载

预下载分包的行为,会在进入指定的页面时触发。在app.json中,使用preloadRule节点定义分包的预下载规则

限制

同一个分包中的页面享有共同的预下载大小限额2M