2022春招Web前端高频面试题(自用,附答案)

文章目录

JS数据类型

JS 数据类型一共有 7 种,分为基本数据类型和引用数据类型:

基本数据类型:字符串(String)、数字 (Number)、布尔 (Boolean)、空(Null)、未定义(Undefined)、Symbol、BigInt。

Symbol:ES6 引入了一种新的原始数据类型,表示独一无二的值,主要用于解决属性名冲突的问题,做为标记

BigInt:是 ES2020 新增加的,在对大整数执行数据运算时,使用 BigInt会减少整数溢出问题

引用数据类型:对象 (Object),其中包含了日期(Date)、函数(Function)、数组(Array)、正则(RegExp)等

两者总结区别:

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

基本:存储在栈中的简单数据段,它们的值直接存储在变量访问的位置

原因:基本类型数据占据的空间是固定的,所以将他们存储在较小的内存区域 —— 栈,便于迅速查寻变量的值

引用:存储在堆中的对象,存储在变量处的值是一个指针,指向存储对象的内存地址

原因:引用类型数据的大小会改变,不能把它放在栈中,否则会降低变量查寻速度,相反,地址的大小是固定的,可以存在栈中

2)复制变量时的不同

基本:变量复制时,会将原始值的副本赋值给新变量,此后两变量是完全独立的,他们只是拥有相同的值而已(深拷贝)

引用:变量复制时,会把内存地址赋值给新变量,新旧变量都指向了堆内存中的同一个对象,任何一个作出的改变都会影响另一个(浅拷贝)

null 和 undefined 的区别?

null 是一个表示” 无” 的对象,转为数值时为 0

undefined 是一个表示” 无” 的原始值,转为数值时为 NaN

undefined 表示此处应该有一个值,但是还没有定义。

典型用法是:

(1)变量被声明了,但没有赋值时,就等于 undefined。

(2) 调用函数时,应该提供的参数没有提供,该参数等于 undefined。

(3)对象没有赋值的属性,该属性的值为 undefined。

(4)函数没有返回值时,默认返回 undefined。

null 表示” 没有对象”,即该处不应该有值。

典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象。

(2) 作为对象原型链的终点。

数据类型判断方法

typeof:一般用来判断基本数据类型

typeof 目前能返回 string,number,boolean,symbol,bigint,unfined,object,function 这八种判断类型

对于 null ,返回 object 类型。对于引用类型,除 function 返回 function 类型,一律返回 object 类型。

instanceof:一般用来判断引用数据类型的判断

instanceof 主要的作用就是判断一个实例是否属于某种类型

是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true, 否则返回 false。 instanceof 检测的是原型。

其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。

Object.prototype.toString.call(这个是判断类型最准的方法)

如何实现 copy 一个数组

扩展运算符(浅拷贝)

numbers = [1, 2, 3];
numbersCopy = [...numbers];

Array.slice(浅拷贝)

// 当不给定参数时,就返回了原数组的拷贝
numbers = [1, 2, 3, 4, 5];
numbersCopy = numbers.slice();
// [1, 2, 3, 4, 5]

Array.concat(浅拷贝)

//不指定参数或者提供一个空数组作为参数,就可以进行浅拷贝
[1, 2, 3].concat(); // [1, 2, 3]
[1, 2, 3].concat([]); // [1, 2, 3]

JSON.parse & JSON.stringify(深拷贝)

JSON.stringify 将一个对象转成字符串;JSON.parse 将转成的字符串转回对象。

将它们组合起来可以将对象转换成字符串,然后反转这个过程来创建一个全新的数据结构。

深拷贝和浅拷贝在内存上的区别

深拷贝与浅拷贝简单区分方法:假设 B 复制了 A,当修改 A 时,B 是否改变,若 B 也跟着变化,说明是浅拷贝;若 B 没变化,则是深拷贝

注意:一般情况下,深拷贝只针对较为复杂的 object 类型数据

基本数据类型:名与值都存储在栈内存中

当修改 a 时,对 b 并不会造成影响,因为此时的 b 具有独立的存储空间,不受 a 的影响了

引用数据类型:名存在栈内存中,值存在于堆内存中,栈内存会提供一个引用的地址指向堆内存中的值

当 b=a 时,其实 b 复制了 a 的引用地址,而并非堆内存中的值,而当 a [0]=1 时进行数组修改时,由于 a 与 b 指向的是同一个地址,自然 b 也受影响,这就是所谓的浅拷贝。

JQuery 和 Vue 的区别和各自的优点

JQuery偏重于对 DOM 的操作,经常要考虑怎么去渲染数据,怎么从视图中取到数据,操作数据前必须对 dom 节点

进行选取修改赋值等操作,分散了本该放在业务逻辑上的精力。

而 Vue 则是基于 MVVM 思想,数据驱动,双向绑定,只需要定义好渲染规则,如果数据发生改变,vue 会帮我们重

新渲染整个页面,所以我们只需将注意力放在数据操作上就可以了。

请问定位布局 position 属性有哪些取值?

1. 相对定位 relative

  • 不会使元素脱离文档流(原本位置会被保留,即改变位置也不会占用新位置)

  • 相对于自身原本位置移动(没有定位偏移量则对元素无影响)

  • 不影响元素本身特性(无论块级元素或行内元素,保留其原本特性)

  • 常用于提升层级,从而改变元素覆盖关系,若两个都为定位元素,后面的会覆盖前面

    2. 绝对定位 absolute

  • 使元素完全脱离文档流(在文档流中不再占原来位置)

  • 相对于最近一个有定位的父元素进行偏移,如果不存在就逐级向上排查,直到相对于 body 元素,即相对于浏览器窗口(必须有参照物)

  • 子绝父相,一般配合相对定位使用,(将父元素设置相对定位,子元素相对于父元素偏移)

  • 可提升层级

    3. 固定定位 fixed

  • 直接相对于浏览器窗口进行 “绝对定位”

  • 浮动在页面中,元素位置不会随浏览器窗口滚动条滚动而变化

  • 不会受文档流动影响

    4. 粘性定位 sticky

  • 基于用户的滚动来定位,在相对定位与绝对定位两者间切换。滚动前相当于 position:relative,当页面滚动超出目标区域时,相当于 position:fixed,会将元素固定在目标位置

  • 相对于离它最近的具有滚动框的父级元素,如果父级元素都不可以滚动,那相对于浏览器窗口计算偏移量

  • 如 top: 50px,在 sticky 元素到达距离相对定位的元素顶部 50px 的位置时固定,无论怎么滚动,都不再向上移动

  • 兼容性不好,如 Internet Explorer, Edge 15 及更早 IE 版本不支持 sticky 定位,通常需要结合 CSS3 兼容方案

    5. 静态定位 static

  • 默认定位,遵循正常的文档流

  • 元素不会受到影响

    6. 继承值 inherit

  • 从父元素继承 position 属性值

请问你了解浮动布局 float 属性吗

浮动布局:为方便页面设计,给元素设置 float 属性,将元素脱离文档流,浮动框进行左右移动,直至外边缘遇到包含框或者另一个浮动框边缘,再通过 margin 属性调整位置,float 属性可取 3 个值:left:左浮动、right:右浮动、none:不浮动(默认)

浮动的影响:

  • 改变块级元素的排列方式,内容从上下排列显示变成水平排列显示
  • 浮动元素会脱离文档流,不占位,盒子重叠,内容不重叠
  • 浮动的块级元素的宽度由内容撑开,行内元素可设宽高、margin 和 padding 均有效,可理解为隐式转换为 inline-block 元素

【延伸考点】

浮动布局最常产生什么问题?

通常父级盒子不设置高度时,高度将由内容或子元素撑开,当子元素浮动脱离文档流后, 父盒子就会出现高度塌陷,边框变成一条线,通常需要清除浮动来解决该问题

盒模型

包括内容区域、内边距区域、边框区域和外边距区域。

box-sizing: content-box(W3C 盒子模型):元素的宽高大小表现为内容的大小。

