资讯详情

2020前端面试题72道总结

1.说说你对盒子模型的理解?

当文档布局时,浏览器的渲染引擎将遵循标准之一css基本框盒模型将所有元素表示为矩形盒

盒子由四部分组成:

content 内容区域

padding 内边距 清除内容周围区域,内部距离透明,值不能为负,盒子background 属性影响

margin 外边距 在元素外创建额外的空白通常是指不能放置其他元素的区域

border 边框 由粗细样式颜色三部分组成

在css 中 盒模可分为:

W3C标准盒模型

IE奇怪的盒子模型

默认情况下是W3C标准盒模型

标准盒模型

盒子总宽度 = width padding border margin

盒子总高度 = height padding border margin

width height 只有内容高度,不包括padding和border值

奇怪的盒子模型

盒子总宽度 = width margin

盒子总高度 = height margin

width height 包含 padding和border值

2.css什么是选择器?优先级?可以继承哪些属性?

选择器:

id选择器、选择、标签选择、后代选择、子选择、相邻同胞选择、群组选择、

还有一些不常用的选择:

伪选择器、伪元素选择器、属性选择器

css3 中新选择器:

层次选择器、伪类选择器 (新属性)、属性选择器(新属性)

优先级:

!important > 内联>类选择器>标签选择器

继承属性:

字体系列属性:

font

font-family 字体系列规定元素

font-weight 设置字体的厚度

font-size 设置字体尺寸

font-style 定义字体的风格

font-variant 大字体或小字体

文本系列属性

text-indent 文本缩进

text-align 文本水平对刘

line-height 行高

word-spacing 增加或减少单词见的空白

letter-spacing 增加或减少字符间的空白

text-transform 控制文本大小写

direction 规定文本的写作方向

color 文本颜色

元素可见性 visibility

表格布局属性

caption-side 定位表格标题位置

border-collapse 合并表格边框

border-spacing 设置相邻单元格边框之间的距离

empty-cells 单元格边框的出现和消失

table-layout 什么决定了表格的宽度?

列表属性

list-style-type 文字前面的小点点样式

list-style-position 小点点位置

list-style 上述属性可以通过此属性集合

引用 qoutes 设置嵌套引用的引号类型

光标属性 cursor 箭头可以成为所需的形状

继承中特殊的几点

a标签的字体颜色不能继承

h1-h6的字体大小不能继承

无继承属性

dispaly

文本属性 vertical-align、text-decoration

盒子模型属性 宽度 高度 内外边距 边框

背景属性 背景图片 颜色 位置

定位属性 浮动 清楚浮动 定位position 等

产生内容属性 content couter-reset counter-increment

轮廓风格属性 outline-style

页面样式属性 size page-break-before page-break-after

3.元素水平居中的方法有哪些?若元素不定宽高呢?

实现居中方法分为两类

居中元素的宽高已知

居中元素宽高未知

实现方式

利用定位 margin:auto

