前端面试题

2023-05-16

浏览器


输入一个URL到页面过程中发生了什么(高频)

  1. 首先在浏览器中输入URL

  1. 查找缓存:浏览器先查看浏览器缓存-系统缓存-路由缓存中是否有该地址页面,如果有则显示页面内容。如果没有则进行下一步。

  1. DNS域名解析:浏览器向DNS服务器发起请求,解析该URL中的域名对应的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议。

  1. 建立TCP连接:解析出IP地址后,根据IP地址和默认80端口,和服务器建立TCP连接

  1. 发起HTTP请求:浏览器发起读取文件的HTTP请求,该请求报文作为TCP三次握手的第三次数据发送给服务器

  1. 服务器响应请求并返回结果:服务器对浏览器请求做出响应,并把对应的html文件发送给浏览器

  1. 关闭TCP连接:通过四次挥手释放TCP连接

  1. 浏览器渲染:客户端(浏览器)解析HTML内容并渲染出来,浏览器接收到数据包后的解析流程为:

  • 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象

  • 构建CSS规则树:生成CSS规则树(CSS Rule Tree)

  • 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)

  • 布局(Layout):计算出每个节点在屏幕中的位置

  • 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。

浏览器渲染机制、重绘、重排

网页生成的过程:

  • 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象

  • 构建CSS规则树:生成CSS规则树(CSS Rule Tree)

  • 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)

  • 布局(Layout):计算出每个节点在屏幕中的位置

  • 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。

重排:当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。

触发条件:

  1. 添加或者删除可见的DOM元素

  1. 元素尺寸改变——边距、填充、边框、宽度和高度

重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。

触发条件:改变元素的color、background、box-shadow等属性

HTML相关


常见的语义化标签

header nav main article section aside footer

语义化的优点如下:

  • 对机器友好,带有语义的文字表现力丰富,更适合搜索引擎的爬虫爬取有效信息,有利于SEO。除此之外,语义类还支持读屏软件,根据文章可以自动生成目录;

  • 对开发者友好,使用语义类标签增强了可读性,结构更加清晰,开发者能清晰的看出网页的结构,便于团队的开发与维护

H5新特新

  1. 语义化标签

  1. 媒体标签

  1. 表单

  1. DOM查询操作

  1. Web存储

  1. 拖拽

  1. ...

script标签中defer和async的区别

多个带async属性的标签,不能保证加载的顺序;多个带defer属性的标签,按照加载顺序执行;

async属性,表示后续文档的加载和执行与js脚本的加载和执行是并行进行的,即异步执行;defer属性,加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本需要等到文档所有元素解析完成之后才执行,DOMContentLoaded事件触发执行之前。

CSS相关


盒模型(高频)

盒模型都是由四个部分组成的,分别是margin、border、padding和content。

  • 标准盒模型的width和height属性的范围只包含了content,

  • IE盒模型的width和height属性的范围包含了border、padding和content。

HTML 各块级,行内元素

https://blog.csdn.net/qq_42952262/article/details/103834029

块级元素

容器级标签:div , h系列 , li , dt ,dd

  1. 总是从新的一行开始

  1. 高度、宽度都是可控的

  1. 宽度没有设置时,默认为100%

  1. 块级元素中可以包含块级元素和行内元素

行内元素

文本级标签:p , span , a , b , i , u , em

  1. 和其他元素都在一行

  1. 高度、宽度以及内边距都是不可控的

  1. 宽高就是内容的高度,不可以改变

  1. 行内元素只能行内元素,不能包含块级元素

块级元素和行内元素的相互转换

  我们可以通过display属性将块级元素(比如div)和行内元素进行相互转换。

  • display:inline;

  那么这个标签将变为行内元素,即:

    1,此时这个div将不能设置宽度和高度了。

    2,此时这个div可以和其他行内元素并排了。

  同样的到了我们也可以用display将行内元素(比如span)转行成块级元素。

  • display:block;

  那么这个span标签将变为块级标签,即:

    1,此时这个span能够设置宽度,高度。

    2,此时这个span必须独占一行,其他元素无法与之并排。

    3,如果不设置宽度,将占满父级。

其他

说一下浮动?

浮动的作用,设置浮动的图片,可以实现文字环绕图片,设置了浮动的块级元素可以排列在同一行,设置了浮动的行内元素可以设置宽高,同时可以按照浮动设置的方向对齐排列盒子。

设置浮动元素的特点:

· 设置了浮动,该元素脱标。元素不占位置

· 浮动可以进行模式转换(行内块元素)

浮动造成的影响,使盒子脱离文档流,如果父级盒子没有设置高度,需要被子盒子撑开,那么这时候父级盒子的高度就塌陷了,同时也会造成父级盒子后面的兄弟盒子布局受到影响。如果浮动元素后面还有其他兄弟元素,其他兄弟元素的布局也会受到影响。

清除浮动:

  • 伪元素清除浮动:不会新增标签,不会有其他影响,是当下清除浮动最流行的方法

  • overflow:hidden:不会新增标签,超出部分会隐藏,在不涉及父级元素有超出内容的情况,overflow:hidden比较常用,毕竟写法方便简洁

  • 额外标签 {clear: both} ==> 添加多余标签,造成页面混乱

简单说说HTML的语义化

主要是以下几点:

  • 正确的标签做正确的事情(精辟)

  • 页面内容结构化

  • 无CSS样子时也容易阅读,便于阅读维护和理解

  • 便于浏览器、搜索引擎解析。 利于爬虫标记、利于SEO

flex常用属性(高频)

  1. flex-direction属性决定主轴的方向(即项目的排列方向)。

  1. flex-wrap属性定义,如果一条轴线排不下,如何换行。

  1. flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。

  1. justify-content属性定义了项目在主轴上的对齐方式。

  1. align-items属性定义项目在交叉轴上如何对齐。

  1. align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

