2024 前端面试题!!! html css js相关

**常见的块元素、行内元素以及行内块元素,三者有何不同?**​​​​​​​
**HTML、XML、XHTML它们之间有什么区别?**​​​​​​​
DOCTYPE(⽂档类型) 的作⽤

Doctype是HTML5的文档声明,通过它可以告诉浏览器,使用哪一个HTML版本标准解析文档。在浏览器发展的过程中,HTML出现过很多版本,不同的版本之间格式书写上略有差异。如果没有事先告诉浏览器,那么浏览器就不知道文档解析标准是什么?此时,大部分浏览器将开启最大兼容模式来解析网页,我们一般称为怪异模式,这不仅会降低解析效率,而且会在解析过程中产生一些难以预知的bug,所以文档声明是必须的。

浏览器渲染页面的两种模式(可通过document.compatMode获取):

  • CSS1Compat:标准模式(Strick mode),默认模式,浏览器使用W3C的标准解析渲染页面。在标准模式中,浏览器以其支持的最高标准呈现页面。
  • BackCompat:怪异模式(混杂模式)(Quick mode),浏览器使用自己的怪异模式解析渲染页面。在怪异模式中,页面以一种比较宽松的向后兼容的方式显示。
localStorage、sessionStorage、cookie 三者明细区别
  1. cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
  2. cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
  3. sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

存储大小

  • cookie数据大小不能超过4k。
  • sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

有期时间

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

网站TDK三大标签以及SEO优化

img标签的title属性与alt属性的区别是什么?
  • alt是给搜索引擎识别,在图像无法显示时的替代文本
  • title属性是关于元素的注释信息,主要是给用户解读

在定义 img 对象时,将 alt 和 title 属性写全,可以保证在各种浏览器中都能正常使用

注意:(IE已淘汰,仅做了解即可)

当鼠标放到文字或是图片上时有 title 文字显示。

(因为IE不标准)在 IE 浏览器中 alt 起到了 title 的作用,变成文字提示。

src 和 href 的区别?

src和href都是HTML中特定元素的属性,都可以用来引入外部的资源。两者区别如下:

src:全称source,它通常用于img、video、audio、script元素,通过src指向请求外部资源的来源地址,指向的内容会嵌入到文档中当前标签所在位置,在请求src资源时,它会将资源下载并应用到文档内,比如说:js脚本、img图片、frame等元素。当浏览器解析到该元素时,会暂停其它资源下载,直到将该资源加载、编译、执行完毕。这也是为什么将js脚本放在底部而不是头部的原因。

href:全称hyper reference,意味着超链接,指向网络资源,当浏览器识别到它指向的⽂件时,就会并⾏下载资源,不会停⽌对当前⽂档的处理,通常用于a、link元素。

9、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别?

title与h1的区别

从网站角度看,title 更重于网站信息。title可以直接告诉搜索引擎和用户这个网站是关于什么主题和内容的。

从文章角度看,h1则是用于概括文章主题。

一个网站可以有多个title,最好一个单页用一个title,以便突出网站页面主体信息,从seo看,title权重比h1高,适用性比h1广。

标记了h1的文字页面给予的权重会比页面内其他权重高很多。一个好的网站是h1和title并存,既突出h1文章主题,又突出网站主题和关键字。达到双重优化网站的效果。
b与strong 的区别

b 是只是对文本的简单加粗, strong 是一个语义化标签,对相关文本具有强调作用

b 标签只是侧重于字体加粗, strong标签加强字体的语气都是通过粗体来实现的,相比之下,搜索引擎更喜欢侧重于strong标签

strong标签更注重于内容上的应用,在html中,对关键词的标明,然而还有一些网站上,也有使用strong标签登对小标题进行强调,但是在页面中,如果出现过多的strong标签,可能会对排名不利。
i 与 em 的区别

i(italic)是实体标签,用来使字符倾斜,em(emphasis)是逻辑标签,作用是强调文本内容

i标签只是斜体的样式,没有实际含义,常用来表达无强调或着重意味的斜体,比如生物学名、术语、外来语;

em表示标签内字符重要,用以强调,其默认格式是斜体,但是可以通过CSS添加样式。

建议:为了符合CSS3的规范,i 标签应尽量少用而应改用 em

10、iframe的优点和缺点 ?

iframe的缺点:

页面样式调试麻烦,出现多个滚动条;

浏览器的后退按钮失效;

过多会增加服务器的HTTP请求;

小型的移动设备无法完全显示框架;

产生多个页面,不易管理;

不容易打印;

代码复杂,无法被一些搜索引擎解读。

搜索引擎的检索程序无法解读这种页面,不利于SEO;
iframe的优点:

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