<style>   .father{     width:500px;     height:300px;     border:1px solid #0a3b98;     position: relative;    }   .son{     width:100px;     height:40px;     background: #f0a238;     position: absolute;     top:0;     left:0;     right:0;     bottom:0;     margin:auto;    } </style> 父级设置为相对定位 子级绝对定位 4个定位属性的值设置为0  如果子级没有设置宽高,它将被拉到与父级相同的宽高

利用定位 margin:负值

<style>   .father {     position: relative;     width: 200px;     height: 200px;     background: skyblue;    }   .son {     position: absolute;     top: 50%;     left: 50%;     margin-left:-50px;     margin-top:-50px;     width: 100px;     height: 100px;     background: red;    } </style>

利用定位 transfrom

<style>   .father {     position: relative;     width: 200px;     height: 200px;     background: skyblue;    }   .son {     position: absolute;     top: 50%;     left: 50%;  transform: translate(-50%,-50%);     width: 100px;     height: 100px;     background: red;    } </style>

table布局

<style>   .father {     display: table-cell;     width: 200px;     height: 200px;     background: skyblue;     vertical-align: middle;     text-align: center;    }   .son {     display: inline-block;     width: 100px;     height: 100px;   &bsp;    background: red;
    }
</style>

flex布局

<style>
    .father {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 200px;
        height: 200px;
        background: skyblue;
    }
    .son {
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

grid布局

<style>
    .father {
            display: grid;
            align-items:center;
            justify-content: center;
            width: 200px;
            height: 200px;
            background: skyblue;
​
        }
        .son {
            width: 10px;
            height: 10px;
            border: 1px solid red
        }
</style>

根据元素标签的性质,可以分为

内联元素居中布局

块级元素居中布局

内联元素居中布局

水平居中

行内元素可设置 text-align center

flex 布局设置父元素 display:flex justify-content center

垂直居中

单行文本父元素确认高度 height === line-height

多行文本父元素确认高度 display:table-cell vertical-align:middle

块级元素居中布局

水平居中

定宽:margin:0 auto;

绝对定位+left:50%+margin:负自身的一半

垂直居中

position: absolute设置left、top、margin-left、margin-top(定高)

display: table-cell

transform: translate(x, y)

flex(不定高,不定宽)

grid(不定高,不定宽),兼容性相对比较差

4.什么是响应式设计?响应式设计的基本原理是什么?如何做?

响应式网站设计 是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境 进行相应的响应和调整

响应式网站常见的特点:

同时适配pc+平板+手机等

标签导航在接近手持终端设备时改变为经典的抽屉式导航

网站的布局会根据视口来调整模块的大小和位置

实现方式

原理 通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta声明viewport

实现响应式布局方式

媒体查询

给不同分辨率的设备编写不同的样式来实现响应式布局,可以给不同分辨率的屏幕设置不同的样式

百分比

通过百分比单位来实现响应式的效果

可以让组件随着浏览器的宽度和高度变化而变化从而实现响应式布局,有些元素并不继承父元素的尺寸 所以并不建议使用百分比实现响应式

vw/vh

vw表示相对于视图窗口的宽度,vh表示相对于视图窗口的高度,任意层级元素,在使用vw单位的情况下。1vw都等于视图宽度的百分之一

rem

rem 相当于根元素html的font-size属性,默认浏览器字体大小为16px 所以 1rem = 16px

还可以利用ui框架 的栅格布局实现响应式

响应式设计通常会从以下几个方面思考:

弹性盒子 和媒体查询等技术

使用百分比布局创建流式布局的弹性ui同时使用媒体查询限制元素的尺寸和内容变更范围

使用相对单位使得内容自适应调节

选择断点针对不同断点实现不同的布局和内容展示

总结

响应式布局的优点

面对不同分辨率设备灵活性强

能够快捷解决多设备显示适应问题

缺点

仅适用布局、信息、框架、并不复杂的部门类型网站

兼容各种设备工作量大,效率低下

代码累赘,会出现隐藏无用的元素,加载时间加长

一种折中性的设计解决方案,多方面因素影响而达不到最佳效果,

一定程度上改变了网站原有的布局结构,会出现用户混淆的情况

5.怎么理解重绘和回流?什么场景下会触发?

html中每个元素都可以理解为一个盒子 在浏览器解析过程中会涉及到回流与重绘:

回流:

布局引擎根据各种样式计算每个盒子再页面上大小与位置

重绘:

当计算好盒子模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制

回流触发机制:

回流主要式计算节点的位置和几何信息,当页面布局和几何信息发生变化的时候就会触发回流

删除或者添加可见的dom元素

元素的位置发生变化、元素的尺寸发生变化

内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代

页面一开始渲染的时候(这避免不了)

浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

重绘触发机制:

触发回流一定会触发重绘

颜色的修改

文本方向的修改

阴影的修改

6.如果要做优化,css提高性能的方法有哪些?

实现方式有很多主要如下:

内联首屏关键CSS

通过内联css关键代码能够使浏览器在下载完html后就能立刻渲染

而如果外部引用css代码,在解析html结构过程中遇到外部css文件,才会开始下载css代码,再渲染

所以,CSS内联使用使渲染时间提前

异步加载CSS

在css文件请求 下载 解析完成之前,css会阻塞渲染,浏览器将不会渲染任何已处理的内容,前面加载内联代码后没必要阻塞浏览器渲染,这时候就可以使用异步加载

通过rel属性将link元素标记为alternate可选样式表

使用javascript将link标签插到head标签最后

资源压缩

使用webpack gulp/grunt rollup 模块化工具 将css代码进行压缩,使文件变小,大大降低了浏览器的加载时间

合理使用选择器

不要嵌套使用过多复杂选择器,最好不要三层以上,

使用id选择器就没必要在进行嵌套

通配符和属性选择器效率最低,避免复用

减少使用昂贵的属性

在页面发生重绘的时候,昂贵属性如box-shadow / border-radius / filter/透明度/:nth-child 等 会降低浏览器的渲染性能

不要使用@import

css样式文件有两种引入方式,一种是link元素 另一种是@import

@import 会影响浏览器的并行下载,使得页面在加载时增加额外的延迟,增添了额外的往返耗时,而且多个@import 可能会导致下载顺序紊乱,

其他:

减少重排操作,以及减少不必要的重绘

了解哪些属性可以继承而来,避免对这些属性重复编写

cssSprite 合成所有icon图片,用宽高加上background-position的背景图方式显现出我们要的icon图 ,减少了http请求

把小的icon图片转换成base64编码形式

css3动画或者过渡尽量使用transform和opacity 来实现动画,不要使用left和top属性

css实现性能方式可以从选择器嵌套 属性特性 减少http这三面考虑,同时还有注意css代码的加载顺序

7.对前端工程师这个职位是怎么理解的?它的前景会怎么样?

8.说说JavaScript中的数据类型?存储上的差别?

基本类型,复杂类型

两种类型的区别是:储存位置不同

基本类型:

Number,String,Boolean,Undefined,null,symbol

引用数据类型:

统称为Object ,

Object,Array,Function,Date,RegExp,Map,Set等

存储区别:

基本数据类型存储在栈中,

引用类型的对象储存于堆中,

当变量赋值时,解析器首先要确认的就是这个值是基本类型值还是引用类型值

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

简单类型的值存放在栈中,在栈中存放的时对应的值

引用类型对应的值存储在堆中,在栈中存放的是指向堆内存的地址

不同的类型数据导致赋值变量时的不同:

简单类型赋值,是生成相同的值,两个对象不同的地址

复杂类型赋值,是将保存对象的内存地址赋值给另一个变量,也就是两个变量指向堆内存中同一个对象

9.typeof 与 instanceof 区别

typeof 操作符返回一个字符串,表示未经计算的操作数的类型

虽然 typeof null 为 object 这是javaScript 一个悠久的Bug 不代表null 就是引用数据类型 并且null 本身也不是对象 所以 null在typeof之后返回的是有问题的结果

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

实现原理 顺着原型链去找,直到找到相同的原型对象,返回true , 否则为 false

typeof 与 instanceof 都是判断数据类型的方法 区别如下

typeof 会返回一个变量的基本类型,instanceof,返回的是一个布尔值

instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

typeof 也存在弊端 虽然可以判断基础数据类型 null除外

但是引用数据类型中,除了function 类型以外,其他的也无法判断

如果需要通用检测数据类型,可以采用Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串

10.说你对闭包的理解?闭包使用场景?

闭包是什么?

闭包就是能够读取其他函数内部变量的函数

一个函数和对其周围状态的引用捆绑在一起这样的组合就是个闭包,

也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域

在js中 每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内容与外部来凝结起来的一座桥梁

使用场景

创建私有变量,

延长变量的生命周期

一般函数的词法环境在函数返回后就被销毁,但是闭包会保存对创建时所在词法环境的引用, 即便创建时所在的执行上下文被销毁,但是创建时所在的词法环境依然存在,以达到延长变量的生命周期的目的,

11.bind apply call 区别? 如何实现一个bind?

作用是改变函数执行时的上下文,简而言之就更是改变函数运行时的this指向,

区别

apply 接受两个参数 第一个参数时this的指向,第二个参数是函数接受的参数,以数组的形式传入,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次,当第一个参数为null,undefined 的时候 默认指向window浏览器中

call 方法的第一个参数也是this的指向,后面传入的是一个参数列表,跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

bind 方法 和 call 很相似,第一个参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)

改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

总结:

三者都可以改变函数的this对象指向

三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined 或 null 则默认指向全局window

三者都可以传参,但是apply 是数组,而call、是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入

bind 是返回绑定this之后的函数,apply call 则是立即执行

实现步骤:

bind 修改this指向,动态传递参数,兼容new关键字

12.说说你对事件循环的理解

首先,JavaScript是一门单线程语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环

在JavaScript中所有的任务都可以分为:

同步任务:

立即执行的任务,同步任务一般会直接进入到主线程中执行

异步任务:

异步执行的任务,ajax网络请求,setTimeout定时函数等

流程

任务进入执行栈中 判断是同步任务还是异步任务 同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行,不断重复这个过程就是事件循环

异步任务的细分 宏任务和微任务

微任务 执行时机是在主函数执行结束之后,当前宏任务结束之前,常见的微任务有 promise.then , MutaionObserver, Object.observer (已经废弃,proxy代替) , process.nextTick (nodejs中)

宏任务 的事件粒度比较大,执行的时间间隔是不能精准控制,对一些高实时性的需求不太适合,常见的宏任务有,script(外层同步代码)

setTimeout/setInterval ,UI rendering/UI事件 , postMessage、messageChannel,setImmediate、I/O (node)

执行机制 执行一个宏任务,如果遇到微任务就将它放到微任务的事件队列中,当宏任务执行完成后会查看微任务的事件队列,然后将里面的所有微任务以此执行完

13.DOM常见的操作有哪些?

文档对象模型dom 是html和xml 文档的编程接口,它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构、样式和内容,任何HTML或XML文档都可以用Dom表示为一个由节点构成的层级结构

常见的DOM操作主要分为:

创建节点

createElement 创建新元素

createTextNode 创建一个文本节点

createDocumentFragment 用来创建一个文档碎片

表示一种轻量级的文档,主要是用来存储临时节点,然后把文档碎片的内容一次性添加到DOM中

create Attribute 创建属性节点 可以是自定义属性

查询节点

querySelector

传入任何有效的css选择器,即可选中单个DOM元素

如果页面上没有指定元素时,返回null

querySelectorAll

返回一个包含节点子树内所有与之相匹配的Element节点列表,如果没有相匹配,则返回一个空节点列表 ,返回的是一个静态实例并不是实时查询

更新节点

innerHTML 不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树

innerText,textContent 自动对字符串进行HTML编码,保证无法设置任何HTML标签,区别在于读取属性时,innerText,不返回隐藏元素的文本,而textCOntent返回所有文本

style

dom节点的style属性对应所有的css,可以直接获取或者设置

添加节点

innerHTML

appendChild

把一个子节点添加到父节点最后一个子节点

删除节点

删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild 把自己删掉,删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置

14.说说你对BOM的理解?常见的BOM对象你了解多少?

BOM , 浏览器对象模型,提供了独立于内容与浏览器窗口进行交互的对象,其作用就是跟浏览器做一些交互效果,比如如何进行页面的后退,前进,刷新,浏览器的窗口发生变化,滚动条的滚动,以及获取客户的一些信息,浏览器品牌版本,屏幕分辨率,

浏览器的全部内容可以看成DOM,整个浏览器可以看成BOM 区别如下:

DOM

文档对象模型

DOM就是把文档当作一个对象来看待

DOM的顶级对象是document

DOM主要学习的是操作页面元素

DOM是W3C标准规范

BOM

浏览器对象模型

把浏览器当做一个对象来看待

BOM的顶级对象是window

BOM学习的是浏览器窗口交互的一些对象

BOM是浏览器厂商在各自浏览器上定义的,兼容性较差

二、window

BOM的核心对象是window,它表示浏览器的一个实例,在浏览器中,window对象有双重角色,即是浏览器窗口的一个接口,又是全局对象,因此所有在全局作用域中声明的变量、函数都会变成window对象的属性和方法,

三、location

属性名 例子 说明
hash "#contents" utl中#后面的字符,没有则返回空串
host www.wrox.com:80 服务器名称和端口号
hostname www.wrox.com 域名,不带端口号
href Homepage | Wiley 完整url
pathname "/WileyCDA/" 服务器下面的文件路径
port 80 url的端口号,没有则为空
protocol http: 使用的协议
search ?q=javascript url的查询字符串,通常为?后面的内容

四、navigator

navigator对象主要用来获取浏览器的属性,区分浏览器类型,属性较多,且兼容性比较复杂

五,screen

六、history

15.JavaScript本地存储的方式有哪些?区别及应用场景?

JavaScript 本地缓存的方法有四种

cookie、sessionStorage、localStorage、indexedDB

cookie

Cookie 类型为 小型文本文件,指某些网站为了辨别用户身份而储存在用户本地终端上的数据,是为了解决http无状态导致的问题,一般不超过4kb的小型文本数据,由一个name、一个值value和其它几个用于控制cookie有效期、安全性、使用范围的可选属性组成,但是cookie每次请求都会被发送,如果不使用https并对其加密,其保存的信息很容易被窃取,导致安全风险,

localStorage

新方法,IE8及以上浏览器都兼容

· 特点;

生命周期:持久化的本地储存,除非主动删除数据,否则数据是永远不会过期的

存储的信息在同一域中是共享的

当本页操作新增、删除、修改了localStorage的时候,本页面不会触发storage事件,但是别的页面会触发storage事件

大小:5M (跟浏览器厂商有关系)

localStorage本质上是对字符串的读取,如果存储的内容多会消耗内存空间会导致页面变卡,

受到同源策略的限制

localStorage两个缺点:

无法像cookie 一样设置过期时间

只能存入字符串,无法直接存对象

sessionStorage

sessionStorage 和 localStorage使用方法基本一致唯一不同的是声明周期,一旦页面关闭之后sessionStorage将会删除数据

拓展:

indexedDB是一种低级API,用于客户端储存大量结构化数据,该api使用索引来实现对数据的高性能搜索,

优点:

储存量理论上没有上限

所有操作都是异步的,相比localStorage同步操作性能更高,尤其是数据量较大时

原生支持储存JS的对象

是个正经的数据库,意味着数据库能干的事都能干

缺点:

操作非常繁琐

本身有一定门槛

使用步骤:

打开数据库并且开始一个事务

创建一个object store

9 构建一个请求来执行一些数据库操作,像增加或提取数据

通过监听正确类型的dom事件以等待操作完成,

在操作结果上进行一些操作(可以在request对象中找到)

cookie、sessionStorage、localStorage三者的区别主要如下

储存大小: cookie数据大小不能超过4k,sessionStorage和localStorage存储大小可以达到5M或者更大

有效时间:localSorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除,sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的过期时间之前一直有效

数据与服务器之间的交互方式

cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端,sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存

应用场景

标记用户和跟踪用户行为 推荐使用cookie

长期保存在本地的数据或者令牌 建议使用localStorage

敏感账号一次性登录建议使用sessionstorage

储存大量数据、在线文档、保存编辑历史情况推荐使用indexedDB

16.什么是防抖和节流?有什么区别?如何实现?

防抖和节流本质上是优化高频率执行代码的一种手段

可以采用防抖和节流来降低调用的频率

定义:

防抖:

n秒后在执行该事件,若在n秒内被重复触发则重新计时

节流:

n秒内只运行一次,若在n秒内重复触发只有一次生效

区别:

相同点

都可以通过使用setTimeout实现,

目的都是,降低回调执行频率,节省计算资源

不同点

函数防抖 ,在一段连续操作结束后,处理回调,利用clearTimeout和setTimeout实现,

函数节流在一段连续操作中,每一段事件只执行一次,频率较高的事件中使用来提高性能

函数防抖关注一定事件连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次

应用场景:

防抖

搜索框搜索输入,用户输入完再次发送请求

手机号、邮箱验证

窗口大小,窗口调整完成后在发送请求

节流

滚动加载,加载更多或者底部监听

搜索框,搜索联想功能

17.如何通过js判断一个数组?

__ proto __

实例的__ proto__属性指向其构造函数的原型对象.

const arr = [1,2,3]
console.log(arr.__proto__ === Array.prototype)  // true

constructor

实例的constructor属性指向构造函数本身

const arr = [1,2,3]
console.log(arr.constructor === Array)  // true

instanceof

instanceof可以判断Array是否是实例的构造函数(在原型链上即可)

isPrototypeOf()

判断Array的原型对象是否为在某个对象的原型链上

const arr = [1,2,3]
console.log(Array.prototype.isPrototypeOf(arr) )  // true

const arr = [1,2,3]
console.log(arr instanceof Array) // true

通过Object原型上的方法判断

Array.isArray()

es6中用于判断数组类型的方法

console.log(arr instanceof Array) // true

Object.prototype.toString

Object原型对象上的方法,被所有对象继承,返回'[Object type]'字符串

console.log(Object.prototype.toString.call(arr))  // [object Array]

18.作用域链的理解

作用域、即变量作用域又称上下文和函数生效的区域或集合

作用域分成 全局作用域、函数作用域、块级作用域

全局作用域

任何不再函数中或是大括号中声明的变量都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问

函数作用域

函数作用域也叫局部作用域,如果一个变量是在函数内部声明它就是在一个函数作用域下面,只能在函数内部访问,外部访问不到

块级作用域

es6中引入的let 和 const 关键字,和var不同在大括号中使用let和const声明的变量存在于块级作用域中,大括号外访问不到这些变量

词法作用域

又叫静态作用域,变量被创建时就确定好了,而非执行阶段确定的,也就是说写好代码时它的作用域就确定了,JavaScript遵循的就是词法作用域

作用域链:

JavaScript中使用一个变量的时候,首先JavaScript引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到该变量或是已经到了全局作用域

如果在全局作用域里仍然找不到该变量,他就会在全局范围内隐式声明该变量,或者直接报错

变量的引用会顺着作用域连进行查找,找不到则会往上一层找,一但到达顶层查找的过程都会停止

19.JavaScript原型,原型链?有什么特点?

JavaScript常被描述为一种基于原型的语言,每个对象拥有一个原型对象

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索直到找到一个名字匹配的属性或达到原型链的顶层

准确的说,这些属性和方法定义在Object的构造器函数,(coustrtuctor functions) 之上的prototype属性上,而非实例对象本身

原型队形有一个自有属性constructor 这个属性指向该函数

二、原型链

原型对象也可能拥有原型,并从中继承方法和属性,一层一层一次类推,这种关系常被称为原型链

对象实例和它的构造器之间建立一个链接 proto属性,是从构造函数的prototype属性派生的,之后通过上溯原型链在构造器中找到这些属性和方法,

构造函数

总结

proto 作为不同对象之间的桥梁,用来指向创建它的构造函数的原型对象,每个对象的__proto__都是指向它的构造函数的原型对象prototype

一切对象都是继承Object对象,object对象直接继承根源对象null

一切的函数对象包括Object对象 都是继承Function对象

Object对象直接继承自Function对象

Function对象的 会指向自己的原型对象最总还是继承自Object对象

20.解释一下什么是事件代理?

事件代理通俗来讲就是把一个元素响应的事件 的函数委托到另一个元素

事件流都会经过三个阶段 : 捕获阶段->目标阶段->冒泡阶段 而事件委托就是在冒泡阶段完成

事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素,当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数

总结:

适合事件委托的事件有:click,mousedown,mouseup,keydown,keyup,keypress 从上面应用场景中,我们就可以看到使用事件委托存在两大优点:

减少整个页面所需的内存,提升整体性能

动态绑定,减少重复工作

但是使用事件委托也是存在局限性:

focus,blur这些事件没有事件冒泡机制,所以无法进行委托绑定事件

mousemove,mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不合适于事件委托的

21.谈谈This对象的理解?

函数的this关键字在JavaScript中的表现略有不同,

this关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象

函数的调用方式决定了this的值(运行时绑定)

此外在严格模式和非严格模式之间也会有一些差别

绑定规则 ,根据不同的使用场合,this有不同的值,主要分为下面几种情况:

默认绑定,隐式绑定,new绑定,显示绑定

默认绑定

严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined 只有函数运行在非严格模式下,默认绑定才能绑定到全局对象,

隐式绑定

函数还可以作为某个对象的方法调用,这时this就指这个上级对象,this永远指向的是最后调用它的对象

new绑定

通过构建函数new关键字生成一个实例对象,此时this指向这个实例对象

显示绑定

apply()、call()、bind()是函数的一个方法,作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象

箭头函数

在ES6的语法中还提供了箭头函数语法,让我们在代码书写时就能确定this的指向

优先级

new绑定>显示绑定>隐式绑定>默认绑定

22.new操作符具体干了什么?

在JavaScript 中 new操作符用于创建一个给定构造函数的实例对象

流程:

创建一个新的对象obj

将对象与构建函数通过原型链连接起来

将构建函数中的this绑定到新建的对象obj上

根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理

23.null和undefined的区别?

null 为一个字面量,而undefined则为一个全局变量

null 指的是一个变量未指向任何对象,而undefined通常代表一个变量处于值未定义(未赋值)的状态

概念方面

undefined:一般是简单数据类型,表示此处应该有个值,但是当前尚未赋值,

null 一般是复杂数据类型,表示不存在

用途方面:

undefined 返回执行之后无返回值,获取对象不存在的属性值,null原型链的最顶部的不存在对象

24.JavaScript代码中得 use strict 是什么意思?

use strict 是一个字符串字面量,用来指定代码运行于严格模式下,

25.同步和异步的区别?

同步时阻塞模式,异步是非阻塞模式

同步:

是指一个进程在执行某个请求的时候,如果该请求需要一段时间才能返回信息,那么这个进程会一直等下去,直到收到返回信息才继续执行下去

异步是指进程不需要一直等待下去,而是继续执行下面的操作不管其他进程的状态,当有信息返回时通知进程处理,提高执行效率

26.箭头函数和普通函数的区别?

this指向问题

箭头函数的this指向上层函数作用域的this对象,如果没有上层函数作用域,则指向顶部this(window) ,普通函数的this指向该函数的调用者,call,apply。bind 会改变篇普通函数的this,不能改变箭头函数的this

外形不同

箭头函数使用箭头定义,普通函数中没有

箭头函数是匿名函数,不能作为构造函数,不可以使用new

箭头函数不绑定arguments 在函数体中不存在,使用rest参数替代

箭头函数内 不能用yield且不能用作Generator函数,而普通函数可以

27.js数组和对象的遍历方式,以及几种方式的比较?

forEach

这里的forEach回调,中两个参数分别是value,index

forEach 无法遍历对象 IE不支持该方法 firefox 和 chrome支持

forEach 无法使用 break,continue 跳出循环,且使用return 是跳过本次循环

for in 循环 for 循环

这两种方法应该非常常见且使用很频繁,但实际上,两种方法都存在性能问题

for in 需要分析出array的每个属性,这个操作性能开销很大,用在key已知的数组上市非常不划算的,所以尽量不要使用for in 除非你不清楚要处理哪些属性

for 循环 循环每进行一次,就要检查一下数组的长度,读取属性要比读局部变量慢,尤其是当array里存放的都是dom元素,因为每次读取都会扫描一遍页面上的选择器相关元素,速度会大大降低

28.如何解决跨域问题?

跨域指的是浏览器不能执行其他网站的脚本,他是由浏览器的同源策略造成的,是浏览器加的安全限制

同源就是协议、域名和端口都相同。

跨域问题的四种解决方案

跨域资源共享(cors)

浏览器将cors请求分成两类:简单请求和预检请求

解决方式就是服务端在响应头中加入字段 Access-contro-allowl-origion:

ajax 的 jsonp

jsonp 是json 的一种使用模式 用于解决主流浏览器的跨域数据访问的问题

可以让所有人都能去访问 但是只是支持get请求

前端框架操作

修改配置文件 中的proxy 属性进行配置前端跨域

跨域问题只存在于浏览器,如果是服务器和服务器之间的通讯是不存在跨域问题的

可以再前端框架中设置代理服务器实现跨域请求

29.XML和JSON的区别

json 是一种轻量级的数据交换格式,它完全独立于语言。它基于JavaScript编程语言,易于理解和生成

xml 可扩展标记语言,用于传输数据并不是显示数据,这是W3C的推荐 ,它定义了一组规则,用于以人类可读和机器可读的格式编码文档,侧重于internet上的简单性通用性和可用性 是一种文本数据格式

json和xml之间的一些区别:

json是基于JavaScript语言 xml 源自于SGML

json是一种表示对象的方式,xml是一种标记语言,使用标记结构来表示数据项

json不提供对命名空间的任何支持,xml支持名称空间,

json支持数组,xml 不支持数组

xml文件相对难以阅读和解释,与xml相比,json的文件非常易于阅读

json不适用结束标记,xml有开始和结束标签

json的安全性较低,xml比json更安全

json 不支持注释,xml支持注释

json仅支持utf8编码 xml支持各种编码

30.谈谈你对webpack的看法

webpack 是一个模块打包工具 使用webpack管理模块 并分析模块之间的依赖关系,最终编译输出模块为HTML JavaScript CSS以及各种静态文件 让开发过程更加高效,对于不同类型的资源,webpack 有模块加载器对模块包分析他们之间的依赖关系,最终优化合并为静态资源

31.webpack的打包原理

初始化参数,从配置文件和shell语句中读取与合并参数,得出最终的参数

开始编译 用上一步得到的参数初始化 Compiler对象,加载所有配置的插件,执行对象的run方法开始执行编译

确定入口 根据配置中的entry找出所有的入口文件

编译模块 从入口文件出发 调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理

完成模块编译 在经过第4步使用Loader翻译完所有模块后,得到了每个模块被编译后的最终内容以及它们之间的依赖关系

输出资源 根据入口和模块之间的依赖关系,组成一个个包含多个模块的Chunk 再把每个Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后步骤

输出完成 确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写到文件系统

32.如何优化webpack的打包速度

webpack中每个模块有唯一的id 是从0开始递增的,整个打包以后的bundle.js 是一个匿名函数自执行,参数则为一个数组,数组的每一项都为个function,function的内容则为每个模块的内容,并按照require的顺序排列

我们看到webpack_require 是模块加载函数,接收模块id

a依赖b 所以在a中调用webpack加载模块的函数

33.说说webpack中常见的loader? 解决了什么问题?

Loader 用于对模块的 源代码进行转换 ,在import 或 加载 模块时预处理文件,在遇到import 或者require 加载模块的时候,webpack只支持对js和json 文件打包 像css,sass,png,这些类型的 文件的时候

webpack则无能为力,这时候就需要配置对应的loader进行文件内容的解析,

关于配置loader的方式有三种

配置方式:在webpack.config.js 文件中指定Loader

内联方式: 在每个import 语句中显式指定loader

li方式 :在shell命令中指定它们

css-loader:分析css模块之间的关系,合并成一个css

style-loader:把css-loader生成的内容,用style 标签挂载到页面的head中

34.说说webpack中常见的plugin? 解决了什么问题?

Plugin 是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能,是一种遵循一定规范的应用程序接口编写出来的程序,只能运行在程序规定的系统下,因为其需要调用原纯净系统提供的函数库或者数据

htmlwebpackPlugin 在打包结束后 自动生成一个html文件,并打包生成js模块引入到该html中

clean-webpack-plugin 删除 构建目录

mini-css-extract-plugin:提取css到一个单独的文件中

defineplugin 允许在编译时创建配置的全局对象,是一个webpack内置的插件,不需要安装

copy-webpack-plugin 复制文件或目录到执行区域,如vue的打包过程中,如果我们将一些文件放到public的目录下,那么这个目录会被复制到dist文件夹中

35.说说你对promise的了解?

promise是异步编程的一种解决方案,比其他 传统的解决方法更合理更强大,ES6将其写进了语言标准,统一了用法 promise对象是一个构造函数,用来生成promise实例

promise 的实例有三个状态

pending(进行中)

Resolved (已完成)

Rejected(已拒绝)

把一件事情交给promise时 他的状态就是Pending,任务完成了状态就会变成Resolved 失败变成Rejected

promise 的实例有两个过程:

pending -> fulfilled : Resolved 已完成

pending-> rejected: Rejected 已拒绝

promise 的特点:

对象的状态不受外界影响,只有异步操作的结果,可以决定当前是那种状态

一旦状态改变(从pending变为fulfilled和从pending变为rejected)就不会再变,任何时候都可以得到这个结果

实例方法:

then() 实例状态发生改变时的回调函数 ,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,then返回的是一个新的Promise实例

catch()

用于指定发生错误时的回调函数

finally()

用于指定不管promise对象最后状态如何都会执行的操作

构造函数的方法

all()、rece()、allSetted()、resolve()、reject()、try()

36.async函数是什么?有什么作用

async 函数是异步的一种方案,可以让异步的操作同步执行。

声明形式

在函数前加上关键字async表示该函数是一个async 函数 函数内部通常有await

内置执行器

Generator函数的执行必须靠执行器,所以有了co模块,而async函数自带执行器,也就是说,async函数与普通函数一模一样

更好的语义

async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

更广的适用性

co模块决定,yield命令后面只能是Thunk函数或Promise对象,而async函数的await命令后面,可以是Peomise对象和原始类型的值

返回值是Promise

async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖

基本用法:

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句

37.有使用过vue吗? 说说你对vue的理解?

vue是什么?

Vue.js(/vjuː/,或简称为Vue)是一个用于创建用户界面的开源JavaScript框架,也是一个创建单页应用的Web应用框架

vue核心特性

数据驱动(MVVM)

组件化

什么是组件化

一句话来说就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,在Vue中每一个.vue文件都可以视为一个组件

组件化优势:

降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,例如输入框,可以替换为日历、时间、范围等组件作具体的实现

调试方便,由于整个系统是通过组件组合起来的,在出现问题的时候,可以用排除法直接移除组件,或者根据报错的组件快速定位问题,之所以能够快速定位,是因为每个组件之间低耦合,职责单一,所以逻辑会比分析整个系统要简单

提高可维护性,由于每个组件的职责单一,并且组件在系统中是被复用的,所以对代码进行优化可获得系统的整体升级

指令系统

指令 是带有 v- 前缀的特殊属性作用:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM/

常用的指令

条件渲染指令 v-if

列表渲染指令v-for

属性绑定指令v-bind

事件绑定指令v-on

双向数据绑定指令v-model

Vue跟传统开发的区别

Vue所有的界面事件,都是只去操作数据的,Jquery操作DOM

Vue所有界面的变动,都是根据数据自动绑定出来的,Jquery操作DOM

Vue和React对比

相同点:

都有组件化思想

都支持服务器端渲染

都有Virtual DOM(虚拟dom)

数据驱动视图

都有支持native的方案:VueweexReactReact native

都有自己的构建工具:Vuevue-cliReactCreate React App

区别:

数据流向的不同。react从诞生开始就推崇单向数据流,而Vue是双向数据流

数据变化的实现原理不同。react使用的是不可变数据,而Vue使用的是可变的数据

组件化通信的不同。react中我们通过使用回调函数来进行通信的,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数

diff算法不同。react主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。Vue 使用双向指针,边对比,边更新DOM

38.你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢?

SPA(single-page application),翻译过来就是单页应用SPA是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中,所有必要的代码(HTMLJavaScriptCSS)都通过单个页面的加载而检索,或者根据需要(通常是为响应用户操作)动态装载适当的资源并添加到页面,页面在任何时间点都不会重新加载,也不会将控制转移到其他页面

单页面(SPA)与多页面(MPA)用的区别

单页面

由一个主页面和多个页面片段组成

刷新方式 局部刷新

url模式 哈希模式

SEO搜索引擎优化 难实现,可使用SSR方式改善

数据传递 比较容易

页面切换 速度快,用户体验良好

维护成本相对容易

多页面

多个页面组成

刷新方式 整页刷新

url 模式 历史模式

SEO搜索引擎优化 比较容易实现

数据传递 通过url、cookie、localStorage等传递

页面切换 切换加载资源速度慢,用户体验差

维护成本 相对复杂

单页面优点:

具有桌面应用的即时性、网站的可移植性和可访问性

用户体验好、快,内容的改变不需要重新加载整个页面

良好的前后端分离,分工更明确

缺点:

不利于搜索引擎的抓取 首次渲染速度相对较慢

实现一个SPA

原理

监听地址栏中hash变化驱动界面变化

pushsate记录浏览器的历史,驱动界面发送变化

39.SPA首屏加载速度慢的怎么解决?

什么是首屏加载?

首屏时间,指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容。首屏加载可以说是用户体验中最重要的环节。

SPA首屏加载时间慢的原因?

网络延时问题

资源文件体积是否过大

资源是否重复发送请求去加载了

加载脚本的时候,渲染内容堵塞了

解决方案

减少入口文件体积

常用手段是路由懒加载,把不同路由对应的组件分割成不同的代码块,等路由被请求的时候会单独打包路由,使入口文件变小,加载速度增加

静态资源本地缓存

后端返回资源问题

采用HTTP缓存 设置Cache-Control,Last-Modified,Etag响应头

采用Service Worker离线缓存

前端合理利用localStorage

UI框架按需加载

在日常使用UI框架,例如element-UI、或者antd,我们经常性直接引用整个UI库实际用到的组件只有几个,所以我们要按需在js文件中设置并引用

图片资源的压缩

图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素

对于所有的图片资源,我们可以进行适当的压缩

对页面上使用到的icon,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻http请求压力

组件重复打包

开启Gzip压缩

拆完包之后,我们再用gzip做一下压缩 安装compression-webpack-plugin

在vue.config.js中引入并修改webpack配置

使用SSR

SSR(Server side ),也就是,组件或页面通过服务器生成html字符串,在发送到浏览器从头搭建一个服务端渲染是很复杂的,vue应用建议使用Nuxt.js 实现服务端渲染

40.vue 路由原理

vue-router 提供三种路由模式

hash模式

默认模式,通过路径中的hash值来控制路由跳转,不存在兼容问题

history模式

H5新增的history API 相对hash而言,不会显示#号,但是需要服务器端配置

abstract模式

支持JavaScript的所有运行环境,常指Node.js服务器环境

hash模式实现原理

在正常路径后跟一个 # 号,匹配 # 后边的路径为前端路由,通过window.onhashchange方法来操控路由改变的时候切换内容

onhashchange 方法的触发机制

直接更改浏览器地址,在最后面增加或改变#hash;

通过改变location.href或location.hash的值;

通过触发点击带锚点的链接;

浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。

history模式实现原理

window.history这个对象中,包含浏览器的历史,而在HTML5中,新增了 history.pushStatehistory.replaceState,通过这两个API可以改变url地址且不会发送请求,同时还有window.onpopstate事件,实现原理与hash相似,只不过因为没有了 # 号,所以刷新页面还是会向服务器发送请求,而后端没有对应的处理措施的话,会返回404

onpopstate事件的触发时机

仅仅调用pushState方法或replaceState方法 ,并不会触发该事件;

只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。

另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

abstract模式实现原理

abstract模式是不依赖于浏览器环境,所以没有使用hash或者history等浏览器才会提供的API,而是VueRouter内部使用数组进行模拟了路由管理,在node环境,或者原生App环境下,都会默认使用abstract模式,VueRouter内部会根据所处的环境自行判断,默认使用hash模式,如果检测到没有浏览器API的时候,就会使用abstract模式

41.vue中组件和插件有什么区别?

组件是什么?

组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念来实现开发的模式,在Vue中每一个.vue 文件都可以看成一个组件

插件是什么?

插件通常用来为Vue添加全局功能,插件的功能范围没有严格的限制

两者的区别:

编写形式

编写一个组件,可以有很多方式,我们最常见的就是vue单文件的这种格式,每一个.vue文件我们都可以看成是一个组件 vue插件的实现应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象

注册形式

vue组件注册主要分为全局注册与局部注册

全局注册通过Vue.component方法,第一个参数为组件的名称,第二个参数为传入的配置项

局部注册只需在用到的地方通过components属性注册一个组件

插件的注册通过Vue.use()的方式进行注册(安装),第一个参数为插件的名字,第二个参数是可选择的配置项

注意事项

注册插件的时候,需要在调用 new Vue() 启动应用之前完成

Vue.use会自动阻止多次注册相同插件,只会注册一次

使用场景

组件 (Component) 是用来构成你的 App 的业务模块,它的目标是 App.vue

插件 (Plugin) 是用来增强你的技术栈的功能模块,它的目标是 Vue 本身

简单来说,插件就是指对Vue的功能的增强或补充

42.Vue组件之间的通信方式都有哪些?

vuex

State:放状态的地方

Mutation:唯一修改状态的地方,不支持异步

· Action:通过调用Mutation中的方法来达到修改状态的目的,支持异步

Getter:可以理解为计算属性

Module:模块每个模块拥有自己的 state、mutation、action、getter

父子组件间通信

子组件通过 props 属性来接受父组件的数据,然后父组件在子组件上注册监听事件,子组件通过 emit 触发事件来向父组件发送数据

通过 ref 属性给子组件设置一个名字。父组件通过 $refs 组件名来获得子组件,子组件通过 $parent 获得父组件,这样也可以实现通信

vue3新增加的 使用 provide/inject,在父组件中通过 provide提供变量,在子组件中通过 inject 来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provide中的数据

兄弟组件间通信

使用 eventBus 的方法,它的本质是通过创建一个空的 Vue 实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过在这个实例上监听和触发事件,来实现消息的传递

通过 $parent / $refs 来获取到兄弟组件,也可以进行通信。

任意组件间通信

使用 eventBus ,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件

43. 你了解vue的diff算法吗?说说看

diff算法是什么?

diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。

换句话说就是 diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁

两个特点

比较只会在同层级进行, 不会跨层级比较

在diff比较的过程中,循环从两边向中间比较

diff算法的步骤

用 JavaScript 对象结构表示

标签: 微压压力变送器留言

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台