position属性

  1. 固定定位 fixed: 元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。Fixed 定 位使元素的位置与文档流无关,因此不占据空间。 Fixed 定位的元素和其他元素重叠。

  1. 相对定位 relative: 如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直 或水平位置,让这个元素“相对于”它的起点进行移动。 在使用相对定位时,无论是 否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。

  1. 绝对定位 absolute: 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那 么它的位置相对于。absolute 定位使元素的位置与文档流无关,因此不占据空间。 absolute 定位的元素和其他元素重叠。

  1. 粘性定位 sticky: 元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。而后,元素定位表现为在跨越特定阈值前为相对定 位,之后为固定定位。

  1. 默认定位 Static: 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声 明)。 inherit: 规定应该从父元素继承 position 属性的值。

transition和animation的区别

transition是过度属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于flash的补间动画,设置一个开始关键帧,一个结束关键帧。animation是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于flash的补间动画,但是它可以设置多个关键帧(用@keyframe定义)完成动画。

CSS3中有哪些新特性

新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)

1.圆角 (border-radius:8px)

2.多列布局 (multi-column layout)

3.阴影和反射 (Shadoweflect)

4.文字特效 (text-shadow)

5.文字渲染 (Text-decoration)

6.线性渐变 (gradient)

7.旋转 (transform) 增加了旋转,缩放,定位,倾斜,动画,多背景

隐藏元素的方法有哪些

1.使用display: none; 隐藏dom;

2.使用visibility: hidden; 隐藏dom;

3.使用z-index: -888; 把元素的层级调为负数,然后其他元素覆盖即可;

4.使用opacity: 0; 把元素的透明度调为0,也可以达到隐藏;

5.使用固定定位position: absolute; 把元素定位到看不见的区域;

6.使用transform: scale(0, 0); 把元素缩放为0,也可以实现元素隐藏。

盒子水平垂直居中方法(高频)

1.利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心

2.利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况

3.利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况

4.使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中

CSS样式优先级

  • !important

  • 内联样式(1000)

  • ID选择器(0100)

  • 类选择器(0010)

  • 元素选择器(0001)

  • 通配符选择器(0000)

JS相关


JS的数据类型

基本类型:

Number、String、Boolean、Null、undefined、Symbol

复杂类型:

Object、Array、Function

JS的类型检测(高频)

typeof

instanceof

Object.prototype.toString.call()

作用域和作用域链

作用域负责收集和维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。(全局作用域、函数作用域、块级作用域)。 作用域链就是从当前作用域开始一层一层向上寻找某个变量,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链。

原型和原型链(高频)

原型:

  • 每个 class都有显示原型 prototype

  • 每个实例都有隐式原型 _ proto_

  • 实例的_ proto_指向对应 class 的 prototype

原型链: 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念

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

闭包(高频)

闭包是指有权访问另一个函数作用域中的变量的函数 ——《JavaScript高级程序设计》当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行 ——《你不知道的JavaScript》

闭包形成的条件

  1. 函数的嵌套

  1. 内部函数引用外部函数的局部变量,延长外部函数的变量生命周期

闭包用途:

  1. 能够访问函数定义时所在的词法作用域(阻止其被回收)

  1. 私有化变量

  1. 模拟块级作用域

  1. 创建模块

闭包缺点:会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏

EventLoop(高频)

JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,Promise.then,MutationObserver,宏任务的话就是setImmediate setTimeout setInterval

new运算符的实现机制

  1. 首先创建了一个新的空对象

  1. 设置原型,将对象的原型设置为函数的prototype对象。

  1. 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)

  1. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

深拷贝和浅拷贝

JavaScript有两种数据类型,基础数据类型和引用数据类型。基础数据类型都是按值访问的,我们可以直接操作保存在变量中的实际的值。而引用类型如Array,我们不能直接操作对象的堆内存空间。引用类型的值都是按引用访问的,即保存在变量对象中的是一个地址,该地址与堆内存的实际值相关联。参考:JavaScript 基础数据类型和引用数据类型

1、深拷贝和浅拷贝的区别

  • 浅拷贝(shallow copy):只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存。

  • 深拷贝(deep copy):复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。

2、浅拷贝的实现

浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用(地址),所以改变新对象,旧对象也会改变,因为新旧对象共享一块内存。

通过 Object.assign() 拷贝 Object.assign(目标文件, 原文件) 浅拷贝的方法

注意:

  • 当对象只有一级属性为深拷贝;

  • 当对象中有多级属性时,二级属性后就是浅拷贝;

<script>

// 浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用(地址)

varobj= {

id: 1,

name: 'andy',

msg: {

age: 18

}

};

varo= {};

// for (var k in obj) {

// // k 是属性名 obj[k] 属性值

// o[k] = obj[k];

// }

// console.log(o);

// o.msg.age = 20;

// console.log(obj);

console.log('--------------');

// Object.assign(目标文件, 原文件) 浅拷贝的方法

Object.assign(o, obj);

console.log(o);

o.msg.age=20;

console.log(obj);

// 结果就是 o 和 obj 的 msg.age 都变成了20, 因为 o 和 obj 是共享一块内存的

</script>

1234567891011121314151617181920212223242526

3、深拷贝的实现

深拷贝的原理:复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。

3.1 递归遍历所有层级,实现深拷贝

我们采用递归的方式来封装实现深拷贝的函数。

// 1. 使用递归的方式实现深拷贝

// 深拷贝拷贝多层, 每一级别的数据都会拷贝.

varobj= {

id: 1,

name: 'andy',

msg: {

age: 18

},

color: ['pink', 'red']

};

varo= {};

// 封装函数

functiondeepCopy(newobj, oldobj) {

for (varkinoldobj) {

// 判断我们的属性值属于那种数据类型

// 1. 获取属性值 oldobj[k]

varitem=oldobj[k];

// 2. 判断这个值是否是数组(首先判断数组是因为数组也属于对象)

if (iteminstanceofArray) {

newobj[k] = [];

deepCopy(newobj[k], item);

} elseif (iteminstanceofObject) {

// 3. 判断这个值是否是对象

newobj[k] = {};

deepCopy(newobj[k], item);

} else {

// 4. 属于简单数据类型

newobj[k] =item;

}

}

};

deepCopy(o, obj);

o.msg.age=20;

console.log(o);

console.log(obj); // obj.msg.age 还是等于 18 没有改变

vararr= [];

console.log(arrinstanceofObject); // true 数组也是对象

1234567891011121314151617181920212223242526272829303132333435363738

3.2 利用 JSON 对象实现深拷贝