如果有多个网页引用iframe,那么你只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷。

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

如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由iframe来解决。

重载页面时不需要重载整个页面,只需要重载页面中的一个框架页(减少了数据的传输,增加了网页下载速度)

总而言之:运维性网站或继承性开发的网站,可以使用iframe;

销售内,官网、展示性网站等建议不使用iframe;

标准的网页设计是不使用iframe的。

页面导入外部css文件的方法通常有两种,一种在网页中直接link标签加入,另一种在页面中@import引入css文件。两种引入形式如下:

link引入形式:

<link href="styles.css" type="text/css" />
@import引用形式:
<style type="text/css">
    @import url("styles.css");
</style>

1、适用范围不同

@import可以在网页页面中使用,也可以在css文件中使用,用来将多个css文件引入到一个css文件中;而link只能将css文件引入到网页页面中。

2、功能范围不同

link属于XHTML标签,而@import是CSS提供的一种方式,link标签除了可以加载CSS外,还可以定义rel连接属性,定义RSS等,@import就只能加载CSS。

3、加载顺序不同

页面被加载的时候,link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再被加载。所以有时候浏览@import加载CSS的页面时开始会没有样式(就是闪烁)

4、兼容性

由于@import是css2.1提出的,所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题。

5、控制样式时的差别

使用link方式可以让用户切换CSS样式.现代浏览器如Firefox,Opera,Safari都支持rel="alternate stylesheet"属性(即可在浏览器上选择不同的风格),当然你还可以使用Javascript使得IE也支持用户更换样式。

6、使用DOM控制样式时的差别

当使用JavaScript控制DOM去改变样式的时候,只能使用link标签,因为@import不是DOM可以控制的。

rgba和opacity的透明效果有什么不同?

opacity

opacity是一个属性。opacity属性的值,可以被其子元素继承,给父级div设置opacity属性,那么所有子元素都会继承这个属性,并且,该元素及其继承该属性的所有子元素的所有内容透明度都会改变。

rgba(0,0,0,0.5)

rgba是一个属性值。rgba设置的元素,只对该元素的背景色有改变,并且,该元素的后代不会继承该属性。

补冲:rgba只是一个属性值,在background 里用改变背景色,在color里是改字体颜色,shadow里是改阴影色,不止是能够改元素的背景色,要看具体是在哪个属性上用

display:none与visibility:hidden的区别?

这两个属性都是让元素隐藏,不可见。两者区别如下:

(1)在渲染树中

display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间;

visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。

(2)是否是继承属性

display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;

visibility:hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible可以让子孙节点显示;

(3)修改常规文档流中元素的 display 通常会造成文档的重排,但是修改visibility属性只会造成本元素的重绘;

(4)如果使用读屏器,设置为display:none的内容不会被读取,设置为visibility:hidden的内容会被读取。

(5)display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。

(6)visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。

定位布局 position中的relative、absolute、fixed、sticky它们之间的区别?

(1)relative:相对定位,相对于自己本身在正常文档流中的位置进行定位。

(2)absolute:生成绝对定位,相对于最近一级定位不为static的父元素进行定位。

(3)fixed: 生成绝对定位,相对于浏览器窗口或者frame进行定位。(老版本IE不支持)

(4)static:默认值,没有定位,元素出现在正常的文档流中。(很少用)

(5)sticky:生成粘性定位的元素,容器的位置根据正常文档流计算得出。(很少用)

如何用CSS3画一条0.5px的直线?

height: 1px;

transform: scale(0.5);

CSS3盒子模型: 标准盒模型、怪异盒模型

盒子模型分为两种:

  • 第一种是 W3C 标准的盒子模型(标准盒模型)

  • 第二种 IE 标准的盒子模型(怪异盒模型)

  • 标准盒模型与怪异盒模型的表现效果的区别之处:

    1、标准盒模型中 width 指的是内容区域 content 的宽度

    height 指的是内容区域 content 的高度

    标准盒模型下盒子的大小 = content + border + padding + margin

  • 怪异盒模型中的 width 指的是内容、边框、内边距总的宽度(content + border + padding);height 指的是内容、边框、内边距总的高度

    怪异盒模型下盒子的大小=width(content + border + padding) + margin

嵌套块元素垂直外边距的塌陷

盒子居中的几种方法:"子绝父相"、"Flex布局"、"transform"

利用定位(子绝父相)、margin-left、margin-top实现

利用定位(子绝父相)、transform属性实现

利用flex布局实现盒子居中

