面试题

一、宏观

1. 自我介绍

2. 你能说一下你是如何自学前端的

  • 好的。首先前端开发的东西是要跑在浏览器里面的,浏览器只能识别html,css,js的。所以我觉得这三块是我们入行最基础的东西,学好这些之后。然后呢,我在使用JavaScript这些老代码的时候,会有很多问题。我就又去学习了es6。就可以做出一个没有前后端交互,但是有前端效果的静态页面。比如说手写一些轮播图啊什么的。然后又去了解前后端分离,我就又去学习网络,比说说http协议什么的。就可以去做一些前后端分离的项目了。但是在做项目的时候又遇到了一些问题,比如说要经常保存代码,去浏览器刷新;还有很多人配合的时候,css的class类名会冲突,然后js没有模块嘛,就文件加载会有一些问题。为了解决这些问题我就又去学习了一些打包工具,比如说webpack,这个相对于业内来说比较火嘛。但是我对它的了解可能只在使用上,我可以给他配一些,因为我知道webpack只可以处理JavaScript文件嘛,处理其他的文件的话,都要去配一些对应loader嘛。然后接触webpack之后,就可以从一些js的demo变成个比较复杂的项目,可以多人配合,比如说css的命名会拼接一些哈希值来保证它全局的唯一。在工程化这一块完成之后!我们都知道前端可以做一些其他端的事情,比如说把网站塞到一个app里面,比如说用前端来构建小程序这些跨端的能力。我认为这些可能就是一个初级前端重要的比较核心的能力。有了这些能力之后呢,就去探索一些效率的提升,因为之前一个功能可要去封装函数,这样代码就比较臃肿。我就又去了解了比较火的前端框架vue,它会把我们一些底层的事情给做掉,比如说一些实际操作的dom,因为在vue里面他是不建议去使用真实dom去操作的,是基于数据去驱动视图的,我们开发者只需要去关注视图这一层,剩下的事情都去交给框架来做。

3. 上大学的时候有学习过别的语言嘛,你觉得JavaScript和其他语言的区别

  • JavaScript是解释型语言,java是编译型语言

    • 解释性语言:执行时由解释器逐条翻译并执行
    • 编译性语言:执行前先有编译器全部翻译,在执行
    • 编译型语言执行速度快,解释性语言最主要的是安全性

    JavaScript是基于对象,java是面向对象

    JavaScript可在任何浏览器上运行,java需要借助虚拟机实现跨平台

    js的安全性更好,不会读取本地数据

    但是他们都是高级语言,都必须被翻译为机器语言才能执行

4. 假如公司要开发一个新的项目,那项目应该具备什么基础功能

  • 首先我们确立技术选型:

    ​ 首先要确认我们团队人员的技术栈,然后对应技术栈的社区活跃程度,是否有人维护。

    ​ 确立技术方案之后呢,要详细考虑一些功能的实现,比如说vue中使用vue-router来处理路由,使用vuex来管理全局的数据。在项目搭建好之后呢,我们可以先把一些基础的功能搞定,比如要和后端一起确认登录的技术选型,然后可以对我们的请求库进行封装,比如说在全局处理掉 数据的结构啊,全局接口的报错啊,报错的错误提示等。然后再继续考虑,拿后台管理来说,会用到权限管理,比如果不同的管理员登录之后见到的菜单按钮是不同的。把这些确立好模板这些。然后再按照模板进行开发。我大概的理解就是这样。

5. 你的优点/竞争力

  • 暂时还没有实习经验。但是很多技能我愿意去尝试,喜欢去接触新的东西,学习新的技能,就是哪里不会学哪里。平时喜欢在一些网站上看学习视频,比如慕课网,腾讯课堂等去学习自己需要掌握的技能。个人一般有比较好的学习习惯和较好的接受新知识的能力,相信能较快适应所在岗位,如果能够入职的话。

6. 你可以接收加班嘛

  • 我作为这个行业的新人,我认为我自己有很多的不足去弥补和学习,并且我自己也会在工作之余去学习其他的技术,丰富自己的技术栈,我个人觉得加班对于我来说也算是一个比较好的事情,能让我提升自己。

二、CSS

1. 把div居中的几个方法

  • 其实实现水平垂直剧中方法有很多:

    第一种:定位:

    第一种思路:通过给div设置绝对定位,并且left,right,top,bottom设置为0,margin:auto即可以水平垂直居中

    第二种思路:通过给div设置绝对定位,left为50%,top为50%,再给div设置距左是自身的一半即:margin-left:自身宽度/2,margin-top:自身高度/2。

    第三种思路:通过给div设置绝对定位,left为50%,top为50%,再给div设置跨左和跟上是自身的一半:transform:translate3d(-50%,-50%,0)

    第四种:flex布局:

    ​ 思路:有两个div,父级div和子级div,给父级div设置display:flex,并且设置父级div的水平居中justify-content:center,并且给父级div设置垂直居中align-items:center即可

2. css优先级怎么计算的

    • 第一优先级:!important会覆盖页面内任何位置的元素样式
    • 1.内联样式,如style=“float: right”,权值为:1000
    • 2.ID 选择器,如:#app,权值为:0100
    • 3.类、伪类、属性选择器,权值为:0010
    • 4.标签、伪元素选择器,权值为:0001
    • 5.通配符、子类选择器、兄弟选择器。权值为:0000
    • 6.继承的样式,没有权值

3. px、rem、em、%、vw、vh、vm的区别

  • 1、px是什么

    px就是像素,也是我们现在经常使用的基本单位。px就是一张图片最小的一个点,一张位图就是千千万万这样的点构成的,比如常常听到的电脑像素是1024×768的,表示的是水平方向是1024个像素点,垂直方向是768个像素点。使用px时,页面按精准像素展示。

    2、什么是em?

    相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值

    3、什么是rem

    相对单位,可理解为“root em”,相对根节点html(网页)的字体大小来计算,css3新加属性,chrome/firefox/IE9+支持。不会像em那样,依赖于父元素的字体大小,而造成混乱。rem参考物是相对于根元素,我们在使用时可以在根元素设置一个参考值即可。相对于em使用,减少很大运算工作量,例如:html大小为10px,12rem就是120px

    4、什么是%

    一般宽泛的讲是相对于父元素,但是并不是十分准确

    1. 对于普通定位元素就是我们理解的父元素
    2. 对于position:absolute;的元素是相对于已定义的父元素
    3. 对于position:fixed的元素是相对于ViewPort(可视窗口)

    5、什么是vw

    v是viewport,可视窗口的意思。w是width,宽度的意思。视窗宽度

    举个例子:浏览器宽度1200px,1vw = 1200px/100 = 12px

    6、什么是vh

    v是viewport,可视窗口的意思。h是height,宽度的意思。视窗高度

    举个例子:浏览器高度900px,1vh = 900px/100 = 9px

    7、什么是vm

    css3新单位,相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vm

    举个例子:浏览器高度为900px,宽度1200px,取最小的浏览器高度,1vm = 900px/100 = 9px。但是现在vm的兼容性很差。