// 深拷贝拷贝多层, 每一级别的数据都会拷贝.

varobj= {

id: 1,

name: 'andy',

msg: {

age: 18

},

color: ['pink', 'red']

};

// 2. 利用 JSON 对象

functiondeepCopy(obj) {

let_obj=JSON.stringify(obj);

letnewObj=JSON.parse(_obj);

returnnewObj;

}

letnewObj=deepCopy(obj);

newObj.msg.age=22;

console.log(newObj); // newObj.msg.age = 22

console.log(obj); // obj.msg.age 还是等于 18 没有改变

123456789101112131415161718192021

注意: 无法实现对象中方法的深拷贝。

3.3 通过 jQuery 的 extend 方法实现深拷贝

jQuery 的 extend 方法也可以拷贝对象。

$.extend([deep ], target, object1 [, objectN ])

1

  • deep:表示是否深拷贝,true,为深拷贝;false,为浅拷贝。

  • target:Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

  • object1: objectN 可选。 Object 类型 第一个以及第 N 个被合并的对象。

leta= [0,1,[2,3],4]

letb=$.extend(true, [], a)

a[0] =1

a[2][0] =1 // [1,1,[1,3],4]

b // [0,1,[2,3],4]

12345

3.4 Object.assign(),slice,concat 拷贝

当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。

(1)通过 Object.assign() 拷贝 Object.assign(目标文件, 原文件) 浅拷贝的方法

varobj= {a:1,b:2}

varnewObj=Object.assign({},obj)

12

(2)使用 concat 实现对数组的深拷贝

concat(arr1, arr2,....)

vararr= [1,2,3]

varnewArr= [].concat(arr)

1234

(3)使用 slice 实现对数组的深拷贝

slice(idx1, idx2)

1

vararr= [1,2,3]

varnewArr=arr.slice(0)

// slice 接受两个参数,第一个表示起始索引,第二个表示结束位置索引,省略时表示一直到末尾

123

参数可以省略

1)没有参数是拷贝数组

2)只有一个参数是从该位置起到结束拷贝数组元素

3)两个参数,拷贝从起始位置到结束位置的元素(不包含结束位置的元素:含头不含尾)

注意:

  • 当数组中的元素均为一维是深拷贝。

  • 数组中元素一维以上是值的引用。

3.5 lodash函数库实现深拷贝

lodash 很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝。

_.cloneDeep(value)

value : 要深拷贝的值。

返回拷贝后的值

vue中使用:

a. npmi--savelodash 下载依赖

b. import_from'lodash' 在组件中引入

c. 用法和下面的一样

varobjects= [{ 'a': 1 }, { 'b': 2 }];

vardeep=_.cloneDeep(objects);

console.log(deep[0] ===objects[0]);

// => false

1234567891011121314

参考:https://www.lodashjs.com/docs/lodash.cloneDeep

3.6 使用扩展运算符实现数组深拷贝

vara=[1,2,3]

varb=[...a];

b.push(4);

console.log(b);//1,2,3,4

console.log(a)//1,2,3

ES相关


var/let/const

  1. var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。 let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。

  1. var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。

  1. var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。

  1. 会产生暂时性死区:

https://es6.ruanyifeng.com/#docs/letes6.ruanyifeng.com/#docs/let

var tmp = 123;

if (true) {

// 存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,

所以在let声明变量前,对tmp赋值会报错

tmp = 'abc'; // ReferenceError

let tmp;

}

map 跟 forEach 的区别

map有返回值 forEach 没有返回值

常用的数组方法

不改变原数组

join()

参数:可选。指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符。

语法:*array.join(separator*)

返回值:转换后的字符串

使用场景:把数组转为字符串的方法

let arr = [1, 2, 3, 4]

let res = arr.join('')

console.log('res', res) // 1234

let res2 = arr.join(',')

console.log('res2', res2) // 1,2,3,4

concat()

语法:*array1.concat(array2,array3,...,arrayX*)

参数:必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。

返回值:返回新的数组

使用场景: 是连接多个数组的方法

let arr = [1, 2, 3]

let arr2 = [4, 5, 6]

let res = arr.concat(arr2)

console.log('res', res) // [1, 2, 3, 4, 5, 6]

// 可以使用ES6的"..."扩展运算符更简单

let res = [...arr, ...arr2] // [1, 2, 3, 4, 5, 6]

forEach()