CSS3中有哪些新特性?
  1. 新增各种CSS选择器 (: not(.input):所有 class 不是"input"的节点)
  2. 圆角 (border-radius:8px)
  3. 多列布局 (multi-column layout)
  4. 阴影和反射 (Shadoweflect)
  5. 文字特效 (text-shadow)
  6. 文字渲染 (Text-decoration)
  7. 线性渐变 (gradient)
  8. 旋转 (transform)
  9. 增加了旋转,缩放,定位,倾斜,动画,多背景
CSS3选择器及其优先级

对于选择器的优先级:

  • 标签选择器、伪元素选择器:1
  • 类选择器、伪类选择器、属性选择器:10
  • id 选择器:100
  • 内联样式:1000

注意事项:

  • !important声明的样式的优先级最高;
  • 如果优先级相同,则最后出现的样式生效;
  • 继承得到的样式的优先级最低;
  • 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
  • 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。
display的block、inline和inline-block的区别?

(1)block: 会独占一行,多个元素会另起一行,可以设置width、height、margin和padding属性;

(2)inline: 元素不会独占一行,设置width、height属性无效。但可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin;

(3)inline-block: 将对象设置为inline对象,但对象的内容作为block对象呈现,之后的内联对象会被排列在同一行内。

对于行内元素和块级元素,其特点如下:

行内元素

  • 设置宽高无效;
  • 可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin;
  • 不会自动换行;

块级元素

  • 可以设置宽高;
  • 设置margin和padding都有效;
  • 可以自动换行;
  • 多个块状,默认排列从上到下。
Localstorage、sessionStorage、cookie 的区别

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

三者区别:

1、cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器

间来回传递,而 sessionStorage 和 localStorage 不会自动把数据发送给服务器,仅在本地保存。 cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下

2、存储大小限制也不同,cookie 数据不能超过 4K,同时因为每次 http 请求都会携带 cookie、 所以 cookie 只适合保存很小的数据,如会话标识。sessionStorage 和 localStorage 虽然也有存 储大小的限制,但比 cookie 大得多,可以达到 5M 或更大。

3、数据有效期不同

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

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

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

4、作用域不同

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

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

cookie 也是在所有同源窗口中都是共享的

5、web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。

6、web Storage 的 api 接口使用更方便。

如何实现双飞翼(圣杯)布局?

1、利用定位实现两侧固定中间自适应

父盒子设置左右 padding 值

给左右盒子的 width 设置父盒子的 padding 值,然后分别定位到 padding 处.

中间盒子自适应

2、利用 flex 布局实现两侧固定中间自适应

父盒子设置 display:flex

左右盒子设置固定宽高

中间盒子设置 flex:1

伪元素和伪类的区别和作用?

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

p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}

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