box-sizing: border-box(IE 盒子模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿。IE5.x 和 IE6 在怪异模式中使用非标准的盒子模型,这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。

请问 BFC 布局有哪些特点、触发条件以及实际应用

BFC(Block Formatting Context):格式化上下文,也称 BFC 布局,是 Web 页面中盒模型布局的 CSS 渲染模式,指一个独立的渲染区域,与其他元素隔离,不受外部布局影响

BFC 布局特点:

  • 在 BFC 区域内,内部盒子会在垂直方向上一个接一个地放置
  • 属于同一个 BFC 的两个相邻盒子的上下 margin 会发生重叠
  • 同一个 BFC 区域内,设置了 float 属性的盒子不会重叠
  • 计算 BFC 的高度时,区域内的浮动元素也参与计算

BFC 布局触发条件(满足任意一个即可形成 BFC):

  • 根元素
  • 浮动元素:float 不为 none
  • 绝对定位元素:position(absolute、fixed)
  • display 为 inline-block、flex
  • overflow :hidden

BFC 布局实际应用:

  • 清除浮动,通过设置 overflow:hidden 解决父元素坍塌问题
  • 垂直 margin 合并,BFC 区域内两个相邻元素的垂直外边距会发生叠加,叠加后的外边距为两者外边距的最大值。这样可保持各区域间上下间距一致,比如多个段落之间与顶部底部的边距保持一致
  • 防止垂直 margin 合并,反之可以在元素外层包裹一层容器,并触发该容器生成一个新的 BFC 布局,与相邻元素隔离开来
  • 实现自适应双栏、三栏布局,利用浮动、定位、Flex 布局原理可实现多种自适应布局

CSS 选择器以及优先级

  • !important

  • 内联样式(1000

  • ID 选择器(0100

  • 类选择器 / 属性选择器 / 伪类选择器(0010

  • 元素选择器 / 伪元素选择器(0001

  • 关系选择器 / 通配符选择器(0000

说一下原型链,原型对象

  • 原型:
    • 概念:在构造函数创建的时候,系统默认的帮构造函数创建并关联一个对象 这个对象就是原型
    • 作用:在原型中的所有属性和方法,都可以被和其关联的构造函数创建出来的所有的对象共享
    • 特点:JavaScript 对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变
  • 原型链:
    • 构造函数以及 js 原生 Object 对象之间的原型关系
    • 当一个对象调用的属性 / 方法自身不存在时,就会去自己 [__proto__] 关联的前辈 prototype 对象上去找
    • 如果没找到,就会去该 prototype 原型 [__proto__] 关联的前辈 prototype 去找。依次类推,直到找到属性 / 方法或 undefined 为止。从而形成了所谓的 “原型链”

无论何时,我们创建的每一个函数都有一个 prototype 属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。

prototype 就是通过该构造函数创建的某个实例的原型对象,但是其实 prototype 是每个构造函数的属性而已,只能说万物皆对象罢了。

原型对象的优点是:所有的对象实例都可以共享它包含的属性和方法。这一点可以在构造函数里就可以看出来,因为构造函数在函数里面就定义了对象的实例信息,而原型对象可以在任何地方定义属性和方法。

this指向

this 的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定 this 到底指向谁,实际上 this 的最终指向的是那个调用它的对象

如果一个函数中有 this,但是它没有被上一级的对象所调用,那么 this 指向的就是 window

如果一个函数中有 this,这个函数有被上一级的对象所调用,那么 this 指向的就是上一级的对象。

如果一个函数中有 this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this 指向的也只是它上一级的对象

有 return 时,如果返回值是一个对象,那么 this 指向的就是那个返回的对象,如果返回值不是一个对象那么 this 还是指向函数的实例。

call apply bind 区别/ 改变 this 指向的方法

共同点:都能用于改变 this 绑定。第一个参数都为改变 this 的指针。若第一参数为 null/undefined,this 默认指向

window第一个参数都为改变 this 的指针。

apply 与 call:都可以自动执行,但是参数传递方式不同。

call:接受一个参数列表,可以自动执行

apply:第二个参数被包裹在一个数组中,可以自动执行

bind:接受一个参数列表,不会自动执行,需要手动调用,返回值为一个新的函数

call、bind 与 apply 区别:前两个都有无数个参数,apply 只有两个参数,而且第二个参数为数组

详细说一下闭包和箭头函数,闭包和箭头函数分别解决了什么问题?

函数嵌套函数当内部函数访问外部函数变量时就产生了闭包

闭包的两个作用:

一个是内部函数可以直接访问外部函数的变量或参数

另一个是让这些变量的值始终保持在内存中,不会被垃圾回收机制回收。

使用闭包的注意点:

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。将调用闭包的属性或者函数指向 null。

箭头函数相当于匿名函数,并且简化了函数定义。

箭头函数中的 this 始终指向父级上下文,即定义时的 this,而不是执行时的 this。

call () /apply () /bind () 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响

箭头函数不可以当作构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误。

箭头函数不可以使用 arguments 对象,该对象在函数体内不存在。可以用展开运算符… 解决,arguments 是参数的集合, 是一个类数组 / 伪数组体现在他不能调用数组的方法

箭头函数没有 prototype 属性

HTML5 新特性

HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。

拖拽释放 (Drag and drop) API

语义化更好的内容标签(header,nav,footer,aside,article,section)

音频、视频 API (audio,video)

画布 (Canvas) API

地理 (Geolocation) API

本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;

sessionStorage 的数据在浏览器关闭后自动删除

表单控件,calendar、date、time、email、url、search

新的技术 webworker, websocket, Geolocation

移除的元素

纯表现的元素:basefont,big,center,font, s,strike,tt,u;

对可用性产生负面影响的元素:frame,frameset,noframes;

CSS3新特性

CSS3 选择器

  • nth 选择器

:first-child/last-child

选择属于父元素的首个 / 最后一个子元素的每个 element 元素,注意 element 为子元素。

:nth-child(n)

选择某元素下的第 n 个 element 元素(n 是一个简单的表达式,不能用其他的字母代替),括号里还可以传 odd 和 even 两个关键字

:nth-last-child(n)

匹配属于某元素下的第 n 个 element 子元素,从最后一个子元素开始计数

:nth-of-type(n)

匹配属于父元素的特定类型的第 n 个子元素,element 为指定类型的子元素

:nth-last-of-type

匹配属于父元素的特定类型的第 n 个子元素,从最后一个计数

:first-of-type/:last-of-type

匹配属于其父元素的特定类型的首个 / 最后一个子元素的每个元素

:only-child

匹配属于父元素的唯一子元素的每个元素

:only-of-type

匹配属于其父元素特定类型的唯一子元素的每个元素

:empty

匹配没有子元素(包括文本节点)的每个元素

  • 否定选择器:not

定义:匹配非元素或者选择器的每个元素

语法:父元素:not (子元素或者选择器)

例:ul:not (span){}

  • 伪元素 (也可以使用:)

element::first-line

定义:对元素的第一行文本进行设置,只能用于块级元素

element::first-letter

定义:用于向文本的首字母设置特殊样式,只能用于块级元素

element::before

定义:在元素的内容前面插入新内容,常与 content 配合使用

element::after

定义:在元素的内容后面插入新内容,常与 content 配合使用

element::selection

定义:用于设置浏览器中选中文本后的背景色与前景色

CSS3 边框与圆角

圆角 border-radius

定义:可以为元素添加圆角边框(块元素,行内块元素,行内元素)

属性:

border-top-left-radius 左上角

border-top-right-radius 右上角

border-bottom-right-radius 右下角

border-bottom-left-radius 左下角

盒阴影 box-shadow

定义:可以控制一个或多个下拉阴影的框

语法:box-shadow: 水平方向的偏移量 垂直方向的偏移量 模糊程度 扩展程度 颜色 是否具有内阴影

CSS3 背景与渐变

background-image

backgroundimage:url('1.jpg‘),url('2.jpg')

注意:元素引入多个背景图片,前面图片会覆盖后面的图片

background-cilp

定义:指定背景的绘制区域(裁剪)

background-cilp:border-box / padding-box / content-box
border-box:背景被裁剪到边框盒(从边框开始绘制背景图片)---默认
padding-box:背景被裁剪到内边距框(从内边距开始绘制背景图片)
content-box:背景被裁剪到内容框

background-origin

定义:设置背景图像的原始起始位置

background-origin:border-box / padding-box / content-box(背景图片坐标原点与这三个有关系)
border-box:相对于边框来定位
padding-box:相对于内边距来定位
content-box:相对于内容框来定位
background-position:定义背景图片的位置,水平与垂直方向上面的偏移量(参考点)

background-repeat

定义:设置是否及如何重复背景图像,默认地,背景图像在水平和垂直方向上重复。

repeat 默认。背景图像将在垂直方向和水平方向重复。
repeat-x 背景图像将在水平方向重复。
repeat-y 背景图像将在垂直方向重复。
no-repeat 背景图像将仅显示一次。
inherit 规定应该从父元素继承 background-repeat 属性的设置

background-size

定义:指定背景图像的大小

background-size:number / % / cover / contain

属性介绍:

number: 宽度 高度(如果只写一个数值,第二个数值默认auto)
百分比: 0% - 100% 之间的任何值,此时的百分比参照于元素div的大小
cover:将背景图片等比缩放以填满整个容器(最远边),如果高度达到一定比例100%,宽度多出的会溢出,但是,具体那部分溢出取决于定位
contain:将背景图片等比缩放至某一边紧贴容器边缘为止(最近边),如果图片高度比较小,高度就会有空白区域出现

线性渐变

定义:是沿着一根轴线改变颜色,从起点到终点进行顺序渐变(从一边拉向另一边)

语法:background:linear-gradient(方向,开始颜色,结束颜色)

径向渐变

定义:从起点到终点,颜色从内向外进行圆形渐变

语法:background:radial-gradient (形状尺寸,开始颜色,结束颜色)

CSS3 过渡

定义:允许 css 的属性值在一定时间区间内平滑的过渡,在鼠标点击,鼠标滑过或对元素任何改变中触发,并圆滑地以动画形式改变 css 的属性值。

transition-property 属性

定义:设置对象中的参与过渡的属性

语法:transition-property:none | all | property

参数说明:

none: 没有属性改变

all : 默认值,所有属性都改变

property: 元素的属性名 width,color 等

transition-duration 属性

定义:设置对象过渡的持续时间

语法:transition-duration:time

参数说明:

规定完成过渡效果需要花费的时间,以秒或者毫秒计,默认值 0

transition-timing-function 属性

定义:设置对象中过渡的动画类型,即规定过渡效果的速度曲线。

该属性允许过渡效果随着时间来改变其速度。

语法:只能使用一个属性值

transition-timing-function: linear|ease|ease-in|ease-out|ease-in-out|cubic-
bezier(n,n,n,n);

transition-delay 属性

定义:设置对象延迟的过渡时间

语法:transition-delay:time

参数说明:

指定秒或者毫秒数来延迟动画效果的开始,默认是 0

transition 复合属性

语法:

transition : property duration timing-function delay;

参数说明:过渡时间和延迟时间的顺序不能乱

CSS3 变换

定义:让一个元素在一个坐标系统中变形,这个属性包含一系列的变形函数,可以移动,旋转,缩放元素。

rotate () 旋转

定义:通过指定一个角度参数,对元素指定一个 2D 的旋转

语法:transform:rotate (angle) 单位 deg

参数说明:angle 指旋转角度,正数表示顺时针旋转,负数表示逆时针旋转

translate () 平移

定义:根据 X 轴和 Y 轴的位置给定参数,使当前元素位置移动

translateX () 仅水平方向移动

语法:transform:translateX () 单位 px

translateY () 仅垂直方向移动

语法:transform:translateY () 单位 px

translate (x,y) 水平方向和垂直方向同时移动

语法:transform:translate (X, Y) 单位 px

注意:如果只写一个参数,第二个默认是 0,也就是只设置了水平方向上的位移

scale ( ) 缩放

定义:设置元素的缩放程度

分类:

scaleX ( ) 仅水平方向缩放

语法:transform:scaleX () 没有单位

scaleY ( ) 仅垂直方向缩放

子主题 语法:transform:scaleY () 没有单位

scale (x,y) 使元素水平和垂直方向同时缩放

语法:transform:scale (x,y) 没有单位

CSS3 动画

定义:使元素从一种样式逐渐变化到另外一种样式的效果

@keyframes

定义:keyframes 关键帧,用来决定动画变化的关键位置

@keyframes animationname {
	keyframes-selector{
		cssStyles;
	}
}

animationname:必写项,定义动画的名称

keyframes-selector:必写项,动画持续时间的百分比 0% - 100% 之间, 或者使用 form 和 to 关键字也可以设置,form 代表 0%,to 代表 100%

animation 属性

animation-name 属性

设置对象所应用的动画名称

animation-duration 属性

定义:设置对象动画的持续时间

animation-timing-function 属性

定义:设置对象动画的过渡类型,即规定动画的速度曲线

animation-delay 属性

定义:设置动画的延迟时间

animation-iteration-count 属性

定义:设置对象动画的循环次数

animation-direction 属性

定义:设置对象动画是否反向运动

ES6 新增特性

一、块级作用域、块级变量 let、块级常量 const

var会发生变量提升现象,将变量提升到函数顶部或全局顶部

必须在let声明后调用该变量 (const和let一样)

let和const的这种现象称为暂时性死区

从块开始到let声明之间是“暂存死区”

二、箭头函数

this 对象的指向是可变的,但是在箭头函数中,它是固定的。箭头函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。

三、参数处理(默认参数 /…)

给函数设置默认参数值,参数的传递是从左到右的

剩余参数允许我们将一个不定数量的参数表示为一个数组

function(a, b, ...theArgs) {
   ...
}
//必须是函数的最后一个参数以...为前缀
//它是由剩余实参组成的Array数组
//这个例子中的theArgs收集第三个以及之后的所有实参

展开运算符(…):可以在函数调用 / 数组构造时,将数组表达式或者 string 在语法层面展开;还可以在构造字面量对象时,将对象表达式按 key-value 的方式展开。

四、模板字面量 (模板字符串)

由反引号 `来代替单引号 ’ 或者双引号" 。

带标签的模板字符串:标签使我们可以用函数来解析模板字符串。${ person }

五、对象的扩展

创建对象时可以简化方法和重名的键值对

六、解构赋值

是一种 Javascript 表达式,目的就是将数组中的值或对象中的属性方便的提取到其他变量中

//可以用来交换变量
var a = 1;
var b = 3;
//等价于[a,b]=[3,1]
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

七、模块(import/export)

export 命令用于规定模块的对外接口,import 命令用于输入其他模块提供的功能。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用 export 关键字输出该变量。

八、类(class/extends)

ES6 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为 JavaScript 引入新的面向对象的继承模型。

九、 Promise

Promise 是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

Promise、Promise.all、Promise.race 分别怎么用?

Promise.all () 实现多任务并行。一个页面聊天系统,我们需要从两个不同的 URL 分别获得用户的个人信息和好友列表,这两个任务是需要并行执行的。

Promise.race () 实现多任务赛跑。有些时候,多个异步任务是为了容错。比如,同时向两个 URL 读取用户的个人信息,只需要获得先返回的结果即可,其他任务的结果会被丢弃。

JS 异步编程方案

JS 异步编程进化史:callback -> promise -> generator -> async/await

async/await 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。

async/await 函数相对于 Promise,优势体现在:处理 then 的调用链,能够更清晰准确的写出代码,并且也能优雅地解决回调地狱问题。

当然 async/await 函数也存在一些缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低,代码没有依赖性的话,完全可以使用 Promise.all 的方式。

async/await 函数对 Generator 函数的改进,体现在以下三点:内置执行器、更广的适用性、更好的语义。

vue 如何导入插件?

npm 安装,然后在 main.js 里 import导入相应的插件后,然后 Vue.use (xx) 后便可全局使用

从浏览器地址栏输⼊ url 到显示页面中的过程

分为 4 个步骤:

1)浏览器发送一个 URL 请求

2) 浏览器与服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。

3)一旦 TCP/IP 连接建立,浏览器向服务器发送 HTTP 的 GET 请求。服务器找到资源并使用 HTTP 响应返回该资源,值为 200 的 HTTP 响应状态表示一个正确的响应。

4)此时,服务器提供资源服务,客户端开始下载资源。

请求返回后,浏览器会解析 HTML 生成 DOM Tree,其次会根据 CSS 生成 CSS Tree,加载 JS,构建渲染树

浏览器渲染过程

  • 解析 HTML,生成 DOM 树
  • 解析 CSS,生成 CSSOM 树
  • 将 DOM 树和 CSSOM 树结合,生成渲染树 (Render Tree)
  • Layout (回流):根据生成的渲染树,进行回流 (Layout),得到节点的几何信息(位置,大小)
  • Painting (重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  • Display:将像素发送给 GPU,展示在页面上。

get 和 post 的区别

  • GET 是获取数据的,而 POST 是提交数据的。
  • GET 在浏览器回退时是无害的,而 POST 会再次提交请求。
  • GET 请求在 URL 中传送的参数是有长度限制的,而 POST 没有。
  • 对参数的数据类型,GET 只接受 ASCII 字符,而 POST 没有限制。
  • GET 参数通过 URL 传递,POST 放在 Request body 中。
  • GET 不能用来传递敏感信息,因为参数直接暴露在 URL 上。

实现垂直水平居中的方法

元素宽高固定时(设元素宽高为 100px):

  • absolute + 负 margin
.box {     
    position:absolute;;     
    top:50%;
    left:50%;     
    margin-left:-50px;     
    margin-top:-50px;
}
  • absolute + margin auto
.box {     
    position:absolute;;     
    top:0;
    left:0;
    right:0;     
    bottom:0;    
    margin:auto;     
}
  • absolute + calc()
.box{     
    position:absolute;;     
    top:calc(50% - 50px);     
    left:calc(50% - 50px);
}

元素宽高未知时:

  • absolute + transform
.box{
    position:absolute;
    top: 50%;
    left: 50%;
    transform:translate(-50%, -50%);
}
  • table,需要先打造一个表格结构,再将盒子放入单元格中,表格单元格中的内容本身就是垂直居中的,此法弊端:增加了很多冗余代码
<table>
    <tbody>
        <tr>
            <td class="wp">
                <div class="box">123</div>
            </td>
        </tr>
    </tbody>
</table>
<style type="text/css">
.wp{
    text-align: center;
    }
.box{
    display: inline-block;
}
</style>
  • css-table,CSS 新增的 table 属性,直接把普通元素,变为 table 元素的现实效果,原理与用 table 一样,但没有那么多的冗余代码
<div class="wp">    
    <div class="box">123</div> 
</div>
<style type="text/css">
.wp{
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
.box{
    display: inline-block;
}
</style>
  • flex 布局
<div class="wp">    
    <div class="box">123</div> 
</div>
<style type="text/css">
.wp{
    display: flex;
    justify-content: center;
    align-items: center;
}
</style>
  • grid 布局,CSS 新出的网格布局,代码量少,但兼容性不太好
<div class="wp">    
    <div class="box">123</div> 
</div>
<style type="text/css">
.wp{
    display: grid;
}
.box{
    align-self: center;
    justify-self: center;
}
</style>

总结:宽高固定时,推荐 absolute + 负 margin;宽高不固定,推荐 flex

flex 布局中如何解决内容溢出的问题

第一种方案:对父元素增加 overflow: hidden

第二种方案: 对父元素限定宽度,对父元素设置width: 0

Flex 实现两列布局

这里简单实现一下(其实应该使用 flex-basis 属性):

<div class="box">
  <div class="box-left"></div>
  <div class="box-right"></div>
</div>

.box {
  height: 200px;
  display: flex;
}
.box > div {
  height: 100%;
}
.box-left {
  width: 200px;
  background-color: blue;
}
.box-right {
  flex: 1; // 设置flex-grow属性为1,默认为0
  overflow: hidden;
  background-color: red;
}

如何实现文本溢出后使用… 代替

width:100px; //指定文本能显示的宽度为 100px;
overflow: hidden;     //超出 width 设定宽度的文本被隐藏
white-space: nowrap;    //设置文本不会换行,直到遇到 <br> 标签为止;
text-overflow:ellipsis;    //当文本溢出包含元素时,用省略号(...)代替。

伪类与伪元素

伪类:将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。

伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为 “伪” 元素。

区别

伪类的操作对象是文档树中已有的元素,而伪元素则创建了一个文档树外的元素。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

CSS3 规范中的要求使用双冒号 (:😃 表示伪元素,以此来区分伪元素和伪类,比如::before 和::after 等伪元素使用双冒号,:hover 和:active 等伪类使用单冒号。除了一些低于 IE8 版本的浏览器外,大部分浏览器都支持伪元素的双冒号 (:😃 表示方法。

你使用过的伪类选择器

a 标签的 4 种伪类(即对应四种状态), 如下:

:link “链接”:超链接点击之前
:visited “访问过的”:链接被访问过之后
:hover “悬停”:鼠标放到标签上的时候
:active “激活”: 鼠标点击标签,但是不松手时。

伪类选择器一个冒号和两个冒号的区别

单冒号 (😃 用于 CSS3 伪类,双冒号 (:😃 用于 CSS3 伪元素

伪元素由双冒号和伪元素名称组成。双冒号是在CSS3中引入的,用于区分伪类和伪元素。

但是伪类兼容现存样式,浏览器需要同时支持旧的伪类,对于 CSS2 之前已有的伪元素,单冒号和双冒号的写法作用是一样的。

promise 的三种状态和两种可能

  • pending - 进行中
  • fulfilled - 成功
  • rejected - 失败

状态的改变不可逆,一旦决议就不能再更改。

从 pending 变为 fulfilled 和从 pending 变为 rejected

promise 是否可以中断?为什么?

Promise 是无法被终止,但是可以中断,我们可以中断调用链

可以在某个 then/catch 执行之后,把 pending 状态的 promise 给 reject 掉

promise的then ()

p.then(第一个参数是成功的回调函数,第二个参数是失败的回调函数);

then 方法返回一个新的 promise 实例,状态是 pending

promise 的状态不改变,不会执行 then 里的方法

使用 return 可以将实例状态改成 fulfilled

在 then 方法中出现代码错误,promise 实例会改为 rejected 状态

如何实现文本框加 *

要赋值的文本框添加一个属性 id

在 js 中根据 ID 获取得到当前的文本框

得到文本框之后,变量名.value = 要赋的值

说一下 localStorage 和 sessionStorage 的区别

生命周期不同:

localStorage 的生命周期是永久性的,除非主动的去删除数据。

sessionStorage 的生命周期是在浏览器关闭前。关闭浏览器,数据及被删除。

作用域不同:

localstorage 在所有同源窗口中都是共享的。

sessionStorage 不在不同的浏览器窗口中共享。

同源请求中在同一浏览器打开两个页面可以使用 sessionStorage 实现数据共享嘛?

这取决于标签页如何打开。

通过点击链接(或者用了 window.open)打开的新标签页之间是属于同一个 session 的,但新开一个标签页总是会初始化一个新的 session,即使网站是一样的,它们也不属于同一个 session。

解决办法:对标签共享 session

方案:基于 Nginx 的 ip_hash 负载均衡、使用 Redis 做 session 的统一缓存、把 session 放到 cookie 中去,因为每次用户请求的时候,都会把自己的 cookie 放到请求中。

绝对定位是相对于谁的?相对于它的条件是什么?

绝对定位就是把该元素从文档流中踢出,不会占用文档流的位置,也不会影响后面的元素。

绝对定位相对于最近一个有定位的父元素,如果不存在就逐级向上排查,直到相对于 body 元素,即相对于浏览器窗口(必须有参照物)。

只能依赖于上级元素的位置,而不能依赖于设备的高度和宽度。

HTML的标签有哪些?

1、在 HTML 中,表格的标签是 <table></table>

2、在 HTML 中,单元格的标签是 <td></td>

3、在 HTML 中,表格的行标签是 <tr></tr>

5、在 HTML 中,表单控件的标记符是 <form></form>

6、在 HTML 中,表单中多行文本域的标记符是 <textarea></textarea>

8、在 HTML 中,插入图片的标记符是 <img src=” 图片地址”>

9、在 HTML 文件中,表示文件主体部分的标签是 <body></body>

10、在 HTML 文件中,标题的标记符是 <title></title>

11、在 HTML 中,用来定义超文本文档的标记符是 <a>

12、在 HTML 中,用来介绍与文件内容有关的信息的标记符是 <head></head>

13、在 HTML 中,换行标记符是 <br>

14、在 HTML 中,用来定义段落的标记符是 <p></p>

15、在 HTML 中,用来定义黑体的标记符是 <b></b>

16、在 HTML 中,用来定义斜体的标记符是 <i></i>

17、在 HTML 中,用来显示文字加下划线的标记符是 <u></u>

18、在 HTML 中,用来定义无序列表的标记符是 <ul></ul>

19、在 HTML 中,用来定义有序列表。的标记符是 <ol></ol>

HTML 语义化标签

常见语义化标签:<hn>:h1~h6,分级标题;<header>:头部;<nav>:导航栏;<main>:主要内容;<footer>:尾部
time、article、aside、details、section

语义化标签的一些优点:

代码结构清晰,

有利于 SEO,

提升用户体验,例如 title、alt 属性可以解释名称、图片信息,

代码可读性强,便于团队开发和维护,让其他开发人员能快速理解 HTML 结构,减少差异化。

便于其他设备解析: 如屏幕阅读器、盲人阅读器、移动设备等,

网页渲染效率高

html 公共属性有哪些?还有自定义属性

公共属性:id,name,class,style,lang,title

自定义属性:格式: data - 属性 =“属性值”,可以设置一个,也可以设置多个

获取元素属性的常规方法:直接获取元素,然后使用 getAttribute () 函数获取元素属性的值

form 表单如何进行提交?

第一种方法使用的是 submit 类型的 input 实现提交表单

第二种方法是使用 button 类型的 input 通过 οnclick=“function ();”

介绍下 iframe,它有哪些优点和缺点

它相当于在浏览器窗口内嵌一个子窗口,内容自动打开。Iframe 可以嵌在网页中的任意部分,也可以随意定义其大小。

优点:

iframe 能够原封不动的把嵌入的网页展现出来。

网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用 iframe 来嵌套,可以增加代码的可重用。

跨域完毕之后DOM操作和互相之间的JavaScript调用都是没有问题的

缺点:

iframe 会阻塞主页面的 onload 事件。

代码复杂,不利于搜索引擎优化(SEO)。

很多的移动设备无法完全显示框架,设备兼容性差。

iframe 框架页面会增加服务器的 http 请求,对于大型网站是不可取的。

display 有哪些属性?

display最常用的属性值 inline、block、inline-block、none。(还有table,table-row,table-cell这个我用的少)

inline(内联元素)属性值为默认值,此元素会被显示为内联元素,元素前后没有换行符。

block(块级元素)设置为块级元素独占一行,就具备了宽、高,和别的块级元素的间距 margin 属性的设置,还有间距的设置 padding,但是不能设置行高(line-height)。

inline-block(内联块)这个属性值一来他可以作为块级元素,可以具有 block 的特性,另一方面,使用这个属性值可以设置行高,从而使文字居中,方便易用。

none(元素不会被显示)。

如何使用 flex 设置水平垂直居中?

display:flex;
align-items: center;
justify-content: center;

处理过哪些 css 兼容性问题?

浏览器 CSS 样式初始化

*{ 
 margin: 0; 
 padding: 0; 
}

浏览器私有属性

可直接在某个属性中额外添加浏览器私有写法,确保浏览器能识别该属性值

-webkit-transform:rotate(-3deg); /*为Chrome/Safari*/ 
 -moz-transform:rotate(-3deg); /*为Firefox*/ 
 -ms-transform:rotate(-3deg); /*为IE*/ 
 -o-transform:rotate(-3deg); /*为Opera*/ 
 transform:rotate(-3deg);

CSS hack 语法

CSS hack 的写法大致归纳为 3 种:条件 hack、属性级 hack、选择符级 hack。

**(**一般情况下,尽量避免使用 CSS hack,过多滥用会造成 html 文档混乱,不易管理与维护)

(这个没用过,不了解)

解决父元素塌陷的方法

如果父元素只包含浮动元素,且父元素未设置高度和宽度的时候。那么它的高度就会塌缩为零,也就是所谓的 “高度塌陷”,如果父级元素包含背景或者边框,那么溢出的元素就不像父级元素的一部分了。解决 “高度塌陷” 的问题很简单:

浮动父级元素,并在该元素的下个元素添加 clear:both, 确保浮动元素落到父级元素的下方。

overflow:hidden

使用 after 伪元素

//父元素添加  
.clearfix:after{
  content:'';
  display:block;
  clear:both;
}

三次握手、四次挥手

TCP 三次握手:

1、客户端发送 SYN 包来建立连接。包信息: [SYN=1,ACK=0] Seq=1000 (随机生成的初始序号 client_isn, 目前假设 1000);Len=0;MSS=1460 (通常情况下是 1460);

2、服务端收到包之后,提取 SYN 的报文信息,然后分配 TCP 缓存和变量,发送允许连接的报文段。包信息 [SYN=1,ACK=1] Seq=666 (随机生成的初始序号 server_isn, 目前假设 535);Ack=1000 (上一个包的 Seq)+1;Len=0;MSS=1200 (这个不是固定的,根据当前窗口来判断能接受的最大报文段长度) 在第三次握手之前分配缓存容易收到 SYN 洪泛的拒绝服务攻击

3、客户端接受到服务端的确认包之后,发送确认包 [ACK=1,SYN=0] Seq=1001 (上一个包的 Ack), Ack=666 (上一个包的 Seq)+1; 之后就可以正常通信了。前两次不能有效负载,第三次就可以携带客户数据了,后面在通信的时候标志位都将置为 0

TCP 四次挥手:

1、客户端给服务器发送 TCP 包,用来关闭客户端到服务器的数据传送。将标志位 FIN=1 表示请求断开连接,同时把 Seq = u

2、服务器收到 FIN 后,先检验 Ack =u+1,发回一个 ACK = 1 (标志位 ACK=1) 表示确认断开连接请求,同时把 Seq = v , 服务器开始断开工作

3、服务器断开工作完成,发送一个 FIN = 1 请求断开连接,ACK=1 (标志位 ACK=1) 表示确认断开连接请求,同时把 Seq =w

4、客户端收到服务器发送的 FIN=1 之后,发回 ACK=1 (标志位 ACK=1) 确认关闭请求,同时把 Ack= w+1 服务器在检验 Ack= 服务器 Seq+1 之后关闭连接,客户端在等待 2msl 时间后关闭连接

注意:为什么建立连接只要三次握手,但是断开连接要四次挥手?

因为三次握手的第二次由服务器发送 SYN 建立连接的信息和 ACK 确认建立连接的信息是在同一个报文中传输的,而四次挥手的由服务器发送的 ACK 确认断开请求的信息和 FIN 发送断开连接的信息是在两个报文中传输的

分别说一下 XSS、CSRF、Dos/DDoS、点击劫持、sql 注入

XSS 攻击是指攻击者在网站上注入恶意的客户端代码,通过恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。

CSRF,跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。通常情况下,CSRF 攻击是攻击者借助受害者的 Cookie 骗取服务器的信任,可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

DOS 是 Denial of Service 的简称,即拒绝服务,其目的是使计算机或网络无法提供正常的服务。

分布式拒绝服务攻击 (Distributed Denial of Service) 可以使很多的计算机在同一时间遭受到攻击,使攻击的目标无法正常使用,DDOS 攻击已经出现了很多次,导致很多的大型网站都出现了无法进行操作的情况,这样不仅仅会影响用户的正常使用,同时造成的经济损失也是非常巨大的。

点击劫持(ClickJacking)是一种视觉上的欺骗手段。大概有两种方式:

一是攻击者使用一个透明的 iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的 iframe 页面。

二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义。

SQL 注入是比较常见的网络攻击方式之一,它不是利用操作系统的 BUG 来实现攻击,而是针对程序员编写时的疏忽,通过 SQL 语句,实现无账号登录,甚至篡改数据库。

怎么处理 XSS?

XSS(跨站脚本攻击)是指攻击者在返回的HTML中嵌入javascript脚本,为了减轻这些攻击,需要在HTTP头部配上,set-cookie:

httponly-这个属性可以防止XSS,它会禁止javascript脚本来访问cookie。

secure - 这个属性告诉浏览器仅在请求为https的时候发送cookie。

Event Loop,宏任务微任务

JS 中有两种任务类型:微任务(microtask)和宏任务(macrotask)

  • 宏任务: script (主代码块)、setTimeout 、setInterval 、setImmediate 、I/O 、UI rendering
  • 微任务:process.nextTick(Nodejs) 、Promise 、Object.observe 、MutationObserver

正确的一次 Event loop 顺序是这样的:

  • 执行同步代码,这属于宏任务
  • 执行栈为空,查询是否有微任务需要执行
  • 执行所有微任务
  • 必要的话渲染 UI
  • 然后开始下一轮 Event loop,执行宏任务中的异步代码

防抖和节流

//防抖
//在滚动事件中需要做个复杂计算或者实现一个按钮的防二次点击操作。可以通过函数防抖动来实现
function debounce (fn, wait = 1000) {
  let timeOutId
  return function () {
    let context = this
    if (timeOutId) {
      clearTimeout(timeOutId)
    }
    timeOutId = setTimeout(() => {
      fn.apply(context, arguments)
    }, wait)
  }
}

//节流
//防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行
function throttle (fn, wait) {
  let timeoutId = null
  return function () {
    let context = this
    if (!timeoutId) {
      timeoutId = setTimeout(() => {
        fn.apply(context, arguments)
        timeoutId = null
      }, wait)
    }
  }
}

回流和重绘

  • 浏览器使用流式布局模型 (Flow Based Layout)
  • 浏览器会把 HTML 解析成 DOM,把 CSS 解析成 CSSOM,DOM 和 CSSOM 合并就产生了 Render Tree
  • 有了 RenderTree 就能知道所有节点的样式,计算节点在页面上的大小和位置,把节点绘制到页面上
  • 由于浏览器使用流式布局,对 Render Tree 的计算通常只需要遍历一次就可以完成,但 table 及其内部元素除外,通常需要多次计算且要花费 3 倍于同等元素的时间,这也是为什么要避免使用 table 布局的原因之一。

何时触发回流和重绘

何时发生回流:

  • 添加或删除可见的 DOM 元素
  • 元素的位置发生变化
  • 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
  • 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
  • 页面一开始渲染的时候(这肯定避免不了)
  • 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

何时发生重绘(回流一定会触发重绘)

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

有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化,浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。你访问以下属性或方法时,浏览器会立刻清空队列:

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • width、height
  • getComputedStyle()
  • getBoundingClientRect()

以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。因此,我们在修改样式的时候,最好避免使用上面列出的属性,他们都会刷新渲染队列 如果要使用它们,最好将值缓存起来。

如何避免触发回流和重绘

CSS:

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

JavaScript:

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

vue2 和 vue3 响应式的区别

Vue2 中使用 ES5 中的 Object.defineProperty 方法实现响应式数据

缺点:无法监测到对象属性的动态添加和删除、无法监测到数组的下标和 length 属性的变更

Vue3 中使用 ES6 中的 proxy 语法实现响应式数据

优点:弥补了Vue2的缺点,可以检测到代理对象属性的动态添加和删除、可以监测到数组的下标和 length 属性的变更

vue 异步加载的方式

vue 中自己的异步 api,$nextTick 等待 Vue 将 dom 渲染完后再执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的 DOM。

使用异步组件,使用 import ( ) 动态导入

用 async/await 来处理异步

VueX解决了什么问题,VueX的 API?

Vuex 是一个专为 Vue.js 开发的状态管理插件。

解决了多个组件依赖于同一状态、来自不同组件的行为需要变更同一状态的问题。

vuex 就是一个 store 对象,每个 vue 应用仅且仅有一个 store 对象。

不能直接改变 store 中的状态。改变 store 中的状态的唯一途径是提交 (commit) mutations。

在构造函数中可以传一个对象参数。这个参数中可以包含 5 个对象:

1.state – 存放状态,相当于组件中的 data

2.getters – state 的计算属性,相当于 computed

3.mutations – 更改状态的逻辑,同步操作,相当于 methods

4.actions – 提交 mutation,异步操作

5.mudules – 将 store 模块化

当一个组件获取多种状态的时候,则在计算属性中要写多个函数。为了方便,可以使用 mapState 辅助函数来帮我们生成计算属性。mapState 函数返回的是一个对象,为了将它里面的计算属性与组件本身的局部计算属性组合起来,需要用到对象扩展运算符。

说一下 composition API

composition api 是为了解决传统的 option API配置方法写组件业务复杂度越来越高,代码量会不断的加大,

由于需要遵循 option 的配置写到特定的区域,导致后续维护非常的复杂,同时代码可复用性不高。

compositon-api 提供了一下几个函数:

  • setup 在 created 函数被完全实例化之前执行,只能是同步的,不能是异步的,由于在执行 setup 时尚未创建组件实例,因此在 setup 选项中没有 this
  • ref 响应式引用 处理基础类型的数据
  • reactive 响应式引用 处理数组、对象数据
  • toRefs 处理对象解构之后的数据,无默认值
  • toRef 处理对象解构之后的数据,有默认值
  • readonly 只能读的响应式数据
  • watchEffect 接受一个函数作为参数,监听函数内响应式数据的变化,当函数内响应式数据发生变化时函数会立即再调用一次

vue 的 API 和函数

Vue.component()注册或获取全局组件。

Vue.use()使用插件

Vue.directive()注册或获取全局指令。

Vue.compile()将一个模板字符串编译成 render 函数。

Vue.mixin()全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。

 var vm = new Vue({
      el: '#app',// 控制区域
      data: {},// 定义数据
      methods: {},// 定义方法
      filters: {},// 定义私有过滤器
      directives: {},// 定义私有指令
      components: { }, // 定义实例内部私有组件的

      beforeCreate() { },// 实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
      created() { }, //实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
      beforeMount() { },// 此时已经完成了模板的编译,但是还没有挂载到页面中
      mounted() { },// 此时,已经将编译好的模板,挂载到了页面指定的容器中显示
      beforeUpdate() { },// 状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
      updated() { },// 实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
      beforeDestroy() { },// 实例销毁之前调用。在这一步,实例仍然完全可用。
      destroyed() { }, //Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
    })

Ajax 是什么?

Ajax 全称:Asychronous javascript and xml,是一种创建交互式网页应用网页开发技术。

Ajax 的交互模型/创建 ajax 过程

(1) 创建 XMLHttpRequest 对象,也就是创建一个异步调用对象.

(2) 创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息.

(3) 设置响应 HTTP 请求状态变化的函数.

(4) 发送 HTTP 请求.

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

(6) 使用 JavaScript 和 DOM 实现局部刷新.

同步和异步的区别?

同步现象:客户端向服务器发出请求后,在服务器发出响应前,客户端处于等待卡死状态;

异步现象:客户端向服务器发出请求后,不论服务器是否发出响应,客户端都可以做其他事情,如:Ajax;

“同步模式” 就是后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。

“异步模式” 则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

JavaScript 的同源策略

概念:同源策略是客户端脚本(尤其是 Javascript)的重要的安全度量标准。它最早出自 Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。

这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。

指一段脚本只能读取来自同一来源的窗口和文档的属性。

如何解决跨域问题?

jsonp 。jsonp是浏览器会放过 img script 标签引入资源的方式。所以可以通过后端返回一段执行 js 函数的脚本,将数据作为参数传入。然后在前端执行这段脚本。

document.domain+iframe

API 跨域可以通过服务器上 nginx 反向代理

本地 webpack dev server 可以设置 proxy :changeOrigin 参数, 设置为true

CORS 。需要后台配合设置 HTTP 响应头,如果请求不是简单请求(1. method:get,post,2. content-type:三种表单自带的 content-type,3. 没有自定义的 HTTP header),浏览器会先发送 option 预检请求,后端需要响应 option 请求,然后浏览器才会发送正式请求,cors 通过白名单的形式允许指定的域发送请求

为什么 vue 组件中 data 必须是一个函数?

对象为引用类型,当复用组件时,由于数据对象都指向同一个 data 对象,当在一个组件中修改 data 时,其他重用的组件中的 data 会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object 的实例),引用地址不同,则不会出现这个问题。

vue 中 v-if 和 v-show 有什么区别?

v-if 和 v-show 看起来似乎差不多,当条件不成立时,其所对应的标签元素都不可见,但是这两个选项是有区别的:

1、v-if 在条件切换时,会对标签进行适当的创建和销毁,而 v-show 则仅在初始化时加载一次,因此 v-if 的开销相对来说会比 v-show 大。

2、v-if 是惰性的,只有当条件为真时才会真正渲染标签;如果初始条件不为真,则 v-if 不会去渲染标签。v-show 则无论初始条件是否成立,都会渲染标签,它仅仅做的只是简单的 CSS 切换。

computed 和 watch 的区别

computed支持缓存,只有依赖数据发生改变,才会重新进行计算。

不支持异步,当 computed 内有异步操作时无效,无法监听数据的变化。

watch不支持缓存,数据变,直接会触发相应的操作;watch 支持异步

v-for key 的作用

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。key 属性的类型只能为 string 或者 number 类型。

key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复 / 再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

使用 key 要什么要注意的吗?

  • 不要使用对象或数组之类的非基本类型值作为 key,请用字符串或数值类型的值;

  • 不要使用数组的 index 作为 key 值,因为在删除数组某一项,index 也会随之变化,导致 key 变化,渲染会出错。

    例:在渲染 [a,b,c] 用 index 作为 key,那么在删除第二项的时候,index 就会从 0 1 2 变成 0 1(而不是 0 2),随之第三项的 key 变成 1 了,就会误把第三项删除了。

vue 双向绑定原理

vue2 是采用数据劫持结合发布者 - 订阅者模式的方式,

通过 Object.defineProperty () 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者。

vue3基于Proxy代理的变动侦测,性能整体优于getter/setter

vue 如何获取 dom

先给标签设置一个 ref 值,再通过 this.$refs.domName 获取

watch 的属性和 methods 方法能用箭头函数定义吗?

不可以。this 会是 undefind, 因为箭头函数中的 this 指向的是定义时的 this,而不是执行时的 this,所以不会指向 Vue 实例的上下文。

v-if 和 v-for 的优先级是什么?

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用。

说说 Vue 中 $nextTick

理解 $nexttick 的原理就要提前理解 js 事件循环宏任务和微任务的原理

js 执行宏任务时候遇到微任务(promise)或者 settimeout 等的时候就会把微任务放到下一轮执行而不是立刻执行,当前宏任务执行完之后再执行挂起的微任务,之后再执行下一轮宏任务;这是浏览器执行的基础;
$nexttick 就类似于被 挂起微任务或者挂到下一轮宏任务的 settimeout 一样

由此我们可以看出 $nexttick 就是进行了延迟执行。

使用场景:在 create 函数里面执行 dom 操作时候。

create 函数执行的时候 dom 并没有渲染所以操作 dom 失败,那么在 create 函数里使用 nexttick 操作dom则可以完美获取到dom 元素。

因为 nexttick 函数里面的事件是延迟执行的,是等 dom 渲染完之后执行的。

总结:

1、没有更新 dom 但想操作 dom 的时候,可以使用 nexttick 方法
2、改变了多个变量或多个方法改变了同一变量的时候,可以使用 $nexttick 延迟更新操作

HTTP 状态码

下面是常见的 HTTP 状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它 URL
  • 302 - 临时移动。与 301 类似。但资源只是临时被移动。客户端应继续使用原有 URI
  • 304 - 浏览器在接收到这个状态码后,会使用浏览器已缓存的文件。
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误
  • 502 - 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应

讲讲 304 缓存

304 是 HTTP 状态码,服务器用来标识这个文件没修改,不返回内容。

浏览器在接收到这个状态码后,会使用浏览器已缓存的文件。

缓存分为强缓存和协商缓存。

强缓存不过服务器,协商缓存需要过服务器,协商缓存返回的状态码是 304。

两类缓存机制可以同时存在,强缓存的优先级高于协商缓存。

当执行强缓存时,如若缓存命中,则直接使用缓存数据库中的数据,不再进行缓存协商。

请问 HTTP 的请求和响应由哪几个部分组成?

  • HTTP 请求信息由 3 部分组成:

1、请求方法(GET/POST)、URI、协议 / 版本

2、请求头 (Request Header):Content-Type、端口号 Host、Cookie

3、请求正文:包含客户提交的查询字符串信息,请求头和请求正文之间是一个空行

  • HTTP 响应也由 3 个部分构成:

1、状态行:状态代码及描述 如 404、500 等

2、响应头 (Response Header):Content-Type 、Server、Date

3、响应正文:html 代码

Git 工作流

Git 工作流可以理解为团队成员遵守的一种代码管理方案

  • 集中式工作流
  • 功能开发工作流
  • Gitflow 工作流
  • Forking 工作流

CSS3动画

CSS3 新增创建动画方法,通过 @keyframes 规则创建动画,在规则中指定 CSS 样式,就能创建由当前样式逐渐改为新样式的动画效果,用百分比来规定变化发生的时间,或用 “from” 和 “to”(等同于 0% 和 100%)

利用 animation 属性将动画绑定到指定选择器上,至少绑定动画名称与时长

行级标签和块级标签

  • 行内元素有:a b span img input select strong
  • 行内元素不可以设置宽高,不独占一行
  • 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4… p
  • 块级元素可以设置宽高,独占一行

JavaScript继承

构造函数绑定:使用 callapply 方法,将父对象的构造函数绑定在子对象上

function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}
  • 实例继承:将子对象的 prototype 指向父对象的一个实例
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象

function extend(Child, Parent) {
   var p = Parent.prototype;
   var c = Child.prototype;
   for (var i in p) {
      c[i] = p[i];
   }
   c.uber = p;
  }

原型继承:将子对象的 prototype 指向父对象的 prototype

function extend(Child, Parent) {
    var F = function(){};
   F.prototype = Parent.prototype;
   Child.prototype = new F();
   Child.prototype.constructor = Child;
   Child.uber = Parent.prototype;
}

HTTP与HTTPS的区别

http 是超文本传输协议,信息是明文传输,HTTPS 协议要比 http 协议安全,https 是具有安全性的 ssl 加密传输协议,可防止数据在传输过程中被窃取、改变,确保数据的完整性 。

http 协议的默认端口为 80,https 的默认端口为 443。

http 的连接很简单,是无状态的。https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20% 的耗电。

https缓存不如 http 高效,会增加数据开销。

Https 协议需要 ca 证书,费用较高,功能越强大的证书费用越高。

SSL 证书需要绑定 IP,不能再同一个 IP 上绑定多个域名,IPV4 资源支持不了这种消耗。

TCP 和 UDP 的区别

TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议

在正式收发数据前,必须和对方建立可靠的连接。

一个 TCP 连接必须要经过三次 “对话” 才能建立起来

UDP(User Data Protocol,用户数据报协议)是与 TCP 相对应的协议。

它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!

UDP 适用于一次只传送少量数据、对可靠性要求不高的应用环境。

说说你对作用域链的理解

  • 当代码在一个环境中创建时,会创建变量对象的一个作用域链(scope chain)来保证对执行环境有权访问的变量和函数。作用域第一个对象始终是当前执行代码所在环境的变量对象(VO)。如果是函数执行阶段,那么将其 activation object(AO)作为作用域链第一个对象,第二个对象是上级函数的执行上下文 AO,下一个对象依次类推。
  • 当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级 (词法层面上的父级) 执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

作用域链的作用是保证执行环境里有权访问的变量和函数是有序的。

作用域链的变量只能向上访问,变量访问到 window 对象即被终止,作用域链向下访问变量是不被允许的。

渐进增强和优雅降级

渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

Javascript 垃圾回收方法

标记清除(mark and sweep)

这是 JavaScript 最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为 “进入环境”,当变量离开环境的时候(函数执行结束)将其标记为 “离开环境”。

垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

引用计数 (reference counting)

在低版本 IE 中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加 1,如果该变量的值变成了另外一个,则这个值得引用次数减 1,当这个值的引用次数变为 0 的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为 0 的值占用的空间。

在 IE 中虽然 JavaScript 对象通过标记清除的方式进行垃圾回收,但 BOM 与 DOM 对象却是通过引用计数回收垃圾的,也就是说只要涉及 BOM 及 DOM 就会出现循环引用问题。

谈谈性能优化问题

代码层面:避免使用 css 表达式,避免使用高级选择器,通配选择器。

缓存利用:缓存 Ajax,使用 CDN,使用外部 js 和 css 文件以便缓存,添加 Expires 头,服务端配置 Etag,减少 DNS 查找等

请求数量:合并样式和脚本,使用 css 图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载。

请求带宽:压缩文件,开启 GZIP,

代码层面的优化:

  • 用 hash-table 来优化查找
  • 少用全局变量
  • 用 innerHTML 代替 DOM 操作,减少 DOM 操作次数,优化 javascript 性能
  • 用 setTimeout 来避免页面失去响应
  • 缓存 DOM 节点查找的结果
  • 避免使用 CSS Expression
  • 避免全局查询
  • 避免使用 with (with 会创建自己的作用域,会增加作用域链长度)
  • 多个变量声明合并
  • 避免图片和 iFrame 等的空 Src。空 Src 会重新加载当前页面,影响速度和效率
  • 尽量避免写在 HTML 标签中写 Style 属性

首屏加载优化

  • Vue-Router 路由懒加载(利用 Webpack 的代码切割)
  • 使用 CDN 加速,将通用的库从 vendor 进行抽离
  • Nginx 的 gzip 压缩
  • Vue 异步组件
  • 服务端渲染 SSR
  • 如果使用了一些 UI 库,采用按需加载
  • Webpack 开启 gzip 压缩
  • 如果首屏为登录页,可以做成多入口
  • Service Worker 缓存文件处理
  • 使用 link 标签的 rel 属性设置 prefetch(这段资源将会在未来某个导航或者功能要用到,但是本资源的下载顺序权重比较低,prefetch 通常用于加速下一次导航)、preload(preload 将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度)

移动端性能优化

  • 尽量使用 css3 动画,开启硬件加速。
  • 适当使用 touch 事件代替 click 事件。
  • 避免使用 css3 渐变阴影效果。
  • 可以用 transform: translateZ(0) 来开启硬件加速。
  • 不滥用 Float。Float 在渲染时计算量比较大,尽量减少使用
  • 不滥用 Web 字体。Web 字体需要下载,解析,重绘当前页面,尽量减少使用。
  • 合理使用 requestAnimationFrame 动画代替 setTimeout
  • CSS 中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发 GPU 渲染,请合理使用。过渡使用会引发手机过耗电增加
  • PC 端的在移动端同样适用

js 延迟加载的方式有哪些?

defer 和 async、动态创建 DOM 方式(创建 script,插入到 DOM 中,加载完毕后 callBack)、按需异步载入 js

defer 和 async的区别

defer 并行加载 js 文件,会按照页面上 script 标签的顺序执行

async 并行加载 js 文件,下载完成立即执行,不会按照页面上 script 标签的顺序执行

谈谈 Cookie 的优缺点

cookie 虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的。

优点:极高的扩展性和可用性

  1. 通过良好的编程,控制保存在 cookie 中的 session 对象的大小。

  2. 通过加密和安全传输技术(SSL),减少 cookie 被破解的可能性。

  3. 只在 cookie 中存放不敏感数据,即使被盗也不会有重大损失。

  4. 控制 cookie 的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的 cookie。

缺点:

  1. Cookie 数量和长度的限制。每个 domain 最多只能有 20 条 cookie,每个 cookie 长度不能超过 4KB,否则会被截掉.

  2. 安全性问题。如果 cookie 被人拦截了,那人就可以取得所有的 session 信息。即使加密也与事无补,因为拦截者并不需要知道 cookie 的意义,他只要原样转发 cookie 就可以达到目的了。

  3. 有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

web storage 和 cookie 的区别

Web Storage 的概念和 cookie 相似,区别是它是为了更大容量存储设计的。Cookie 的大小是受限的,并且每次你请求一个新的页面的时候 Cookie 都会被发送过去,这样无形中浪费了带宽,另外 cookie 还需要指定作用域,不可以跨域调用。

除此之外,Web Storage 拥有 setItem,getItem,removeItem,clear 等方法,不像 cookie 需要前端开发者自己封装 setCookie,getCookie。

但是 cookie 也是不可以或缺的:cookie 的作用是与服务器进行交互,作为 HTTP 规范的一部分而存在 ,而 Web Storage 仅仅是为了在本地 “存储” 数据而生

浏览器的支持除了 IE7及以下不支持外,其他标准浏览器都完全支持 (ie 及 FF 需在 web 服务器里运行),值得一提的是 IE 总是办好事,例如 IE7、IE6 中的 userData 其实就是 javascript 本地存储的解决方案。通过简单的代码封装可以统一到所有的浏览器都支持 web storage。

localStorage 和 sessionStorage 都具有相同的操作方法,例如 setItem、getItem 和 removeItem 等

cookie 和 session 的区别:

1、cookie 数据存放在客户的浏览器上,session 数据放在服务器上

2、cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗,考虑到安全应当使用 session。

3、session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。因此考虑到减轻服务器性能方面,应当使用 cookie

4、单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie

5、建议将登陆信息等重要信息存放为 session,其他信息如果需要保留,可以放在 cookie 中

事件代理

事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。

顾名思义,“事件代理” 即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。

事件代理的原理是 DOM 元素的事件冒泡。使用事件代理的好处是可以提高性能。

网络分层里七层模型

  • 应用层:应用层、表示层、会话层(从上往下)(HTTP、FTP、SMTP、DNS
  • 传输层(TCPUDP
  • 网络层(IP
  • 物理和数据链路层(以太网)

每一层的作用如下:

-物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
-数据链路层:将比特组装成帧和点到点的传递(帧Frame)
-网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
-传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
-会话层:建立、管理和终止会话(会话协议数据单元SPDU)
-表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
-应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

href与src的区别

  • href 是元素或文档与指定资源联通,是引用

  • src 是下载后嵌入构成文档直接内容

Webpack 的 loader 和 plugins 的区别

loader 用于加载某些资源文件。

因为 webpack 只能理解 JavaScript 和 JSON 文件,这就需要对应的 loader 将资源转化,加载进来。

plugin 用于扩展 webpack 的功能。

目的在于解决 loader 无法实现的其他事,它直接作用于 webpack,扩展了它的功能。

当然 loader 也是变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。

而 plugin 的功能更加的丰富,而不仅局限于资源的加载。

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值