语法:array.forEach(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:undefiend

使用场景:用于调用数组的每个元素

let arr = [1, 2, 3]

let res = []

arr.forEach((item, index) => {

res.push(item * 2)

})

console.log('res', res) // [2, 4, 6]

map()

语法:array.map(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:返回新的数组

使用场景:比如我们只想拿到arr数组中name

let arr = [

{

name: '轨迹',

year: '10'

},

{

name: '外婆',

year: '11'

},

{

name: '暗号',

year: '12'

}

]

const res = arr.map(item => item.name)

console.log('res', res) // ['轨迹', '外婆', '暗号']

filter()

语法:array.filter(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:返回(条件满足)新的数组

使用场景:过滤出想要的新数组

// 我们只想要告白气球,过滤掉其他的

let arr = [

{

name: '半岛铁盒',

year: '10'

},

{

name: '回到过去',

year: '11'

},

{

name: '告白气球',

year: '12'

}

]

const res = arr.filter(item => item.name === '告白气球')

console.log('res', res) // { name: '告白气球', year: 12 }

every()

语法:array.every(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:布尔值。如果所有元素都通过检测返回 true,否则返回 false。

使用场景:一个班级所有人的分数60分(含60分)以上就是优秀班级

注意点:如果有一个不通过就返回false,不会再进行检测。

let arr = [

{

name: '小明',

score: 90

},

{

name: '小红',

score: 88

},

{

name: '小花',

score: 70

}

]

const res = arr.every(item => item.score >= 60)

console.log('res', res) // true => 咱们班是优秀班级

some()

语法:array.some(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:布尔值。如果有一个元素满足就返回 true,否则返回 false。

使用场景:一个班级只要有一个人超过90分就是优秀班级啦

注意点:如果有一个通过就返回true,不会再进行检测。

let arr = [

{

name: '小明',

score: 90

},

{

name: '小红',

score: 100

},

{

name: '小花',

score: 70

}

]

const res = arr.some(item => item.score > 90)

console.log('res', res) // true => 小花同学好棒,超过了90咱们又是优秀班级啦

reduce()

语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数:total => 必需,初始值、或者计算结束后的值;currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象; initialValue => 可选,传递给函数的初始值

返回值:返回计算后的结果

使用场景:这个方法能实现的东西太多了,有兴趣的同学可以去百度看看,咱们这里就是实现一个常规的累加和吧

let arr = [1, 2, 3, 4]

const res = arr.reduce((pre, cur) => pre + cur, 0)

console.log('res', res) // 10

find()

语法:array.find(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:返回(条件满足)的元素

使用场景:返回第一个满足条件的元素,比如我们翻试卷,看看谁先超过90,有同学超过了,我们就看这同学的答案,我们就不会再往下看了。

注意点:只要有一个元素满足条件就返回当前元素,不会再进行检测;如果没有都没有满足条件就返回 undefined

let arr = [

{

name: '小明',

score: 99

},

{

name: '小红',

score: 100

},

{

name: '小花',

score: 70

}

]

const res = arr.find(item => item.score > 90)

console.log('res', res) // {name: '小明', score: 99}

findIndex()

语法:array.findIndex(function(currentValue, index, arr))

参数:currentValue => 必需,当前元素;index => 可选,当前元素索引;arr => 可选,当前元素所属的数组对象

返回值:返回(条件满足)的元素

使用场景:返回第一个满足条件的元素,比如我们翻试卷,看看谁先超过90,有同学超过了,我们就得到我们翻了第几张卷子,我们就不会再往下看了。

注意点:只要有一个元素满足条件就返回当前元素的索引,不会再进行检测;如果没有都没有满足条件就返回 -1

let arr = [

{

name: '小明',

score: 60

},

{

name: '小红',

score: 50

},

{

name: '小花',

score: 70

}

]

const res = arr.findIndex(item => item.score > 90)

console.log('res', res) // -1 => 没有同学达到条件所以返回了 -1

indexOf()

语法:*string.indexOf(searchvalue,start*)

参数:*searchvalue => 必需,规定检索的字符串; start => 可选,规定字符串开始检索的位置*

返回值:如果找到就返回第一次出现的索引,找不到就返回 -1

使用场景:咱们找出c的索引,然后去xxoo

let str = 'abcdefg'

const index = str.indexOf('c')

console.log('index', index) // 2

includes()

语法:string.includes(searchvalue, start)

参数:*searchvalue => 必需,规定检索的字符串; start => 可选,从那个位置开始查找,默认为0*

返回值:布尔值,找到就返回true,否则返回false

使用场景:如果检测的数组中有 彭于晏 那么就返回true

注意点:不区分大小写哟

let arr = ['胡歌', '彭于晏', '吴彦祖']

const res = arr.includes('彭于晏')

console.log('res', res) // true

slice()

语法:*array.slice(start,end*)

参数:start => 可选从那个位置开始选取,如果是负数就从数组的倒数第几个开始;end => 可选,从那个位置结束,如果不给参数则默认到数组的最后一个元素。

返回值:返回一个新的数组

使用场景:从开始到结束([)左闭右开,即不包括结束)选择数组的一部分浅拷贝到一个新数组。

const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(arr.slice(1, 5)); // [ 1, 2, 3, 4 ]

at()

语法:array.at(index)

参数:要返回的数组元素的索引(位置)。当传递负数时,支持从数组末端开始的相对索引;也就是说,如果使用负数,返回的元素将从数组的末端开始倒数。

返回值:匹配给定索引的数组中的元素。如果找不到指定的索引,则返回undefined

使用场景:取数组最后一个元素

let arr = ['珊瑚海', '发如雪', '黑色毛衣']

const res = arr.at(-1)

console.log('res', res) // 黑色毛衣

// ES5取最后一个元素

arr[arr.length - 1]

flat()

语法:array.flat(index)

参数:数值 默认是0

返回值:返回扁平后的数组

使用场景:把一个多维数组扁平

const arr = [1, [2]]

const res = arr.flat() // [1, 2]

// Infinity关键字参数

const arr1 = [1, [2, [3, [4, 5]]], 6]

const res2 = arr1.flat(Infinity)

console.log(names) // [1, 2, 3, 4, 5, 6]

fill()

语法:array.fill(value, start, end)

参数:value => 必需,填充的值;start => 可选,开始填充的位置;end, 可选,停止填充位置

返回值:返回新的数组

使用场景:把一个数组进行填充

let arr = ['珊瑚海', '发如雪', '黑色毛衣']

const res = arr.fill('爱在西元前')

console.log('res', res) // ['爱在西元前', '爱在西元前', '爱在西元前']

改变数组

push()

语法:*array.push(item1,item2, ...,itemX*)

参数:必需,要添加到数据的元素

返回值:新数组长度

使用场景:将元素添加到数组的末尾

let arr = []

arr.push('退后', '搁浅', '彩虹')

console.log('arr', arr) // ['退后', '搁浅', '彩虹']

pop()

语法:*array*.pop()

返回值:返回删除的元素

使用场景:删除数组最后的元素

let arr = ['青花瓷', '我不配', '甜甜的']

const res = arr.pop()

console.log('res', res) // 甜甜的

console.log('arr', arr) // ['青花瓷', '我不配']

shift()

语法:*array*.shift()

返回值:返回删除的元素

使用场景:删除数组第一个元素

let arr = ['说好不哭', '烟花易冷', '本草纲目']

const res = arr.shift()

console.log('res', res) // 说好不哭

console.log('arr', arr) // ['烟花易冷', '本草纲目']

unshift()

语法:*array.unshift(item1,item2, ...,itemX*)

参数:可选。向数组起始位置添加一个或者多个元素。

返回值:返回新数组的长度

使用场景:方法可向数组的开头添加一个或更多元素,并返回新的长度。

let arr = ['晴天', '暗号']

const res = arr.unshift('外婆')

console.log('res', res) // 3

console.log('arr', arr) // ['外婆', '晴天', '暗号']

splice()

语法:*array.splice(index,howmany,item1,.....,itemX*)

参数:index =>必需,从何处添加/删除元素;howmany => 可选,要删除几个元素,必需是数字,可以为0,如果不给参数则从index删除到数组的结尾 item1,.....,itemX => 可选,要添加到数组的新元素

返回值:如果是删除元素就返回含有被删除元素的数组

使用场景:数组可以在规定的位置删除/添加元素

let arr = ['听妈妈的话', '算什么男人', '黑色幽默', '可爱女人']

const res = arr.splice(1, 2, '千里之外', '反向的钟')

console.log('res', res) // ['算什么男人', '黑色幽默']

console.log('arr', arr) // ['听妈妈的话', '千里之外', '反向的钟', '可爱女人']

sort()

语法:*array.sort(sortfunction*)

参数:*sortfunction => 可选,规定排序顺序,必需可选*

使用场景:方法用于对数组的元素进行排序。

// 个位数直接 arr.sort() 就可以

let arr = [1, 6, 2, 9, 4]

arr.sort()

console.log('arr', arr) // [1, 2, 4, 6, 9]

// 非个位数

let arr = [40, 100, 1, 5, 25, 10]

arr.sort(function (a, b) {

return a - b // 如果是b - a 就是倒过来排序了

})

console.log('arr', arr) // [1, 5, 10, 25, 40, 100]

// 字母

let arr = ['Banana', 'Orange', 'Apple', 'Mango']

arr.sort()

console.log('arr', arr) // ['Apple', 'Banana', 'Mango', 'Orange']

reverse()

语法:*array*.reverse()

参数:

返回值:

颠倒顺序后的数组

使用场景:把一个数组的元素翻转过来

let arr = [1, 2, 3, 4, 5, 6]

const res = arr.reverse()

console.log('res', res) // [6, 5, 4, 3, 2, 1]

ES6常用的新特新

1.新增symbol类型 表示独一无二的值,用来定义独一无二的对象属性名;

2.const/let 都是用来声明变量,不可重复声明,具有块级作用域。存在暂时性死区,也就是不存在变量提升。(const一般用于声明常量);

3.变量的解构赋值(包含数组、对象、字符串、数字及布尔值,函数参数),剩余运算符(...rest);

4.模板字符串(${data});

5.扩展运算符(数组、对象);

6.箭头函数;

7.Set和Map数据结构;

8.Proxy/Reflect;

9.Promise;

10.async函数;

Vue相关


vue 的生命周期

create阶段:vue实例被创建 beforeCreate: 创建前,此时data和methods中的数据都还没有初始化 created: 创建完毕,data中有值,未挂载

mount阶段: vue实例被挂载到真实DOM节点 beforeMount:可以发起服务端请求,去数据 mounted: 此时可以操作Dom

update阶段:当vue实例里面的data数据变化时,触发组件的重新渲染 beforeUpdateupdated

destroy阶段:vue实例被销毁 beforeDestroy:实例被销毁前,此时可以手动销毁一些方法 destroyed

vue 的通讯方式

父子组件通讯 props $emit parent、children Ref

兄弟之间通讯 event bus

跨组件通讯 $attrs、$listeners Provide、inject

vuex

computed与watch

watch 属性监听 是一个对象,键是需要观察的属性,值是对应回调函数,主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,监听属性的变化,需要在数据变化时执行异步或开销较大的操作时使用

computed 计算属性 属性的结果会被缓存,当computed中的函数所依赖的属性没有发生改变的时候,那么调用当前函数的时候结果会从缓存中读取。除非依赖的响应式属性变化时才会重新计算,主要当做属性来使用 computed中的函数必须用return返回最终的结果 computed更高效,优先使用。data 不改变,computed 不更新。

使用场景computed:当一个属性受多个属性影响的时候使用,例:购物车商品结算功能 watch:当一条数据影响多条数据的时候使用,例:搜索数据

v-if 和 v-for 的优先级

v-for的优先级是高于v-if的,如果两者同时出现的话,那每次循环都会执行v-if,会很浪费性能,我们正确的做法应该是再v-for的外面新增一个模板标签template,在template上使用v-if

$nextTick

  1. nextTick是Vue提供的一个全局API,是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的DOM;

  1. Vue在更新DOM时是异步执行的。只要侦听到数据变化,Vue将开启1个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中-次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。nextTick方法会在队列中加入一个回调函数,确保该函数在前面的dom操作完成后才调用;

  1. 比如,我在干什么的时候就会使用nextTick,传一个回调函数进去,在里面执行dom操作即可;

  1. 我也有简单了解nextTick实现,它会在callbacks里面加入我们传入的函数,然后用timerFunc异步方式调用它们,首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。

v-for中key的作用

  1. key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度,更高效的更新虚拟DOM;

  1. Vue在patch过程中判断两个节点是否是相同节点,key是一个必要条件,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,Vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能;

  1. 从源码中可以知道,Vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永 远认为这是两个相同的节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。

keep-alive的实现

作用:实现组件缓存

钩子函数: ”activated “组件渲染后调用 ”deactivated“组件销毁后调用

原理:Vue.js内部将DOM节点抽象成了一个个的VNode节点,keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件(pruneCache与pruneCache)的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。

配置属性: include 字符串或正则表达式。只有名称匹配的组件会被缓存 exclude 字符串或正则表达式。任何名称匹配的组件都不会被缓存 max 数字、最多可以缓存多少组件实例

Vuex

Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。

  1. Vuex 的状态存储是响应式的;当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新

  1. 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation, 这样使得我们可以方便地跟踪每一个状态的变化 Vuex主要包括以下几个核心模块:

  1. State:定义了应用的状态数据

  1. Getter:在 store 中定义“getter”(可以认为是 store 的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来, 且只有当它的依赖值发生了改变才会被重新计算

  1. Mutation:是唯一更改 store 中状态的方法,且必须是同步函数

  1. Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作

  1. Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中

vue-router 怎么传参

1.id传参

//路由配置

{

path: '/orderDetail/:id',

name: 'orderdetail',

component: () => import('../components/orderDetail.vue'),

meta: { showTabbar: false}

}

this.$router.push({path:`/orderDetail/${this.id}`})

2.query传参

this.$router.push({path:`/orderDetail`,query:{id:this.id}})

3.pramas传参

this.$router.push({name:`orderdetail`,params:{id:this.id}})

插槽

1.普通插槽

2.具名插槽

3.作用域插槽

vue 的双向绑定原理

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

Vue2和Vue3区别

属性监听:

defineProperty: 遍历对象,劫持对象的每一个属性; Proxy: 劫持整个对象,并返回一个代理对象;

对数组方法的支持:

defineProperty: push...等不能监听;Proxy: 可以监听;

兼容:

defineProperty(ES5)兼容性比Proxy(ES6)好。

Vue3

  1. setup函数

  1. 声明普通类型 ref

  1. 声明复杂类型 reactive

  1. (https://link.zhihu.com/?target=http%3A//4.watch)watch 的用法

  1. v-model 的用法

  1. Vue3双向绑定原理

  1. Vue3的生命周期

  1. Vue3通讯

  1. Vue3.2 setup 语法糖等

webpack相关


常用Loader(高频)

raw-loader:加载文件原始内容(utf-8)

file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)

source-map-loader:加载额外的 Source Map 文件,以方便断点调试

svg-inline-loader:将压缩后的 SVG 内容注入代码中

image-loader:加载并且压缩图片文件

json-loader 加载 JSON 文件(默认包含)

babel-loader:把 ES6 转换成 ES5

ts-loader: 将 TypeScript 转换成 JavaScript

awesome-typescript-loader:将 TypeScript 转换成 JavaScript,性能优于 ts-loader

sass-loader:将SCSS/SASS代码转换成CSS

css-loader:加载 CSS,支持模块化、压缩、文件导入等特性

style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS

postcss-loader:扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀

vue-loader:加载 Vue.js 单文件组件

常用的Plugin

define-plugin:定义环境变量 (Webpack4 之后指定 mode 会自动配置)

ignore-plugin:忽略部分文件

html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)

web-webpack-plugin:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用

uglifyjs-webpack-plugin:不支持 ES6 压缩 (Webpack4 以前)

terser-webpack-plugin: 支持压缩 ES6 (Webpack4)

webpack-parallel-uglify-plugin: 多进程执行代码压缩,提升构建速度

mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代extract-text-webpack-plugin)

serviceworker-webpack-plugin:为网页应用增加离线缓存功能

clean-webpack-plugin: 目录清理

oader 和 plugin 的区别

Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。

Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。

Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入

Git相关

git 常用命令

  1. git clone

  1. git add .

  1. git commit -m

  1. git push

  1. git pull

  1. git branch 查看本地分支

  1. git branch -a 查看远程分支

  1. git branch -d xxx 删除分支

  1. git checkout xxx 切换分支

  1. git checkout -b xxx 新建分支并且切换到改分支

  1. git branch -m 旧分支名 新分支名 分支重命名

  1. git status 查看修改的文件

  1. git merge 合并分支

  1. git checkout -b xxx origin/xxx 拉去远程分支

  1. git log 查看提交记录

网络安全


GET和POST区别(高频)

1.GET在浏览器回退不会再次请求,POST会再次提交请求

2.GET请求会被浏览器主动缓存,POST不会,要手动设置

3.GET请求参数会被完整保留在浏览器历史记录里,POST中的参数不会

4.GET请求在URL中传送的参数是有长度限制的,而POST没有限制

5.GET参数通过URL传递,POST放在Request body中

6.GET参数暴露在地址栏不安全,POST放在报文内部更安全

7.GET一般用于查询信息,POST一般用于提交某种信息进行某些修改操作

8.GET产生一个TCP数据包;POST产生两个TCP数据包

HTTP和HTTPS


http 和 https 的基本概念

http: 是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议。 https:是以安全为目标的 HTTP 通道,即 HTTP 下 加入 SSL 层进行加密。其作用是:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。

http 和 https 的区别(高频)

1.HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头

2.HTTP 是不安全的,而 HTTPS 是安全的

3.HTTP 标准端口是80 ,而 HTTPS 的标准端口是443

4.在OSI 网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层

5.HTTP 无法加密,而HTTPS 对传输的数据进行加密

6.HTTP无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书

http状态码(高频)

  1. 200响应成功

  1. 301永久重定向

  1. 302临时重定向

  1. 304资源缓存

  1. 403服务器禁止访问

  1. 404服务器资源未找到

  1. 500 502服务器内部错误 504 服务器繁忙

性能相关


请求跨域

  1. jsonp(利用script标签没有跨域限制的漏洞实现。缺点:只支持GET请求)

  1. CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)

  1. proxy代理 目前常用方式,通过服务器设置代理

  1. 利用h5新特性window.postMessage()

浏览器本地存储

浏览器的本地存储主要分为Cookie、localStorage和sessionStorage。

共同点: 都是保存在浏览器端、且同源的不同点:

  1. cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。

  1. 存储大小限制也不同,

  • cookie数据不能超过4K,sessionStorage和localStorage可以达到5M

  • sessionStorage:仅在当前浏览器窗口关闭之前有效;

  • localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;

  • cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭

3.作用域不同

  • sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;

  • localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在

  • cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在

防抖

多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!

const debounce = (fn, time) => {

let timer = null

return function () {

clearTimeout(timer)

timer = setTimeout(() => {

fn.apply(this)

}, time)

}

}

节流

事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。

const throttle = (fn, time) => {

let flag = true

return function () {

if (!flag) return

flag = false

setTimeout(() => {

fn.apply(this)

flag = true

}, time)

}

}

优化项目


  1. 移除生产环境的控制台打印

  1. 第三方库的按需加载

  1. 避免css表达式、滤镜,较少DOM操作,优化图片、精灵图,避免图片空链接等

  1. 降低请求成本

  1. 减少请求数

  1. 减少传输体积

  1. ...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前端面试题 的相关文章

  • 关于C++变量重复定义

    本人是刚入学的大一计算机类学生 xff0c 最近在学习C 43 43 xff0c 在回顾这个代码时候发现 xff0c 这个重复定义i和j会导致之前定义的全局变量i和j并不能起作用 xff0c 现在还不太清楚为什么 xff0c 请小伙伴们注意
  • OpenMV——色块识别

    OpenMV有很多示例代码 xff0c 下面是我学习过程中有关知识的总结 目录 前言 一 阈值选择 二 代码 前言 函数RGB 255 0 0 表示的是红色 RGB 255 0 0 含义 xff1a 红色值 Red 61 255 xff1b
  • 链表的概念以及相关基础操作

    前言 xff1a 链表是数据结构里面最开始的章节 xff0c 也是对新手的理解有困难的第一章 笔者大二下学校才开设数据结构 xff0c 以防自己忘记 xff0c 遂记录之 链表的概念 xff1a 链表是一种物理存储单元上非连续 非顺序的存储
  • Sqoop数据导入 第2关:Mysql导入数据至HDFS上

    为了完成本关任务 你需要掌握 1 数据库 MySQL 建表 2 Mysql 数据导入至 HDFS 中 数据库 MySQL 建表 用命令进入 MySQL 客户端 mysql uroot p123123 h127 0 0 1 创建数据库hdfs
  • 一、单链表创建以及操作

    链表操作全内容 xff1a 1 xff0c 链表创建 2 xff0c 创建头结点 xff08 赋值 xff09 3 xff0c 输出当前链表 4 xff0c 连接节点形成链表 5 xff0c 插入节点函数 6 xff0c 删除节点函数 7
  • STL常用的容器

    STL常用容器 目录 STL常用容器vector容器pair c 43 43 内置二元组 不需要头文件stringqueue 队列priority queue 优先队列stack 栈deque 双端队列 速度异常的慢set map mult
  • Ubuntu网页连接失败的解决方法

    问题如下 xff1a 一 首先你要先检查自己的Ubuntu是否能连接上网络 二 在确保自己能连接上网络时 xff0c 网页连接失败的原因可能是你的Firefox浏览器的默认搜索引擎时Google xff0c 只需要在网页设置 搜索 中将搜索
  • Hal库_stm32开发之串口IDLE空闲中断+DMA接收不定长数据并修改数据

    本文写自于博主编写平衡智能车程序的时候 xff0c 由于中断使用的较多 xff0c 如定时器中断 xff0c 串口中断等等 为了避免MCU运行程序时卡死 xff0c 我就将串口中断改为串口IDLE空闲接收中断 可以实现不定长数据的接收 xf
  • PCB学习(一)——立创EDA边框设置

    一 伴随原理图转PCB生成的边框 通过在 原理图界面 点击 设计 下的 原理图转PCB xff08 Alt 43 P xff09 xff0c 可以得到如下 矩形边框 二 PCB界面设置边框 在 PCB界面 点击 工具 下的 边框设置 xff
  • c++模板类/模板函数的声明与定义应该放在头文件里

    c 43 43 模板类 模板函数的声明与定义应该放在头文件里 xff0c 不要分开来写类中函数的声明与定义 xff08 比如在 H文件里声明某个成员函数 xff0c 在 CPP文件里定义该成员函数 xff09 xff0c 这样会导致连接错误
  • STM32的GPIO端口配置八种模式的理解

    文章目录 一 GPIO的结构框图二 八种模式1 模拟输入 xff08 GPIO Mode AIN xff09 2 浮空输入 xff08 GPIO Mode IN FLOATING xff09 3 上拉输入 xff08 GPIO Mode I
  • ESP32 micro-usb 多数据量并简单加密的串口通信

    文章目录 前言一 ESP32和上位机的环境二 上位机部分1 串口通信的准备2 数据的准备与发送 三 下位机部分1 ESP32串口通信准备2 数据的接收四 同时测试 总结 前言 最近在研究单片机与上位机的串口通信 xff0c 刚好手头有一块E
  • boost之跨平台 错误处理

    system C 43 43 中处理错误的最佳方式是使用异常 xff0c 但操作系统和许多底层AP工不具有这个能力 xff0c 它们一般使用更通用也更难以操作的错误代码来表示出错的原因 xff0c 不同的操作系统的错误代码通常不是兼容的 x
  • 记录一下vector基本用法(简单易懂)

    vector容器的初始化 vector的使用首先需要加一个头文件 include lt vector gt xff1b vector lt int gt a 最一般的初始化方法 xff0c 就是定义一个容器啊a xff1b vector l
  • MPU6050基本原理介绍及程序配置

    一 MPU6050简介 1 内部主要结构 xff1a 陀螺仪 加速度计 数字运动处理器DMP xff08 Digital Motion Processor xff09 PS MPU6050还含有第二IIC接口 xff0c 用于连接一个 第三
  • Robomaster上位机视觉摘要——比赛规则篇

    本文是笔者多日来总结的2023赛季中针对上位机组的比赛规则摘要 xff0c 力求一文让你看懂上位机在赛场中的飒爽身影 目录 电力元件 电池 遥控器 激光 涂装 机器人 飞镖 雷达 空中机器人 工程机器人 哨兵机器人 英雄与步兵机器人 视觉应
  • C语言:结构体——关于内存字节对齐图文详解

    前言 xff1a 我们在学到c语言内存管理的时候总是一遍惊叹 xff0c 其聪明的内存管理策略 xff0c 一遍抱怨其难以理解的方法 xff0c 网上的资料要不讲究的太详细 xff0c 要不没能讲解清楚 xff0c 今天我们根据实例来学习一
  • 结构体+联合体 详解

    文章目录 一 结构体1 结构体变量2 特殊声明3 结构体的引用1 嵌套调用2 自引用 三 结构体的初始化四 结构体的内存对齐1 用法2 练习题3 修改对齐数 五 位段1 用法2 练习题 六 联合体1 用法2 练习题1 正常算法题2 用联合体
  • Ubuntu20.04——一篇文章让你从零配置VINS_Mono环境以及运行(2023年最新)

    注 xff1a 文末包含该文章涉及的所有安装包的网盘链接 零 换源 xff08 也可以先不换 xff0c 后面觉得下载慢再换也行 xff09 1 备份原来的源 sudo cp etc apt sources list etc apt sou
  • 学C语言推荐的书和软件—C Primer Plus和Dev C++

    写这个的目的是复习巩固C Primer Plus的知识 xff0c 我会一直更新这个系列 对于这本书 xff0c 入门C语言是完全够了 xff0c 后面的链表 队列和二叉树比较综合 xff0c 难度大一些 用这本书学C语言非常好 xff0c

随机推荐

  • mavlink python

    from pymavlink import mavutil Create the connection m 61 mavutil mavlink connection 39 udpin 0 0 0 0 14550 39 dir m mav
  • C++Vector浅析,Vector用法大全

    vector基本概念 功能 xff1a vector数据结构和数组非常相似 xff0c 也成为单端数组 vector与普通数组的区别 xff1a 不同之处在与数组是静态空间 xff0c 而vector可以动态扩展 动态扩展 xff1a 并不
  • 网络通信--Linux

    文章目录 网络通信的基础通信模型IP地址和端口port 网络套接字网络字节序初识UDP与TCP两种协议sockaddr结构体家族认识一些网络常用基础函数 UDP实现简单通信TCP实现简单通信总结 网络通信的基础 网络通信是建立在多层协议之下
  • Git分支和版本(标签)

    目录 一 Git分支 1 1 四大环境 xff08 分支 xff09 1 1 1 分支和标签的关系 1 2 分支的作用 1 3 演示分支 1 3 1 在Gitee中创建项目 1 3 2 克隆到本地 1 3 3 建立分支 1 3 4 切换分支
  • 前端必会算法——栈和队列

    上一篇 前端必会算法 标准快速排序 栈和队列 栈 xff08 Stack xff09 可以理解为是一个箱子 xff0c 存放东西的容器 栈结构的特点 xff1a 先入后出 xff0c 栈相当于一个箱子 xff0c 先放进去的东西被压在了下面
  • OpenMV的单颜色识别讲解

    OpenMV的官方教程 xff1a 寻找色块 xff1b single color rgb565 blob tracking示例讲解 xff1b 视频讲解 需要提前看的文章 xff1a 程序烧录 xff1b 颜色阈值设置 目录 thresh
  • STM32CubeMX串口通讯

    串口的简单介绍 RS 232与TTL 根据通讯使用的电平标准不同 xff0c 串口通讯可分为 TTL 标准及 RS 232 标准 而STM32的串口是TTL电平标准的 如果需要使用到RS 232则需要一个电平转换芯片 单工通信 半双工通信和
  • 自制超简易通讯协议(中断接收)

    前言 在做蓝牙语音小车时 xff0c 总遇到各式各样的问题 本文主题是笔者在解决串口不够并且数据量小的问题时突发奇想自定义一个简易的通讯协议 由于是用89c51做的主控 xff0c 外设的资源比较紧张 串口只有一个 xff0c 但两个系统需
  • 【Java杂谈】Iterator(迭代器)的使用

    x1f3b8 Iterator是什么 xff1f 迭代器是Java提供的一种访问集合的方法 xff0c Iterator 是 Java 迭代器最简单的实现 xff0c 常用来访问ArrayList HashMap等类的对象 Iterator
  • orb 纯背景物体识别

    include lt chrono gt include lt iostream gt include lt opencv2 core core hpp gt include lt opencv2 features2d features2d
  • Windows逆向安全(一)之基础知识(九)

    汇编比较三种循环 众所周知 xff0c 在C语言可以使用可以使用三种循环 xff0c 分别是 xff1a while do while和for 本文从汇编的角度出发 xff0c 观察这三种循环的差异 范例代码 先贴出三种循环的代码 xff0
  • c++读取yolov5模型进行目标检测(读取摄像头实时监测)

    文章介绍 本文是篇基于yolov5模型的一个工程 xff0c 主要是利用c 43 43 将yolov5模型进行调用并测试 xff0c 从而实现目标检测任务 任务过程中主要重点有两个 xff0c 第一 版本问题 xff0c 第二配置问题 一
  • ROS初学(二):ROS的三种基本通信机制(来自赵虚左老师)

    一 综述 ROS引入通信机制 xff0c 是为了实现ROS节点 xff08 进程 xff09 之间的通信 利用ROS进程的分布式框架 xff0c 可以使得每个进程独立的工作 xff0c 甚至分布于不同的主机工作 机器人上的各种传感器 xff
  • webpack 5.5.1 compiled with 1 error in 63 ms

    新建项目空白目录 xff0c 并运行 npm init y 命令 xff0c 初始化包管理配置文件 package json 新建 src 源代码目录 新建 src gt index html 首页和 src gt index js 脚本文
  • TypeError: Class constructor ServeCommand cannot be invoked without ‘new‘

    安装webpack插件 webpack dev server配置时将package json里面webpack改为webpack serve后 xff0c 运行npm run 脚本名 时出现 TypeError Class construc
  • Field ‘browser‘ doesn‘t contain a valid alias configuration

    意思是字段 39 browser 39 不包含有效的别名配置 意思就是说你打包的css路径不对 这个是我的代码 这里js里面导入的css路径不对 xff0c css文件夹不是和index js平级 xff0c 应该是上级所以正确的代码应该是
  • Failed to load resource: the server responded with a status of 404 (Not Found)

    问题场景 xff1a 编写路由模块 解决方法 xff1a 1 先检测路径是否有写错 2 将vscode中开的插件vetur关闭 3 上面方法不管用时 xff0c 将浏览器插件关闭 xff0c 例如油猴 有什么错误望大佬指出 xff01 xf
  • Vue3.js【未完成】

    Vue3 js 如何关闭烦人的vscode的提示框 https blog csdn net liuyuemozhu article details 101056556 ES6模块化与异步编程高级用法 ES6模块化 1 回顾 xff1a no
  • npm ERR! code ERESOLVEnpm ERR! ERESOLVE unable to resolve dependency tree

    npm下载报错 xff0c 这个是因为npm版本问题 xff0c 例如我下载element ui运行npm i element ui S 因为版本问题我就无法下载 xff0c 解决办法就是在末尾加上 legacy peer deps 即np
  • 前端面试题

    浏览器 输入一个URL到页面过程中发生了什么 xff08 高频 xff09 首先在浏览器中输入URL 查找缓存 xff1a 浏览器先查看浏览器缓存 系统缓存 路由缓存中是否有该地址页面 xff0c 如果有则显示页面内容 如果没有则进行下一步