a:hover {color: #FF00FF}
p:first-child {color: red}

总结: 伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。

img 的 alt 与 title 的异同,还有实现图片懒加载的原理?

异同

alt 是图片加载失败时,显示在网页上的替代文字; title 是鼠标放上面时显示的文字,title

是对图片的描述与进一步说明;

这些都是表面上的区别,alt 是 img 必要的属性,而 title 不是 对于网站 seo 优化来说,title 与 alt 还有最重要的一点: 搜索引擎对图片意思的判断,主 要靠 alt 属性。所以在图片 alt 属性中以简要文字说明,同时包含关键词,也是页面优化的 一部分。条件允许的话,可以在 title 属性里,进一步对图片说明 由于过多的图片会严重影响网页的加载速度,并且移动网络下的流量消耗巨大,所以 说延迟加载几乎是标配了。
原理

图片懒加载的原理很简单,就是我们先设置图片的 data-set 属性(当然也可以是其他任意的, 只要不会发送 http 请求就行了,作用就是为了存取值)值为其图片路径,由于不是 src,所 以不会发送 http 请求。 然后我们计算出页面 scrollTop 的高度和浏览器的高度之和, 如果 图片距离页面顶端的坐标 Y(相对于整个页面,而不是浏览器窗口)小于前两者之和,就说明图片就要显示出来了(合适的时机,当然也可以是 其他情况),这时候我们再将data-set 属性替换为 src 属性即可。

箭头函数与普通函数的区别?

(1) 箭头函数比普通函数更加简洁

如果没有参数 , 就直接写一个空括号即可 , 如果只有一个参数 , 可以省去参数的括号 如果有多个参数 , 用逗号分割 , 如果函数体的返回值只有一句 , 可以省略大括号。

(2) 箭头函数没有自己的this

箭头函数不会创建自己的this, 所以它没有自己的this, 它只会在自己作用域的上一层继承this。所以箭头函数中this的指向在它在定义时已经确定了, 之后不会改变。

(3) 箭头函数继承来的this指向永远不会改变

(4) call()、apply()、bind()等方法不能改变箭头函数中this的指向

(5) 箭头函数不能作为构造函数使用

由于箭头函数时没有自己的this,且this指向外层的执行环境,且不能改变指向,所以不能当做构造函数使用。

(6) 箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是它外层函数的arguments值。

(7) 箭头函数没有prototype

(8) 补充:箭头函数的this指向哪⾥?

箭头函数不同于传统JavaScript中的函数,箭头函数并没有属于⾃⼰的this,它所谓的this是捕获其所在上下⽂的 this 值,作为⾃⼰的 this 值,并且由于没有属于⾃⼰的this,所以是不会被new调⽤的,这个所谓的this也不会被改变。

JS基础类型和复杂类型

JS数据基础类型有:

String、Number、Boolean、Null、undefined五种基本数据类型,加上新增的两种ES6的类型Symbol、BigInt

JS有三种 复杂类型 (引用数据类型):

Object(对象)、Array(数组)、function(函数)

JS中null和undefined的判断方法和区别?

1.undefined 的判断

(1) undefined表示缺少值,即此处应该有值,但是还没有定义

(2) 变量被声明了还没有赋值,就为undefined

(3) 调用函数时应该提供的参数还没有提供,该参数就等于undefined

(4) 对象没有赋值的属性,该属性的值就等于undefined

(5) 函数没有返回值,默认返回undefined

2.null 的判断

(1) null表示一个值被定义了,但是这个值是空值

(2) 作为函数的参数,表示函数的参数不是对象

(3) 作为对象原型链的终点 (Object.getPrototypeOf(Object.prototype))

(4) 定义一个值为null是合理的,但定义为undefined不合理(var name = null)

3.typeof 类型不同

typeof null; // 'object'
typeof undefined; // 'undefined'

运行运行

4.Number() 转数字也不同

Number(null); // 0
Number(undefined); // NaN 
keep-alive 的作用是什么?
  • 官网解释:包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
  • 作用:实现组件缓存,保持这些组件的状态,以避免反复渲染导致的性能问题。 需要缓存组件 频繁切换,不需要重复渲染。
  • 场景:tabs标签页 后台导航,vue性能优化。
  • 原理:Vue.js内部将DOM节点抽象成了一个个的VNode节点,keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件(pruneCache与pruneCache)的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。
闭包的理解?

概念: 有权访问另一个函数内部变量的函数。
本质: 是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。
面试:什么是闭包?

通俗的来说:闭包是在一个函数内部在定一个函数,然后内部函数访问外部函数的一个变量就会形成闭包,闭包的话会形成一个私有空间,然后避免全局变量的一个污染,然后会持久化存储数据到内存中,但是闭包也有弊端,它会导致内存泄漏

拓展:内存泄漏怎么解决?

首先避免它的使用,其次的话就是变量执行完以后,可以让它赋值为null,最后利用JS的一个垃圾回收机制进行回收
闭包用处:

读取内部函数的变量;

这些变量的值始终会保持在内存中,不会在外层函数调用后被自动清除
闭包优点:

变量会一直在内存中;

避免全局变量的污染;

私有变量的存在;
闭包缺点:

变量长期储存在内存中,会增大内存的使用量,使用不当会造成内存泄露

判断闭包的3个特点:

1.函数嵌套函数;

2.内部函数一定操作了外部函数的局部变量;

3.外部函数一定将内部函数返回到外部并保存在一个全局变量中;

判断闭包的执行结果:

1.外部函数被调用了几次就有几个受保护的局部变量的副本;

2.来自一个闭包的函数被调用几次,受保护的局部变量就变化几次;
闭包特性:

函数嵌套函数;

内部函数可以直接使用外部函数的局部变量;

变量或参数不会被垃圾回收机制回收;

JS垃圾回收机制

垃圾回收机制(Garbage Collection)简称GC:是JavaScript中使用的内存管理系统的基本组成部分

JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时会 "自动" 释放、释放的过程成为垃圾回收

内存在不使用的时候会被垃圾回收器自动回收

nextTick的实现?

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

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

比如,我在干什么的时候就会使用nextTick,传一个回调函数进去,在里面执行dom操作即可。简单了解nextTick的实现,它会在callbacks里面加入我们传入的函数,然后用timerFunc异步方式调用它们,首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。

实现原理:在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后立即使用 nextTick 来获取更新后的 DOM。 nextTick主要使用了宏任务和微任务。 根据执行环境分别尝试采用Promise、MutationObserver、setImmediate,如果以上都不行则采用setTimeout定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列。

混入mixin的原理?

mixin 项目变得复杂的时候,多个组件间有重复的逻辑就会用到mixin

多个组件有相同的逻辑,抽离出来,其实mixin并不是完美的解决方案,会存在一些问题

如:vue3提出的Composition API旨在解决这些问题【追求完美是要消耗一定的成本的,如开发成本】

场景:PC端新闻列表和详情页一样的右侧栏目,可以使用mixin进行混合

劣势:

  1. 变量来源不明确,不利于阅读

  2. 多mixin可能会造成命名冲突

  3. mixin和组件可能出现多对多的关系,使得项目复杂度变高

js列举和数组操作相关的方法(常用)

在JavaScript中,数组操作是编程的常见任务之一。JavaScript提供了一系列与数组操作相关的方法,这些方法可以用来操纵数组,如添加、删除、查找、排序和遍历元素等。以下是一些常用的数组方法:
添加元素

push(): 在数组的末尾添加一个或多个元素,并返回新的长度。

unshift(): 在数组的开头添加一个或多个元素,并返回新的长度。
删除元素

pop(): 删除数组的最后一个元素,并返回那个元素。

shift(): 删除数组的第一个元素,并返回那个元素。

splice(): 通过删除、替换或添加新元素来改变数组的内容。
查找元素

indexOf(): 查找元素在数组中的索引。

lastIndexOf(): 从数组的末尾开始查找元素。

find(): 查找第一个满足测试函数的元素。

findIndex(): 查找第一个满足测试函数的元素的索引。
排序和翻转

sort(): 对数组元素进行排序。

reverse(): 颠倒反转数组中元素的顺序。
遍历和过滤

forEach(): 对数组的每个元素执行一次提供的函数。

map(): 创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值。

filter(): 创建一个新数组,包含通过所提供函数实现的测试的所有元素。

reduce(): 对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

reduceRight(): 类似reduce(),但是从数组的末尾开始累加。
归并数组

concat(): 合并两个或多个数组。

slice(): 提取原数组的一部分,返回一个新数组。
其它方法

join(): 将数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。

toString(): 返回一个表示数组内容的字符串。

split(): 把字符串转换成数组。

toLocaleString(): 返回一个表示数组内容的本地化字符串。

这些方法可以在日常编程中大大简化数组操作的复杂性。使用这些方法时,需要注意它们的返回值和副作用。例如,push 和 pop 方法会改变原数组,而 concat 方法则会返回一个新数组。在编写代码时,了解这些方法的特性对于避免不必要的错误和优化性能至关重要。

typeof和instanceof的区别是什么?

(1)typeof 的返回值是一个字符串,用来说明变量的数据类型;

typeof用于数据类型的判断,返回值有number、string、boolean、function、undefined、object 六个。但是,在其中你会发现,typeof判断null、array、object以及函数的实例(new + 函数)时,它返回的都是object。这就导致在判断这些数据类型的时候得不到真实的数据类型。所以,typeof 存在的弊端------它虽然可以判断基本数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断。

(2)instanceof的返回值是布尔值,用于判断一个变量是否属于某个对象的实例。instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

JS中 "=="和"==="的区别详解

区别

===:三个等号我们称为等同符,当等号两边的值为相同类型的时候,直接比较等号两边 的值,值相同则返回 true,若等号两边的值类型不同时直接返回 false。也就是说三个等号既要判断值也要判断类型是否相等。

==:两个等号我们称为等值符,当等号两边的值为相同类型时比较值是否相同,类型不同时会发生类型的自动转换,转换为相同的类型后再作比较。也就是说两个等号只要值相等就可以。

如何用原生 JS给一个按钮绑定两个 onclick 事件?
<button id="btn">点击</button>
 
<script>
    //通过事件监听  绑定多个事件
    let btn = document.getElementById('btn')
    btn.addEventListener('click', one)
    btn.addEventListener('click', two)
    function one() {
        alert('第一个')
    },
    function two() {
        alert('第二个')
    },
</script>
var、let和const的区别?

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

内层变量可能覆盖外层变量

用来计数的循环变量泄露为全局变量

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

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

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

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

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

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

讲解js的call、apply和bind区别?

首先,call apply bind三个方法都可以用来改变函数的this指向,具体区别如下:

  • call( ) 是接收一个及其以上的参数,第一个参数表示this要指向的对象,其余参数表示调用函数需要传入的参数,返回调用函数的返回结果,属于立即执行函数;
  • apply( ) 是接收两个参数,第一个参数表示this要指向的对象,第二参数表示调用函数需要传入的参数所组成的数组,返回调用函数的返回结果,属于立即执行函数;
  • bind( ) 是接收一个及其以上的参数,和call()一致,但是其返回是一个函数,而不是调用函数的返回结果
  • call、apply、bind相同点:都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是nul或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
  • call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组
  • bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
  • 值得注意:当 bind 返回的函数 使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)