4. css3有哪些新特性

  • 一、属性选择器

    /* 存在title属性的<a> */
    a[title]{color: blue;
    }/* 存在href属性并且属性值匹配 "https://example.org"的<a> 元素 */
    a[href="https://example.org"]{color: green;
    }/* 存在href属性并且属性值包含"example"的<a> 元素 */
    a[href*="example"]{font-size: 2em;
    }/* 存在href属性并且属性值结尾是".org"的<a> 元素 */
    a[href$=".org"]{font-style:italic;
    }/* 存在class属性并且属性值包含以空格分隔的"logo"的<a>元素 */
    a[class~="logo"] {padding: 2px;
    }
    

    二、border-radius

    三、颜色

    在css 2.1中可以使用:

    • 英文单词
    • 十六进制
    • rgb()函数

    来指定颜色

    在 css 3 中,新增了几个指定颜色的方法:

    • rgba()函数
    • hsl()和hsla()函数
    • opacity属性,用于设置透明度

    在上面的所有特性中,a均指alpha,且alpha指代的就是opacity。

    3.1 rgba

    其实就是 rgb() 函数加了第四参数alpha。实例:

    rgba(255,255,255,.5)/*white with 50% opacity(50%透明度的白色)*/
    rgba(255 255 255 / 0.5);/* css Color 4 space-separated values 同上 */
    

    3.2 hsl

    由于hsla()中的argba()中的a没有差别,所以本部分只写hsl()

    MDN的官方说明如下:

    The hsl() functional notation expresses a given color according to its hue, saturation, and lightness components. An optional alpha component represents the color’s transparency.

    翻译如下(我自己翻的):

    hsl() 函数是用色调(hue)、饱和度(saturation)和亮度(liteness)来表示颜色。额外的alpha参数代表颜色的透明度。

    示例如下:

    /* 示例来自:https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl() */
    hsl(100, 100%, 50%) /* #5f0 */
    hsl(235, 100%, 50%, .5) /* #0015ff with 50% opacity */
    hsl(235 100% 50%); /* CSS Colors 4 space-separated values */
    

    hsl()可加第四参数。加上第四参数后,与hsla()功能相同。

    四、text-shadow

    五、渐变

    六、多背景图片

    七、3D-transform

5. 常用的css优化手段有哪些

  • 加载性能:

    (1)css 压缩:将写好的 css 进行打包压缩,可以减小文件体积。

    (2)css 单一样式:当需要下边距和左边距的时候,很多时候会选择使用 margin:top 0 bottom 0;但 margin-bottom:bottom;margin-left:left;执行效率会更高。

    (3)减少使用@import,建议使用 link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。

    选择器性能:

    (1)关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分)。CSS 选择符是从右到左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等;

    (2)如果规则拥有 ID 选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了)。

    (3)避免使用通配规则,如*{}计算次数惊人,只对需要用到的元素进行选择。

    (4)尽量少的去对标签进行选择,而是用 class。

    (5)尽量少的去使用后代选择器,降低选择器的权重值。后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素。

    (6)了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。

    渲染性能:

    (1)慎重使用高性能属性:浮动、定位。

    (2)尽量减少页面重排、重绘。

    (3)去除空规则:{}。空规则的产生原因一般来说是为了预留样式。去除这些空规则无疑能减少 css 文档体积。

    (4)属性值为 0 时,不加单位。

    (5)属性值为浮动小数 0.**,可以省略小数点之前的 0。

    (6)标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后。

    (7)不使用@import 前缀,它会影响 css 的加载速度。

    (8)选择器优化嵌套,尽量避免层级过深。

    (9)css 雪碧图,同一页面相近部分的小图标,方便使用,减少页面的请求次数,但是同时图片本身会变大,使用时,优劣考虑清楚,再使用。

    (10)正确使用 display 的属性,由于 display 的作用,某些样式组合会无效,徒增样式体积的同时也影响解析性能。

    (11)不滥用 web 字体。对于中文网站来说 WebFonts 可能很陌生,国外却很流行。web fonts 通常体积庞大,而且一些浏览器在下载 web fonts 时会阻塞页面渲染损伤性能。

    可维护性、健壮性:

    (1)将具有相同属性的样式抽离出来,整合并通过 class 在页面中进行使用,提高 css 的可维护性。

    (2)样式与内容分离:将 css 代码定义到外部 css 中。

三、JavaScript

1. JavaScript中的数据类型

  • 六大数据类型

    Number —— 数据类型

    String —— 字符串类型

    Boolean —— 布尔类型 true / false

    Null —— null它是一个空对象

    undefined —— 未定义类型

    Object —— 对象

    分类

    **基本数据类型:**存在栈内存中,赋值时进行的是值传递(number,string,boolean,null,undefined,symbol)

    **引用数据类型:**存在堆内存中,赋值时传递的是地址传递 object → (object,array Date,RegExp)

    栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用的内存消耗

    Symbol(ES6新增数据类型)

      Symbol值是通过Symbol函数生成。这就是说,对象的属性名可以有两种类型:一种是字符串,另一种是Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突
    
    let firstName = Symbol()
    let person = {}
    person[firstName] = "huochai"
    console.log(person[firstName]) // "huochai"
    

    bigint

    js中的Number只能安全的表示-9007199254740991 (-(253-1))和9007199254740991(253-1)之间的整数,任何超出此范围的整数值都可能失去精度。BigInt类型的出现正是为了解决此类问题,要创建Bigint,只需在整数的末尾追加n即可

    console.log(9007199254740995n) // 9007199254740995n
    console.log(9007199254740995)  // 9007199254740996
    