谈谈你对webpack的理解?

1、谈谈你对Webpack的理解

Webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。

它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。

对于不同类型的依赖,Webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。
2、Webpack的基本功能有哪些?

代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等

文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等

代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载

模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件

自动刷新:监听本地源代码的变化,自动构建,刷新浏览器

代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过

自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
3、Webpack构建过程?

从entry里配置的module开始递归解析entry依赖的所有module

每找到一个module,就会根据配置的loader去找对应的转换规则

对module进行转换后,再解析出当前module依赖的module

这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk

最后Webpack会把所有Chunk转换成文件输出在整个流程中Webpack会在恰当的时机执行plugin里定义的逻辑
4、有哪些常见的Loader?

optimize-css-assets-plugin:压缩css;

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

url-loader:与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值会交给 file-loader 处理,小于阈值时返回文件 base64 形式编码 (处理图片和字体)

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

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

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

ts-loader: babel-loader:把 ES6 转换成 ES5

ts-loader: 将 TypeScript 转换成 JavaScript

less-loader:将less代码转换成CSS

eslint-loader:通过 ESLint 检查 JavaScript 代码

vue-loader:加载 Vue单文件组件
5、有哪些常见的Plugin?

html-webpack-plugin:自动创建一个html文件,并把打包好的js插入到html中

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

mini-css-extract-plugin: 在每一次打包之前,删除整个输出文件夹下的内容;

clean-webpack-plugin: 抽离css代码放到一个单独的文件中;

copy-webpack-plugin: 拷贝文件

webpack-bundle-analyzer: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)

optimize-css-assets-plugin:压缩css;
6、那你再说一说Loader和Plugin的区别?

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

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

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

Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
7、如何优化 Webpack 的构建速度?

(1)使用高版本的 Webpack 和 Node.js

(2)压缩代码

通过 uglifyjs-webpack-plugin 压缩JS代码

通过 mini-css-extract-plugin 提取 chunk 中的 CSS 代码到单独文件,通过 css-loader 的 minimize 选项开启 cssnano 压缩 CSS。

(3)多线程/多进程构建:thread-loader, HappyPack

(4)压缩图片: image-webpack-loader

(5)缩小打包作用域

exclude/include (确定 loader 规则范围)

resolve.modules 指明第三方模块的绝对路径 (减少不必要的查找)

resolve.mainFields 只采用 main 字段作为入口文件描述字段 (减少搜索步骤,需要考虑到所有运行时依赖的第三方模块的入口文件描述字段)

resolve.extensions 尽可能减少后缀尝试的可能性

noParse 对完全不需要解析的库进行忽略 (不去解析但仍会打包到 bundle 中,注意被忽略掉的文件里不应该包含 import、require、define 等模块化语句)

ignorePlugin (完全排除模块)
8、说一下 Webpack 的热更新原理吧?

Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

HMR的核心就是客户端从服务端拉去更新后的文件,准确地说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。

后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。
9、什么是bundle?什么是chunk?什么是module?

bundle:是webpack打包后的一个文件;

chunk:代码块,一个chunk 可能有很多的模块组成,用于合并和分割代码;

module:模块,在webpack中,一切都是模块,一个文件就是一个模块,她从入口开始查找webpack依赖的所有模块
10、webpack和grunt以及gulp有什么不同?

grunt和gulp是基于任务处理的工具,我们需要把我们要做的事分配成各种各样的任务,grunt和gulp会自动执行各种分配的任务,像流水线一样,把资源放上去通过不同的插件进行加工,他的插件非常丰富,能够为我们打造各种工作流;

webpack是模块化打包工具,把所有文件都当作模块进行处理,也就是说webpack和grunt和gulp是两种完全不一样的东西;

const定义的对象属性是否可以改变?

情况一:const定义的变量存在块级作用域,且不存在变量提升,一般用于定义常量,定义的时候必须初始化。

答:不可以,const定义的如果是基本数据类型(string,number,boolean,null,undifined,symbol),定义后就不可再修改,如果修改,会报错。

情况二:那么如果是const定义的对象呢?是否可以修改对象中的属性?

答案:可以

原因:对象是引用类型的,const定义的对象t中保存的是指向对象t的指针,这里的"不变"指的是指向对象的指针不变,而修改对象中的属性并不会让指向对象的指针发生变化,所以用const定义对象,对象的属性是可以改变的。

栈溢出及解决方法?

栈溢出(stack Overflow)

缓冲区溢出是由于C语言系列设有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。