2. JavaScript数组的常用方法

  • es5

    1、push()后增

    push()方法可以向数组后添加一个新的元素,并返回新数组的长度

    var a = [1,2,3]
    var b = a.push(4)console.log(a) // [1,2,3,4]
    console.log(b) // 4
    

    2、unshift()前增

    unshift()可以向数组前增加一个或者多个元素,并返回新的长度

    var a = [2,3,4]
    var b = a.unshift(0,1)console.log(a) // [0,1,2,3,4]
    console.log(b) // 5
    

    3、pop()后删

    pop()用于删除并返回最后一个元素

    var a = [1,2,3]
    var b = a.pop()console.log(a) // [1,2]
    console.log(b) // 3
    

    4、shift()前删

    shift()用于删除并返回首个元素

    var a = [1,2,3]var b = a.shift()console.log(a) // [2,3]console.log(b) //1
    

    5、splice()修改删除

    改变原素组

    splice(index,length,增加的元素1,增加的元素2……,增加的元素N),表示从index开始删除length个元素,并从index开始新增元素1-N,返回被删除的元素组成的数组

    var a = [1,2,3]var b = a.splice(1,1,3,[2,3,4],5)console.log(a) // [1,3,[2,3,4],5,3]console.log(b) // [2]
    

    6、concat()拼接

    合并两个或者多个数组,返回新数组,不会改变原数组

    concat()方法用来合并两个或多个数组

    var a = [1,2,3]var b = [4,5,6]var c = a.concat(b)console.log(c) // [1,2,3,4,5,6]
    

    7、slice()剪切

    slice(startIndex,endIndex)返回从startIndex开始(包括),到endIndex(不包括)之间的元素组成的数组

    返回新数组,不改变原数组

    var a = [1,2,3]var b = a.slice(0,1)// 不填参数则表示剪切整个数组var c = a.slice()console.log(b) // [1]console.log(c) // [1,2,3]
    

    8、join()

    不改变原数组,返回转换后的字符串

    var a = [1,2,3,4,5]console.log(a.join(',')) // 1,2,3,4,5console.log(a) // [1,2,3,4,5]
    

    9、sort()排序

    改变原数组,返回排序后的数组

    var a = ['a','b','d','c']console.log(a.sort()) // ['a','b','c','d']console.log(a) // ['a','b','c','d']
    

    10、reverse()颠倒排序

    返回的是颠倒后的数组,会改变原数组

    var a = [1,2,3,4,5]console.log(a.reverse()) // [5,4,3,2,1]console.log(a) // [5,4,3,2,1]
    

    11、indexOf()和astIndexOf()

    indexOf(某数组,startIndex) 从startIndex开始,查找某元素在数组中的位置,若存在,则返回第一个位置的下标,否则返回-1

    astIndexOf(某元素,startIndex) 和indexOf()相同,区别在于从尾部向首部查询

    **不会改变原数组,返回找到的index,否则返回-1

    若不适用下标,则一般通过includes()方法代替indexOf()

    var a = [1,2,4,3,4,5]console.log(a.indexOf(4)) // 2console.log(a.indexOf(4,3))  // 4
    

    12、filter()过滤

    filter()方法返回数组中满足条件的元素组成的新数组,原数组不变

    filter()的参数是一个方法

    var a = [1,2,3,4,11]// 第一个参数为一个方法,有三个参数,current:当前值 index:当前值下标 array:这个数组对象var b = a.filter(function(current,index,array){    return current < 10})console.log(b) // [1,2,3,4]console.log(a) // [1,2,3,4,11]
    

    13、map()格式化数组

    map()方法来根据需求格式化原数组,返回格式化后的数组。原数组不变

    var a = [1,2,3,4,5]// 参数同filter方法var b = a.map((current,index,array) => {    return current + 1})console.log(b) // [2,3,4,5,6]console.log(a) // [1,2,3,4,5]
    

    14、every()

    对数组的每一项都运行给定的函数,若每一项都返回true,则返回true

    var a = [1,2,3,4,5]var b = a.every((current,index,array) => {    return current < 6})var c = a.every((current,index,array) => {    return current < 3})console.log(b) // trueconsole.log(c) // false
    

    15、some()

    对数组的每一项都运行给定的函数,若存在一项或多项返回ture,则返回ture

    var a = [1,2,3,4,5]var b = a.some((current,index,array) => {    return current > 4})var c = a.some((current,index,array) => {    return current > 5})console.log(b) // trueconsole.log(c) // false
    

    16、forEach()数组遍历

    var arr = ['a','b','c']var copy = []arr.foEach(item => {    copy.push(item)})console.log(copy)
    

    es6

    1、find()

    找到数组中第一次满足条件的元素,并返回,若找不到则返回undefined。不改变原数组。

    和filter()方法的区别在于:filter返回值是所有满足条件的元素组成的数组,

    一般在需要使用找到的元素时,用find()方法

    2、findIndex()

    findIndex()的作用同indexOf(),返回第一个满足条件的下标,并停止寻找。

    区别是findIndex() 的参数为一个回调函数,且一般用于对象数组

    3、includes()

    includes()方法,返回一个布尔值。 参数是一个value,一般用于简单数组。

    对于复杂数组,则可以使用some()方法替代includes()方法

    4、Array.isArray()

    判断是不是一个数组

3. apply、call、bind区别

    • 三者都可以改变函数的this对象指向
    • 三者第一个参数都是this要指向的对象,如果没有这个参数或者参数为undefined或null,则默认指向全局window
    • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入
    • bind 是返回绑定this之后的函数,便于稍后调用;apply、call则是立即执行
    • bind() 会返回一个新的函数,如果这个返回的新的函数作为构造函数创建一个新的对象,那么此时this不在指向传入bind的第一个参数,而是指向用new创建的实例

4. 你能说下什么是深拷贝,什么是浅拷贝

    • 浅拷贝:浅拷贝就是直接把一个对象的地址赋值给另外一个对象中,其中一个对象中的值改变另外一个对象的值也会改变
    • 深拷贝:深拷贝就是在队中在开辟一块空间存放,两个对象在栈中存放的地址不一样两个对象互不影响

5. 实现一个深拷贝

    1. 利用JSON.parse()和JSON.steringify()来完成一个深拷贝
    2. 遍历内容把内容赋值给一个新的

6. var、let和const的区别

  • 1. let、const、var的区别

    (1)块级作用域: 块级作用域由 { } 包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:

    • 内层变量可能覆盖外层变量
    • 用来计数的循环变量泄露为全局变量

    **(2)变量提升:**var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否则会报错

    **(3)给全局添加属性:**浏览器的全局对象是window,node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。

    (4)重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的变量。const和let不允许重复声明变量。

    (5)暂时性死区: 在使用let、const命令声明变量之前,该变量都是不可用的。在语法上,成为暂时性死区。使用var声明的变量不存在暂时性死区。

    (6)初始值设置: 在声明变量时,var和let可以不用设置初始值,。而const声明的常量必须设置初始值。

    (7)指针指向: let和const都是ES6新增的用于创建变量的语法。let创建的变量时可以改变指针指向(可以重新赋值)。但是const声明的变量时不允许改变指针指向的。

    区别 var let const
    是否有块级作用域 ✔️ ✔️
    是否存在变量提升 ✔️
    是否添加全局属性 ✔️
    能否重复声明变量 ✔️
    是否存在暂时性死区 ✔️ ✔️
    是否必须设置初始值 ✔️
    能否改变指针指向 ✔️ ✔️

7. es6新特性

    • let、const
    • 模板字符串
    • 解构赋值
    • 扩展运算符
    • 字符串的扩展方法(includes, startsWith, endsWith, padStart, padEnd, repeat, replaceAll, trimStart, trimEnd…)
    • 数组的扩展方法(includes, isArray, from, fill, find, findIndex…)
    • 箭头函数
    • 函数的rest参数,函数参数的默认值
    • Symbol
    • Reflect
    • Proxy
    • Promise
    • Generator
    • Map
    • WeakMap
    • Set
    • WeakSet
    • class
    • import & export

    Symbol

    • Symbol 除了表示独一无二的值
    • 还具有元编程的能力,比如我们手写 Promise 的时候,如果不定义 Symbol.toStringTag 为 Symbol,那么通过 Object.prototype.toString.call 得到的结果就是 [object Object]
    • 还可以用于判断某对象是否为某构造器的实例 Symbol.hasInstance,很多人手写 instanceof 的时候都是通过 proto 的方式,这在 ES5 是没问题的,然而在 ES6 是通过 Symbol.hasInstance

    Reflect

    Reflect 将对象的操作集中起来,可以通过 Reflect. 的方式来使用,比如:

    • Reflect.ownKeys 可以获取对象的普通属性和Symbol类型的属性,如果不使用 Reflect.ownKeys() ,就要使用 Object.keys() 和 Object.getOwnPropertySymbols 将获取到的普通类型的属性和 Symbol 类型的属性拼接起来
    • Reflect.has 可以判断一个对象是否存在某个属性,如果不用 Reflect.has 就要使用 key in object

8. 什么是异步

9. promise是什么

  • Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息,他的出现大大改善了异步编程的困境,避免了地狱回调,它比传统的解决方案回调函数和事件更合理和更强大。

    所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

    (1)Promise的实例有三个状态:

    • Pending(进行中)
    • Resolved(已完成)
    • Rejected(已拒绝)

    当把一件事情交给promise时,它的状态就是Pending,任务完成了状态就变成了Resolved、没有完成失败了就变成了Rejected。

    (2)Promise的实例有两个过程

    • pending -> fulfilled : Resolved(已完成)
    • pending -> rejected:Rejected(已拒绝)

    注意:一旦从进行状态变成为其他状态就永远不能更改状态了。

    Promise的特点:

    • 对象的状态不受外界影响。promise对象代表一个异步操作,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是promise这个名字的由来——“承诺”;
    • 一旦状态改变就不会再变,任何时候都可以得到这个结果。promise对象的状态改变,只有两种可能:从pending变为fulfilled,从pending变为rejected。这时就称为resolved(已定型)。如果改变已经发生了,你再对promise对象添加回调函数,也会立即得到这个结果。这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的。

    Promise的缺点:

    • 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
    • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
    • 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

    总结:

    Promise 对象是异步编程的一种解决方案,最早由社区提出。Promise 是一个构造函数,接收一个函数作为参数,返回一个 Promise 实例。一个 Promise 实例有三种状态,分别是pending、resolved 和 rejected,分别代表了进行中、已成功和已失败。实例的状态只能由 pending 转变 resolved 或者rejected 状态,并且状态一经改变,就凝固了,无法再被改变了。

    状态的改变是通过 resolve() 和 reject() 函数来实现的,可以在异步操作结束后调用这两个函数改变 Promise 实例的状态,它的原型上定义了一个 then 方法,使用这

10. promise.all api是啥

  • **(1)**Promise.all

    Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值

    Promise.all中传入的是数组,返回的也是是数组,并且会将进行映射,传入的promise对象返回的值是按照顺序在数组中排列的,但是注意的是他们执行的顺序并不是按照顺序的,除非可迭代对象为空。

    需要注意,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,这样当遇到发送多个请求并根据请求顺序获取和使用数据的场景,就可以使用Promise.all来解决。

    (2)Promise.race

    顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。当要做一件事,超过多长时间就不做了,可以用这个方法来解决:

    Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
    