栈溢出就是缓冲区溢出的一种。 由于缓冲区溢出而使得有用的存储单元被改写, 往往会引发不可预料的后果。程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据,以致于缓冲区无法容纳,就会造成缓冲区以外的存储单元被改写,这种现象就称为缓冲区溢出。缓冲区长度一般与用户自己定义的缓冲变量的类型有关。

由于缓冲区溢出而使得有用的存储单元被改写,往往会引发不可预料的后果。向这些单元写入任意的数据,一般只会导致程序崩溃之类的事故,对这种情况我们也至多说这个程序有Bug。但如果向这些单元写入的是精心准备好的数据,就可能使得程序流程被劫持,致使不希望的代码被执行,落入攻击者的掌控之中,这就不仅仅是bug,而是漏洞(exploit)了。
栈溢出的解决方法

减少栈空间的需求,不要定义占用内存较多的auto变量,应该将此类变量修改成指针,从堆空间分配内存。

函数参数中不要传递大型结构/联合/对象,应该使用引用或指针作为函数参数。

减少函数调用层次,慎用递归函数,例如A->B->C->A环式调用。

JS如何实现多线程?

什么是JavaScript的多线程?

JavaScript本身是单线程的,但是可以通过实现多线程来提高性能和用户体验。多线程允许JavaScript在等待用户交互或网络请求时,执行其他任务,从而提高页面加载速度和响应速度。
JavaScript中有哪些实现多线程的方式?

JavaScript有多种实现多线程的方式,包括Web Workers、SharedArrayBuffer、WebAssembly等。其中,Web Workers允许在后台线程中运行JavaScript代码,而SharedArrayBuffer和BufferSource API则允许在多个线程之间共享数据。
如何使用Web Workers实现多线程?

使用Web Workers实现多线程需要创建一个新的worker线程,并将需要执行的代码作为字符串传递给worker。worker线程可以访问全局对象messageChannel的postMessage方法来发送消息,主线程可以使用onmessage方法来接收消息并执行相应的操作。
如何保证多线程安全?

多线程环境下的安全问题主要包括数据竞争和死锁等。为了解决这些问题,需要使用同步机制,如使用Promise、async/await等异步编程方式,或者使用事件循环、共享内存等机制来保证数据的一致性和安全性。
描述一个实际的多线程应用场景。

在实际应用中,多线程可以用于提高页面加载速度和响应速度,例如在电商网站中,可以使用Web Workers在后台线程中加载和处理商品图片,从而提高页面加载速度和用户体验。同时,多个并发请求也可以使用Web Workers并行处理,提高系统性能和响应速度。

事件循环,Promise和async/await的详解

事件循环event loop它的执行顺序:

一开始整个脚本作为一个宏任务执行

执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列

当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完

执行浏览器UI线程的渲染工作

检查是否有Web Worker任务,有则执行

执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空

微任务包括:MutationObserver、Promise.then()或catch()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。

宏任务包括:script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering。

注意⚠️:在所有任务开始的时候,由于宏任务中包括了script,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout)将被放到下一轮宏任务中来执行。

Promise和async/await是JavaScript中处理异步操作的两种方式。

Promise是一种用于处理异步操作的对象。它可以表示一个异步操作的最终完成或失败,并返回相应的结果或错误信息。Promise有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。通过调用Promise的then()方法可以注册回调函数来处理异步操作的结果。

async/await是ES8引入的一种更加简洁的处理异步操作的方式。async函数是一个返回Promise对象的函数,其中可以使用await关键字来等待一个Promise对象的解决。await关键字可以暂停async函数的执行,直到Promise对象解决为止,并返回解决后的结果。

区别:

  • 语法上,Promise使用then()和catch()方法来处理异步操作的结果,而async/await使用async函数和await关键字来等待异步操作的结果。

  • 可读性上,async/await更加直观和易于理解,代码结构更加清晰,而Promise则需要通过链式调用then()方法来处理多个异步操作。

  • 错误处理上,Promise使用catch()方法来捕获错误,而async/await可以使用try-catch语句来捕获错误。

详细解答:

JavaScript的异步机制包括以下几个步骤:

(1)所有同步任务都在主线程上执行,行成一个执行栈

(2)主线程之外,还存在一个任务队列,只要异步任务有了结果,就会在任务队列中放置一个事件

(3)一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面还有哪些事件,哪些对应的异步任务,于是异步任务结束等待状态,进入执行栈,开始执行

(4)主线程不断的重复上面的第三步

promise的用法

Promise,简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果)

基本语法

 let obj = new Promise((resolve,reject) => {
        //...
        resolve('success')
    });
    
 obj.then(result => {
        console.log(result); //success
 });

运行运行

promise共有三个状态

pending(执行中)、resolve(成功)、rejected(失败)

链式调用

Promise 链式调用是一种编程模式,允许在异步操作之间顺序执行多个操作。在每个操作中,可以使用 `.then()` 方法返回一个新的 Promise,从而在异步流程中继续执行下一个操作。这样可以避免回调函数地狱,提高代码的可读性和可维护性。

链式调用的基本步骤包括:

创建一个新的 Promise 对象,并调用 `resolve` 或 `reject` 来变更其状态。

在 `then` 或 `catch` 方法中,处理成功或失败的状态。

在 `then` 方法中,可以使用 `return` 关键字返回一个新的 Promise 对象,或者直接返回普通值。

继续在下一个 `then` 方法中处理返回的 Promise 对象,或者直接处理返回的普通值。

例如,以下代码展示了如何使用 `.then()` 和 `.catch()` 方法进行链式调用:

let promise1 = new Promise((resolve, reject) => {
    resolve('new promise111111');
});
 
promise1.then(res => {
    console.log(res); // 输出: 'new promise111111'
    return '链式调用的方式';
  }).then(value => {
        console.log(value); // 输出: '链式调用的方式'
});

运行运行

在这个例子中,`promise1` 被成功地 resolve 并返回了一个值,然后 `then` 方法被调用,返回了一个新的 Promise 对象,并返回了 `'链式调用的方式'`。这个新的 Promise 对象又被继续 `.then` 处理,最终返回了 `'链式调用的方式'`。

需要注意的是,每次 `.then` 方法调用都会返回一个新的 Promise 对象,因此链式调用的结果取决于最后 `.then` 方法中返回的值或新的 Promise 对象。

错误捕获

Promise.prototype.catch用于指定Promise状态变为rejected时的回调函数,可以认为是.then的简写形势,返回值跟.then一样

let obj = new Promise((resolve,reject) => {
    reject('error');
});
 
obj.catch(result => {
    console.log(result);
})

运行运行

async、await的用法

特点简洁:异步编程的最高境界就是不关心它是否是异步。async、await很好的解决了这一点,将异步强行转换为同步处理。

async/await与promise不存在谁代替谁的说法,因为async/await是寄生于Promise,Generater的语法糖。

用法

async用于申明一个function是异步的,而await可以认为是async wait的简写,等待一个异步方法执行完成。

规则:

1 async和await是配对使用的,await存在于async的内部。否则会报错

2 await表示在这里等待一个promise返回,再接下来执行

3 await后面跟着的应该是一个promise对象,(也可以不是,如果不是接下来也没什么意义了...)

写法

async function demo() {
    let a= await sleep(100); //上一个await执行之后才会执行下一句
    let b= await sleep(a+ 100);
    let c= await sleep(b+ 100);
    return c; // console.log(c);
}
 
demo().then(result => {
    console.log(result);
});

错误捕获

如果是reject状态,可以用try-catch捕捉

let obj = new Promise((resolve,reject) => {
    setTimeout(() => {
        reject('error');
    },1000);
});
 
async function demo(item) {
    try {
        let result = await obj;
    } catch(e) {
        console.log(e);
    }
}
 
demo();

运行运行

两者区别

1、promise是ES6,async/await是ES7

2、async/await相对于promise来讲,写法更加优雅

3、reject状态:

(1)promise错误可以通过catch来捕捉,建议尾部捕获错误,

(2)async/await既可以用.then又可以用try-catch捕捉

推荐一篇Promise文章:https://juejin.cn/post/6844904181627781128

相关推荐
NoneCoder11 分钟前
CSS系列(18)-- 工程化实践详解
前端·css
請你喝杯Java1 小时前
Mac软件清单(前后端开发环境搭建)
前端·后端·macos·软件
稀土君1 小时前
角逐20万奖金!这里有一份完整的豆包MarsCode AI编程挑战赛参赛指南!
前端·人工智能·豆包marscode
杨荧1 小时前
【开源免费】基于Vue和SpringBoot的渔具租赁系统(附论文)
前端·javascript·jvm·vue.js·spring boot·spring cloud·开源
用户3623786912591 小时前
【面试题】说说你对发布订阅、观察者模式的理解?区别?_消息订阅与发布面试题
前端
想退休的搬砖人1 小时前
前端水印功能(svg,canvas文字水印,canvas图片水印)
开发语言·前端
王同学JavaNotes2 小时前
ES6 语法:强大特性全解析
前端·es6
GISer_Jing2 小时前
前端面试题目 (Node.JS-Express框架)[二]
前端·面试·node.js·express
别发呆了吧2 小时前
前端面试准备问题2
前端·经验分享
堂铭2 小时前
NextJS多语言
前端·i18n·nextjs