11. map set是啥,有什么区别

  • 3. map和weakMap的区别—了解即可

    (1)Map

    map本质上就是键值对的集合,但是普通的Object中的键值对中的键只能是字符串。而ES6提供的Map数据结构类似于对象,但是它的键不限制范围,可以是任意类型,是一种更加完善的Hash结构。如果Map的键是一个原始数据类型,只要两个键严格相同,就视为是同一个键。

    实际上Map是一个数组,它的每一个数据也都是一个数组,其形式如下:

    const map = [  ["name","张三"],  ["age",18],]
    

    Map数据结构有以下操作方法:

    • sizemap.size 返回Map结构的成员总数。
    • set(key,value):设置键名key对应的键值value,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。(因为返回的是当前Map对象,所以可以链式调用)
    • get(key):该方法读取key对应的键值,如果找不到key,返回undefined。
    • has(key):该方法返回一个布尔值,表示某个键是否在当前Map对象中。
    • delete(key):该方法删除某个键,返回true,如果删除失败,返回false。
    • clear():map.clear()清除所有成员,没有返回值。

    Map结构原生提供是三个遍历器生成函数和一个遍历方法

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器。
    • forEach():遍历Map的所有成员。
    const map = new Map([     ["foo",1],     ["bar",2],])for(let key of map.keys()){    console.log(key);  // foo bar}for(let value of map.values()){     console.log(value); // 1 2}for(let items of map.entries()){    console.log(items);  // ["foo",1]  ["bar",2]}map.forEach( (value,key,map) => {     console.log(key,value); // foo 1    bar 2})
    

    (2)WeakMap

    WeakMap 对象也是一组键值对的集合,其中的键是弱引用的。其键必须是对象,原始数据类型不能作为key值,而值可以是任意的。

    该对象也有以下几种方法:

    • set(key,value):设置键名key对应的键值value,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。(因为返回的是当前Map对象,所以可以链式调用)
    • get(key):该方法读取key对应的键值,如果找不到key,返回undefined。
    • has(key):该方法返回一个布尔值,表示某个键是否在当前Map对象中。
    • delete(key):该方法删除某个键,返回true,如果删除失败,返回false。

    其clear()方法已经被弃用,所以可以通过创建一个空的WeakMap并替换原对象来实现清除。

    WeakMap的设计目的在于,有时想在某个对象上面存放一些数据,但是这会形成对于这个对象的引用。一旦不再需要这两个对象,就必须手动删除这个引用,否则垃圾回收机制就不会释放对象占用的内存。

    而WeakMap的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用

    总结:

    • Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
    • WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。但是 WeakMap 只接受对象作为键名( null 除外),不接受其他类型的值作为键名。而且 WeakMap 的键名所指向的对象,不计入垃圾回收机制。

12. 那weakMap weakSet呢

13. 原型链

  • 1. 对原型、原型链的理解

    在JavaScript中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该能够获取到这个值的,但是现在浏览器中都实现了 proto 属性来访问这个属性,但是最好不要使用这个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原型。

    当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就是新建的对象为什么能够使用 toString() 等方法的原因。

    **特点:**JavaScript 对象是通过引用来传递的,创建的每个新对象实体中并没有一份属于自己的原型副本。当修改原型时,与之相关的对象也会继承这一改变。

14. 什么是闭包 你能例举一些闭包的场景么

  • (1)闭包

    答:闭包说的通俗一点就是打通了一条在函数外部访问函数内部作用域的通道。正常情况下函数外部是访问不到函数内部作用域变量的,

    表象判断是不是闭包:函数嵌套函数,内部函数被return 内部函数调用外层函数的局部变量

    ​ 优点:可以隔离作用域,不造成全局污染

    缺点:由于闭包长期驻留内存,则长期这样会导致内存泄露

    如何解决内存泄露:将暴露全外部的闭包变量置为null

    适用场景:封装组件,for循环和定时器结合使用,for循环和dom事件结合.可以在性能优化的过程中,节流防抖函数的使用,导航栏获取下标的使用

15. js实现异步的操作有哪些

  • 利用setTimout实现异步
    使用Promise对象
    动态创建script标签
    利用script标签提供的async
    还有ES6里面async函数,使得异步操作变得更加方便

16. 谈谈this是什么,this代表什么

  • this是Javascript语言的一个关键字。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。

四、计算机网络和浏览器原理

1. HTTP和HTTPS的区别

  • 一、HTTP协议

    1、什么是HTTP

    • "http" ,又被称为超文本传输协议,是互联网上应用最为广泛的一种网络协议。

    • 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。

    • 是用于从万维网服务器传输超文本到本地浏览器的传送协会。

    • 基于TCP的应用层协议,它不关心数据传输的细节,HTTP是一个基于 请求 与 响应模式的、无状态的、应用层协议,只有遵循统一的HTTP请求格式,服务器才能正确解析客户端发的请求,同样地,服务器遵循统一的响应格式,服务器才得以正确解析不同网站发过来的响应

    2、HTTP请求内容

    HTTP 请求由请求行、请求头、空行、请求体组成

    • **请求行:**请求方法 + URL ++ 协议版本

    3、HTTP响应内容

    HTTP响应格式与请求的格式相似,也是由响应行、响应头、空行、响应体组成

    • **响应行:**HTTP 版本号 + 响应状态码 + 状态说明
    • **响应头:**响应头与请求头对应,是服务器对该响应的一些附加说明
    • **响应体:**他才是真正的响应数据,这些数据其实就是网页的HTML源代码

    4、HTTP的缺点

    缺少安全性,http协议信息传输是通过明文的方式传输,不做任何加密,容易被中间人恶意篡改

    二、HTTPS协议

    1、什么是HTTPS协议

    • HTTPS 的全称是(Hypertext Transfer Protocol Secure),它是用来在计算机网络上的两个端系统之间进行 安全的交换信息 ,它相当于在HTTP的基础上加了一个Secure安全的字眼
    • HTTPS是在一个计算机世界里专门在两点之间安全的传输文字、图片、音频、视频等超文本数据的约定和规范
    • HTTPS是HTTP协议的一种扩展,它本身并不保证传输的安全性,在HTTPS中,使用 传输层安全性(TLS)或 安全套接字层(SSL)对通信协议进行加密
    • HTTP + SSL(TLS) = HTTPS

    2、HTTPS做了什么

    • 加密,HTTPS通过对数据加密来使其免受窃听者对数据的监听
    • 数据一致性,数据在传输的过程中不会被窃听者锁修改,用户发送的数据会完整的传输到服务端
    • 身份认证,是指确认对方的真是身份

    除了协议名和默认端口号外,HTTPS协议在语法,语义上和HTTP一样,关键在于这个s也就是SSL/TLS

    三、HTTPS解决了HTTP的什么问题

    由于HTTP天生明文传输的特性,在HTTP的传输过程中,任何人都可能从中截取、修改或者伪造请求发送,所以可以认为HTTP是不安全的;

    • 在HTTP的传输过程中不会验证通信方的身份,因此HTTP信息交换的双方可能会遭到伪装,也就是没有用户验证;

    • 在HTTP的传输过程中,接收方和发送方并不会验证报文的完整性

    四、什么是SSL/TLS

    TLSSSL 的后续版本,他们是用于在互联网两台计算机之间用于身份验证和加密的一种协议

    SSL 是一个独立的协议,不只有 HTTP 可以使用,其他应用层协议也可以使用,比如 SMTP(电子邮件协议)、Telnet(远程登录协议) 等都可以使用。

    TLS 用于两个通信应用程序之间提供保密性和数据完整性。TLS 由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术

2. HTTP状态码

  • 状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值:

    • 1xx:指示信息——般表示请求已接收,继续处理。
    • 2xx:成功——表示已经成功被接收、理解、接收。
    • 3xx:重定向——要完成请求必须进行更进一步的操作。
    • 4xx:客户端错误——请求有语法错误或请求无法实现。
    • 5xx:服务器端错误——服务器未能实现合法的请求。

    常见的状态码

    • 200(成功):请求成功,通常服务器提供了需要的资源

    • 204(无内容):服务器成功处理了请求,但没有返回任何内容

    • 301(永久移动):请求的网页已经移动到新的位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新的位置。

    • 302(临时移动):服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

    • 304(未修改):自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容

    • 400(错误请求):服务器不理解请求的语法(一般为参数错误)。

    • 401(未授权):请求要求身份验证。对于需要登录的网页,服务器可能返回此响应。

    • 403(禁止):服务器拒绝请求。(一般为客户端的用户权限不够)

    • 404(未找到):服务器找不到请求的网页

    • 422(无法处理):请求格式正确,但是由于含有语义错误,无法响应

    • 500(服务器内部错误):服务器遇到错误,无法完成请求

3. 从一个URL地址到浏览器完成渲染的整个过程

    1. 浏览器地址输入URL并回车
    2. 浏览器查找当前URL是否存在缓存,并比较缓存是否过期
    3. DNS解析URL对应的IP
    4. 根据ip建立TCP连接(三次握手)
    5. 发送http请求
    6. 服务器处理请求,浏览器接收HTTP响应
    7. 浏览器解析并渲染页面
    8. 关闭TCP连接

4. GET和POST的区别

  • 这里主要展示 POST 和GET 的区别

    • GET在浏览器回退时是无害的,而POST会再次提交请求。
    • GET产生的URL地址可以被Bookmark,而POST不可以。
    • GET请求会被浏览器主动cache,而POST不会,除非手动设置
    • GET请求只能进行url编码,而POST支持多种编码方式。
    • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
    • GET请求在URL中传送的参数是有长度限制的,而POST没有
    • 对参数的数据类型,GET只接收ASCII字符,而POST没有限制
    • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
    • GET参数通过URL传递,POST放在Request body中

    重点区别: GET 会产生一个TCP数据包,而POST会产生两个TCP数据包。

    • 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200
    • 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器在发送data,服务器响应200

5. ajax状态码

  • 在AJAX实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是:
    0 - (未初始化)还没有调用send()方法
    1 - (载入)已调用send()方法,正在发送请求
    2 - (载入完成)send()方法执行完成,
    3 - (交互)正在解析响应内容
    4 - (完成)响应内容解析完成,可以在客户端调用了
    对于上面的状态,其中“0”状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用“4”进行判断

6. cookie和session区别

  • cookie和session的区别

    cookie

    Cookie是访问某些网站以后在本地存储的一些网站相关的信息

    Cookie中一般包括如下主要内容:

    1. key:设置的cookie的key
    2. value:key对应的value
    3. max_age/expire_time:设置cookie的过期时间
    4. domain:该cookie在哪个域名中有效。一般设置子域名,比如cms.example.com。
    5. path:该cookie在哪个路径下有效

    例如:我们登录某一个网站时需要输入用户名和密码,如果用户名和密码保存为cookie,则下次我们登录该网站的时候就不需要在输入用户密码了

    session

    session是存在服务器的一种李永来存放用户数据的类HashTable结构。

    浏览器第一次发送请求时,服务器自动生成了—HashTable和—SessionID来唯一标识这个HashTabe,并将其通过响应发送到浏览器。浏览器第二次发送请求会将前一次服务器响应中的SessionID放在请求中一并发送到浏览器上,服务器从请求中提取出sessionID,并和保存的所有sessionID进行对比,找到这个用户对应的HashTable。

    例如:我们浏览一个购物网站,用户将部分商品添加到购物车中,许久以前许多网站都是用服务端session存储购物车内容(现在基本都是用数据库了),就用到了session存储这部分信息。

    区别:

    1. 存储位置不同

    • cookie的数据信息存放在本地。
    • session的数据信息存放在服务器上

    2. 存储容量大小不同

    • cookie存储的容量较小,一般 <= 4kb
    • session存储容量大小没有限制(但是为了服务器性能考虑,一般不能存放太多数据)。

    3. 存储有效期不同

    • cookie可以长期存储,只要不超过设置的过期时间,可以一直存储
    • session在超过一定的操作时间(通常为30分钟)后会失效,但是当关闭浏览器时,为了保护用户信息,会自动调用session.invalidate()方法,该方法会清除掉session中的信息

    4. 安全性不同

    • cookie存储在客户端,所以可以分析存放在本地的cookie并进行cookie欺骗,安全性较低。
    • session存储在服务器上,不存在敏感信息泄露的风险,安全性比较高。

    5. 域支持范围不同

    • cookie支持跨域名访问。例如:所有a.com的cookie在a.com下都能用。
    • session不支持跨域访问。例如:www.a.com的session在api.a.com下不能用

    6. 对服务器压力不同

    • cookie保存在客户端,不占用服务器资源
    • session是保存在服务器端,每个用户都会产生一个session,session过多的时候会消耗服务器资源,所以大型网站会有专门的session服务器

    7. 存储的数据类型不同

    • cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据
    • session中能够存储任何类型的数据,包括且不限于string,integer,list,map等

五、webpack

1. Plugin和loader的区别

2. 你用过webpack哪些插件

六、vue

1. 为什么data是一个函数

  • 当一个组件被定义,data必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例,如果data仍然是一个纯粹的对象,则所有的实例将共享引用的同一个对象!通过提供data函数,每次创建一个新实例后,我们能够调用data函数,从而返回初始数据的一个全新副本数据对象。

2. 能说一下vue的生命周期嘛

vue的生命周期就是,vue实例创建到销毁的过程。即指从创建、初始化数据、编译模板、挂载Dom到渲染、更新到渲染、销毁等一系列过程。它主要分为8个阶段:创建前后、载入前后、更新前后、销毁前、销毁后,以及一些特殊场景的生命周期:

  • beforeCreate:组件实例被创建之初
  • created:组件实例已经完全创建
  • beforeMount:组件挂载之前
  • mounted:组件挂载到实例上去之后
  • beforeUpdate:组件数据发生变化,更新之前
  • updated:数据更新之后
  • beforeDestroy:组件实例销毁之前
  • destroyed:组件实例销毁之后
  • activated:keep-alive缓存的组件激活时
  • deactivated:keep-alive缓存的组件停用时调用
  • errorCaptured:捕获一个来自子孙组件的错误时被调用
生命周期 描述
beforeCreate 执行时组件实例还未创建,通常用于插件开发中执行一些初始任务
created 组件初始化完毕,各种数据可以使用,常用与异步数据获取
beforeMount 未执行渲染、更新,dom未创建
mounted 初始化结束,dom已创建,可用于获取访问数据和dom元素
beforeUpdate 更新前,可用于获取更新前各种状态
updated 更新后,所有状态已是最新
beforeDestroy 销毁前,可用于一些定时器或订阅的取消
destroyed 销毁后

在获取数据时,在created和mouted的区别

  • created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成
  • mouted是在页面dom节点渲染完毕之后就立刻执行的,created的触发时机要比mounted更早一些

3. 父子组件或者兄弟组件之间的传值

    • 父子组件:

      • 使用 props 接收值,使用$emit发送
    • 子父组件:

      • 父亲写事件函数,子$emit触发 传值父使用对应的事件名接收
    • 兄弟传值:

      • $bus中转站,就是在写一个js里边new一个vue的实例两个子组件都导入这个js文件
      • 如果组件之间关系很远,是很多组件都要用到的值使用vuex

    vuex 就是一个全局状态数据管理

4. 介绍一下vue router

  • vue路由钩子是在路由跳转过程中拦截当前路由和要跳转的路由的信息,有三种路由钩子:

    第一种:全局路由钩子 beforeEach(to,from,next) { }

    第二种:路由独享的钩子

    ​ beforeEnter(to,from,next) {

    ​ }

    第三种:组件内的钩子

    beforeRouteEnter(to,from,next) {

    //…

    }

    beforeRouteUpdate(to,from,next) {

    //…

    }

    beforeRouteLeave(to,from,next) {

    //…

    }

    适用场景:动态设置页面标题,判断用户登录权限等:代码示例:

    //全局路由导航守卫

    vueRouter.beforeEach(function (to, from, next) {

    const nextRoute = [ ‘detail’];

    const auth = sessionStorage.getItem(“username”);

    let FROMPATH = from.path;

    //跳转至上述3个页面

    if (nextRoute.indexOf(to.name) >= 0) {

    ​ //上述数组中的路径,是相当于有权限的页面,访问数组列表中的页面就应该是在登陆状态下

    ​ if (!auth) {

    ​ let params = Object.assign({frompath:FROMPATH},from.query);

    ​ next({path: ‘/newlogin’,query:params});

    ​ }

    }

    //已登录的情况再去登录页,跳转至首页

    if (to.name === ‘newlogin’) {

    ​ if (auth) {

    // vueRouter.push({name: ‘index’});

    ​ next({path: ‘/’});

    ​ }

    }

    next();

    });

5. 介绍一下vuex

  • 答:vuex是一个状态管理工具,主要解决大中型复杂项目的数据共享问题,主要包括state,actions,mutations,getters和modules 5个要素,主要流程:组件通过dispatch到 actions,actions是异步操作,再actions中通过commit到mutations,mutations再通过逻辑操作改变state,从而同步到组件,更新其数据状态,而getters相当于组件的计算属性对,组件中获取到的数据做提前处理的.再说到辅助函数的作用.

6. 可以说一下spa共享数据的方式么

    • inndb

7. 遇到过刷新页面 vuex数据丢失么 改如何解决

  • (1)vuex如何实现数据持久化(即刷新后数据还保留)?

    答:因为vuex中的state是存储在内存中的,一刷新就没了,例如登录状态,解决方案有:

    第一种:利用H5的本地存储(localStorage,sessionStorage)

    第二种:利用第三方封装好的插件,例如:vuex-persistedstate

    第三种:使用vue-cookie插件来做存储

    第四种:第四种:可以把数据传递到后台,存储到数据库中,***比较耗费资源

8. 能简单描述一下vue的核心原理么

  • 当一个Vue实例创建时,Vue会遍历data中的属性,用 Object.defineProperty(vue3.0使用proxy )将它们转为 getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

9. 了解vue3么,有使用过么,和vue2有什么变化

  • (1)监测机制的改变

    • 3.0 将带来基于代理 Proxy的 observer 实现,提供全语言覆盖的反应性跟踪。
    • 消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:

    (2)只能监测属性,不能监测对象

    • 检测属性的添加和删除;
    • 检测数组索引和长度的变更;
    • 支持 Map、Set、WeakMap 和 WeakSet。

    (3)模板

    • 作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。
    • 同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。

    (4)对象式的组件声明方式

    • vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。
    • 3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易

    (5)其它方面的更改

    • 支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。
    • 支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。
    • 基于 tree shaking 优化,提供了更多的内置功能。

七、react

1. vue和react的区别

八、小程序

1. 小程序是什么

2. 小程序和普通的h5有什么区别

九、node.js

1. nodejs和js有什么区别

2. 你开发中用到了哪些node提供的能力

十、性能优化

1. cdn是啥

  • 访问离你最近的服务器拿文件,没有的话最近的服务器会去原始服务器拿数据,并做一个缓存当用户再次访问最近的服务器会直接拿到缓存。速度会快上很多。

    CDN是内容分发网络,尽可能避开互联网上有可能影响数据传出速度和稳定性的瓶颈和环节,使传输内容更快、更稳定。CDN只是对某个具体的域名的加速。

    CDN访问的过程(有印象):

    1. 当用户点击网站页面上的URL内容,经过本地DNS解析,会将域名的解析权交给CNAME指向的CDN专用DNS服务器。
    2. CDN的DNS服务器将CDN的全局均衡设备IP地址返回给用户
    3. 用户向CDN的全局负载均衡设备发起请求
    4. CDN全局均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域均衡设备,并将请求转发到这台设备。
    5. 区域负载均衡设备根据用户IP、请求的URL为用户选择一台 合适的缓存服务器提供内容。
    6. 全局负载均衡设备把服务器的IP返回给用户
    7. 用户向CDN缓存服务器发起请求,
    8. 缓存服务器响应用户请求,将用户所需内容传送到用户终端。

2. 如何减小包的体积

  • 1.路由懒加载

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xkva1hZK-1637683910573)(file:///C:/Users/21521/AppData/Local/Temp/msohtmlclip1/01/clip_image002.gif)]

    2.开启Gzip压缩

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cGaeRu4W-1637683910574)(file:///C:/Users/21521/AppData/Local/Temp/msohtmlclip1/01/clip_image004.gif)]

    \3. 使用webpack的externals属性把不需要打包的库文件分离出去,减少打包后文件的大小

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhU81akp-1637683910576)(file:///C:/Users/21521/AppData/Local/Temp/msohtmlclip1/01/clip_image006.gif)]

    \4. 使用vue的服务端渲染(SSR)

3. spa,mpa是啥,各自有啥优点和缺点

  • 概念:

    • SPA单页面应用(SinglePage Web Application),指只有一个主页面的应用,一开始只需要加载一次js、css等相关资源。所有内容都包含在主页面,对每一个功能模块组件化。单页应用跳转,就是切换相关组件,仅仅刷新局部资源。
    • MPA多页面应用 (MultiPage Application),指有多个独立页面的应用,每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。

    区别:

4. script标签中defer async属性的使用

5. dns预解析

6. 分包

7. http缓存在这个场景如何使用

8、回流和重绘

  • 回流

    当Render Tree中部分或全部元素的尺寸、结构、或某些属性发送改变时,浏览器重新渲染部分或全部文档的过程称为回流。

    会导致回流的操作

    • 页面首次渲染
    • 浏览器窗口大小发生改变
    • 元素尺寸或位置发生改变
    • 元素内容变化(文字数量或图片大小等等)
    • 元素字体大小变化
    • 添加或者删除可见的DOM元素
    • 激活CSS伪类
    • 查询某些属性或调用某些方法 eg:clientWidth、clientHeight、clientTop、clientLeft`

    重绘

    当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、backgrond-color等),浏览器会将新样式赋予给元素并重新描绘它,这个过程称为重绘。

    优化:

    CSS

    • 避免使用table布局
    • 尽可能在DOM树的最末端改变class
    • 避免设置多层内联样式
    • 将动画效果应用到position属性为absolute或fixed的元素上
    • 避免使用css表达式(例如:calc())

    JavaScript:

    • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性
    • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有的DOM操作,最后再把它添加到文档中。
    • 也可以先为元素设置display:none,操作结束后再把它显示出来,因为disolay属性为none的元素上进行DOM操作不会引发回流和重绘。
    • 避免频繁读取会引发回流/重绘的属性,如果要多次使用,就用一个变量缓存起来。
    • 对具有复杂动画的元素使用绝对定位,试它脱离文档流,否则会引起父元素以及后续元素频繁回流

对虚拟dom的理解

  • 我大体说下对虚拟dom的理解吧,正是virtual(喂车额奥) DOM这一个特性,让现代这些流行的框架,能够性能更高,才得以市场率占有这么高的.比方说,vue react 阿瓦隆.这些框架都是虚拟dom的.

    在传统的jq中,操作的都是真实的DOM,.而一个真实dom的渲染过程,要经过渲染引擎构建DOM树.构建样式表.组建成render(渲染)树,的过程,要经过不断的重绘回流才能够展示给用户.

    那么在直接js操作dom的过程中,比方说一个循环10次插入dom元素,其实每一次都会经历上面的过程…经历大量的重绘回流.代价特别大.性能低下.所以出现了虚拟dom

    虚拟dom其实就是提前使用js的方式表示出dom结构树来.存储在内存里面.同样的循环.只会最终合并执行一次,大大的提高了性能.(这个地方有点儿像js中的createElementFragment文档碎片)

    而在对比的过程中.通过diff算法进行比较差异.这个比较在我理解而言就是**同层比较.**降低了时间复杂度空间复杂度一些什么玩意儿.最终把差异同步到真实dom上去.这就是我理解的虚拟dom

初级前端面试题最新汇总相关推荐

  1. 前端面试题整理汇总(一)

    前端面试题整理汇总(一) 优才网 关于前端面试题,优优之前推荐过,如下,点击即可查看: 5个经典的前端面试问题 2016年十家知名公司前端面试经验总结 前端面试会问哪些问题? 前端开发面试题汇总[HT ...

  2. 前端面试题vue-element汇总

    [Vue-element] [vue-element] ElementUI是怎么做表单验证的?在循环里对每个input验证怎么做呢? [vue-element] 你有二次封装过ElementUI组件吗 ...

  3. 2017年前端面试题最新汇总

    再来更新一篇面试题 早前我更新过一篇 <前端面试题>,据反馈,确实帮助到了不少去面试的新人或者换工作的菜鸟 他们留言或者直接赞赏表示感谢,还有问答案的,不过我想说:我就是不给你答案,自有原 ...

  4. HTML和CSS初级前端面试题汇总(持续补充)

    1.浏览器内核 IE:trident Firefox:gecko Safari:webkit Opera:以前是presto,现在是Blink Chrome:Blink 2.HTML文件开头的DOCT ...

  5. 2016年11月前端面试题整理汇总

    一些开放性题目 1.自我介绍:除了基本个人信息以外,面试官更想听的是你与众不同的地方和你的优势.2.项目介绍3.如何看待前端开发?4.平时是如何学习前端开发的?5.未来三到五年的规划是怎样的? pos ...

  6. 前端面试题整理汇总100题

    1.一些开放性题目 1.自我介绍:除了基本个人信息以外,面试官更想听的是你与众不同的地方和你的优势.2.项目介绍3.如何看待前端开发?4.平时是如何学习前端开发的?5.未来三到五年的规划是怎样的? p ...

  7. HTML5CSS3上-动画 转换 新特性 前端面试题部分汇总

    HTML5 CSS3 HTML5 CSS3相关面试题 HTML5新特性 CSS3 新特性 列举 5 个以上的 H5 事件 微信小程序与 H5 的区别 H5 的浏览器存储有哪些? 简述 transfor ...

  8. 初级前端面试题 - js

    前言:众所周知,HTML,CSS,JS是学习前端所必备的.js的基础学好了,框架类的vue,react等都会接受的很快,因此js是前端很总要的一个部分,这篇文章将会结合面试题,对js的知识点进行总结 ...

  9. 2020年 前端面试题整理汇总100题【整理】

    1.一些开放性题目 1.自我介绍:除了基本个人信息以外,面试官更想听的是你与众不同的地方和你的优势.2.项目介绍3.如何看待前端开发?4.平时是如何学习前端开发的?5.未来三到五年的规划是怎样的? p ...

最新文章

  1. [欧拉路]CF1152E Neko and Flashback
  2. 迅为linux下串口,迅为iMX6UL开发板多路串口开发板接口详解
  3. 捞人宝估值数亿,已捞出数位大佬,商业模式已验证!
  4. adapter 适配器
  5. 浅析Windows计算机中丢失SETUPAPI.dll的问题
  6. oracle数据库索引介绍,SQL Server和Oracle数据库索引介绍
  7. 如何高效和快乐的学习RS和GIS知识
  8. win10计算机桌面天气,win10电脑桌面显示时间和天气日期怎么设置
  9. matlab 模拟电磁学时域有限差分法,MATLAB模拟的电磁学时域有限差分法
  10. ab plc软件_回收拆厂拆机设备废旧设备PLC触摸屏自动化设备回收【cpu吧】
  11. journalctl
  12. how-to-solve-the-specific-problem,learn-this,imitate-this
  13. Excel必知必会——count,counta,countif,countifs
  14. JavaWeb - 小米商城网 - 项目启动
  15. echarts tooltip属性加背景图片
  16. 技术总结--android篇(四)--工具类总结
  17. Linux ip forward转发问题总结
  18. 滴滴云 远程访问jupyter
  19. 【图像识别-指纹识别】指纹特征提取附matlab代码
  20. transforms.ToTensor()与transforms.Normalize()函数解析

热门文章

  1. 全屏游戏中自动切出到桌面的问题解决(二)
  2. Python:处理yaml格式的数据太简单了,真怕你学会了
  3. datatables 合并单元格(rowspan)
  4. 【C++ 包装器类 map】C++ 标准库(std)中的map结构 哈希表(unordered_map)和黑红树(map)教程
  5. 2020生产实习——信诺达的
  6. Linux pgrep检索当前正在运行的进程
  7. itext实现图片等比缩小放大转pdf
  8. iPhone怎么设置铃声 iPhone铃声设置详细教程
  9. if or函数套用_IF函数还可以这样用!IF(AND)(OR)混合多条件判断
  10. 驱动中动态创建设备号、设备节点