一、前言

经过三个月的等待,最近终于是约了两场线上面试。一个是直接技术面,一个是过了笔试然后进行的技术面。
回答的不算差但也算不上好,一些很基本的问题反而答不上来,脑子一片空白。个人感觉通过的机会比较渺茫。
但是问题不大,咱主打一个乐观。起码这两场面试后可以让我查缺补漏,让我之前模糊的知识点变得清晰。而不是浪费几十分钟说了一堆没用的废话然后还影响我的心情。

在这里非常感谢下面这篇文章,让我提前复习了一些知识点,不然面试效果只会更差。
前端面试题汇总大全(含答案)– 持续更新

二、问答

1. 箭头函数和普通函数区别

  1. 箭头函数不能用于构造函数
  2. this指向不同,箭头函数不创建this,也可以说箭头函数本身没有this,但是它在声明时可以捕获其所在上下文的this供自己使用。this一旦被捕获,就不再发生变化。
  3. 箭头函数不绑定arguments,取而代之用rest参数…解决
  4. 其他区别
    (1).箭头函数不能Generator函数,不能使用yeild关键字。
    (2).箭头函数不具有prototype原型对象。
    (3).箭头函数不具有super。
    (4).箭头函数不具有new.target。
  5. 总结:
    (1).箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
    (2).普通函数的this指向调用它的那个对象

2. NodeList和Array的区别

ChatGPT回答:
NodeList和Array是JavaScript中常见的两种数据类型,它们在某些方面有一些区别。

  1. 类型:
    NodeList是一个类数组对象,它表示一个由DOM元素节点组成的集合。它通常是通过使用像querySelectorAll这样的DOM方法返回的结果。
    Array是JavaScript中的内置数组类型,用于存储和操作一组有序的数据。
  2. 方法和属性:
    NodeList对象具有一些特定的方法和属性,例如item(index)方法用于通过索引获取节点、length属性表示节点数量等。然而,它没有像Array那样丰富的内置方法,例如push、pop、forEach等。
    Array对象具有丰富的内置方法和属性,可以方便地操作数组元素,例如push、pop、forEach、slice等。
  3. 可迭代性:
    NodeList对象不是可迭代的(iterable),不能直接使用for…of循环来遍历其中的元素。如果要遍历NodeList,需要使用传统的for循环或将其转换为一个数组后再进行遍历。
    Array对象是可迭代的,可以使用for…of循环或其他迭代方法(如forEach、map)来遍历数组元素。
  4. 功能差异:
    由于NodeList是基于DOM结构的,所以它在动态性方面更强。当文档结构发生变化时,NodeList会自动更新,以反映最新的DOM状态。这意味着如果使用querySelectorAll获取了某个元素的NodeList,并且之后文档中添加或移除了相应的元素,NodeList会自动更新,而不需要重新查询。相比之下,Array是静态的,不具备自动更新的能力。

综上所述,NodeList适用于处理DOM节点集合,而Array则适用于通用的数据存储和操作。如果需要使用数组的大部分方法和功能,可以将NodeList转换为Array,例如通过Array.from(nodeList)或使用扩展运算符[…nodeList]。

3. 类型判断的几种方法

  1. typeof
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    typeof 1           //number
    typeof 'a' //string
    typeof true //boolean
    typeof undefined //undefined

    // 使⽤typeof来判断null和引⽤类型 返回的结果都是 'object'
    typeof null //object
    typeof {} //object
    typeof [1,2,3] //object
    function Fn(){}
    typeof new Fn() //object
    typeof new Array() //object
  2. instanceof
    这种⽅式判断有个弊端:对于number,string,boolean这三种基本数据类型,只有通过构造函数定义⽐如:let num =new Number(1);这样定义才能检测出。
    适合进行引用类型的判断。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function A(name,age){
    this.name = name;
    this.age = age;
    }
    a = new A('张三',18);
    console.log(a instanceof A) //true
    obj = new Object()//创建⼀个空对象obj
    //或者通过字⾯量来创建:
    obj = {}
    console.log(obj instanceof Object); // true

    arr = new Array() //创建⼀个空数组arr 或arr = []
    console.log(arr instanceof Array ); // true

    date = new Date()
    console.log(date instanceof Date ); // true
    // 注意:instanceof后⾯⼀定要是对象类型,instanceof前⾯相当于它的实例对象,
    // 后⾯的对象类型⼤⼩写不能写错,该⽅法试⽤⼀些条件选择或分⽀
  3. constructor
    constructor是原型对象的属性指向构造函数。这种⽅式解决了instanceof的弊端,可以检测出除了undefined和null的9种类型(因为它两没有原⽣构造函数)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    let num = 23;
    let date = new Date();
    let str = "biu~";
    let reg = new RegExp();
    let bool = true;
    let fn = function () {
    console.log(886);
    };
    let array = [1, 2, 3];
    console.log(num.constructor); // [Function: Number]
    console.log(date.constructor); // [Function: Date]
    console.log(str.constructor); // [Function: String]
    console.log(bool.constructor); // [Function: Boolean]
    console.log(fn.constructor); // [Function: Function]
    console.log(reg.constructor); // [Function: RegExp]
    console.log(array.constructor); // [Function: Array]
    array.constructor == Array; // true
  4. 通过Object下的toString.call()⽅法来判断
    适用所有数据类型,是最好的方法。返回的是字符串类型。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object.prototype.toString.call();
    console.log(toString.call(123)); //[object Number]
    console.log(toString.call('123')); //[object String]
    console.log(toString.call(undefined)); //[object Undefined]
    console.log(toString.call(true)); //[object Boolean]
    console.log(toString.call({})); //[object Object]
    console.log(toString.call([])); //[object Array]
    console.log(toString.call(function(){})); //[object Function]
    console.log(toString.call(null)); //[object Null]
    console.log(toString.call(undefined)); //[object Undefined]
  5. 其他
    Array.isArray() 静态方法用于确定传递的值是否是一个 Array。

4. CSS权重

!important > 行内样式(比重1000)> ID 选择器(比重100) > 类选择器(比重10) > 标签(比重1) > 通配符 > 继承 > 浏览器默认属性

通常可以将css的优先级由高到低分为6组:

  1. 第一优先级:属性后面使用!important。它会覆盖页面内其他位置定义的元素样式。
  2. 第二优先级:在html中给元素标签加style,即内联样式/行内样式。(style=”…”)
  3. 第三优先级:由一个或多个id选择器来定义。 (#box{…})
  4. 第四优先级:由一个或多个类选择器、属性选择器、伪类选择器定义。 (.classname{…})
  5. 第五优先级:由一个或多个类型选择器定义。 (div{…})
  6. 第六优先级:通配选择器。 (*{…})

5. CSS选择器有哪些

1、元素选择器 标签名{ }
2、id选择器 #id属性值{ }
3、类选择器 ·class属性值{ }
4、分组选择器(并集选择器).a, .b{}
5、复合选择器(交集选择器).a.b{}
6、通配选择器 *{}
7、后代元素选择器 ul li{}
8、子元素选择器 ul>li{}
9、伪类选择器 a:hover{}
10、属性选择器

1
2
3
4
5
6
7
8
9
10
/* 选取含有指定属性的元素 */
[属性名]
/* 选取含指定属性值的元素 */
[属性名=“属性值”]
/* 选取属性值以指定内容开头的元素 */
[属性名^="属性值"]
/* 选取属性值以指定内容结尾的元素 */
[属性名$="属性值"]
/* 选取属性值包含指定内容的元素 */
[属性名*="属性值"]

11、兄弟元素选择器
+选择器
作用:选中一个元素后紧挨着的指定的兄弟元素
语法:前一个+后一个(作用在后一个)
~选择器
作用:选中后边所有的制定兄弟元素
语法:前一个~后边所有

6. Vue父传子有几种方法

1、Props
2、Provide/Inject (忘记了,没答上来)

7. 转字符串方法

  1. String()

    1
    2
    3
    4
    5
    6
    console.log(String(123)); // '123'
    console.log(String([1, 2, 3])); // '1,2,3'
    console.log(String({ a: 1 })); // '[object Object]'
    console.log(String(null)); // 'null'
    console.log(String(undefined)); // 'undefined'
    console.log(String(function () { })); // 'function () { }'
  2. toString()
    可将number, boolean, array, object等转换为字符串。局限性更大。

  3. 拼接字符串

    1
    2
    3
    4
    5
    console.log(123 + ''); // '123'
    console.log([1, 2, 3] + ''); // '1,2,3'
    console.log({ a: 1 } + ''); // '[object Object]'
    console.log(null + ''); // 'null'
    console.log(undefined + ''); // 'undefined'
  4. JSON.stringify()

    1
    2
    3
    4
    5
    console.log(JSON.stringify(123)); // '123'
    console.log(JSON.stringify([1, 2, 3])); // '[1,2,3]'
    console.log(JSON.stringify({ a: 1 })); // '{"a":1}'
    console.log(JSON.stringify(null)); // 'null'
    console.log(JSON.stringify(undefined)); // 'undefined'

字符串格式化:

1
2
3
4
console.log(typeof JSON.parse('123')); // number
console.log(typeof JSON.parse('[1, 2, 3]')); // object
console.log(typeof JSON.parse('{"a":1}')); // object
console.log(typeof JSON.parse('null')); // object

8. 简述一下你对 HTML 语义化的理解?

用正确的标签做正确的事情。
html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;即使在没有样式 CSS 情况下也以一种文档格式显示,并且是容易阅读的;
搜索引擎的爬虫也依赖于 HTML 标记来确定上下文和各个关键字的权重,利于 SEO;
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。

9. new的过程

  1. 创建一个新的空对象。
  2. 将这个新对象的原型指向构造函数的原型。
  3. 将构造函数的this指向这个新对象。
  4. 执行构造函数中的代码,初始化这个新对象。
  5. 返回这个新对象。

10. HTML5新特性

  1. 语义化标签
    HTML5引入了许多新的标签,这些标签使得网页更加具有语义化,有利于搜索引擎的优化和页面的可访问性。
  2. 表单增强
    HTML5引入了一些新的表单元素,这些元素可以帮助开发者更方便地构建表单,提供更好的用户体验。以下是HTML5中一些常用的新表单元素:
  3. 视频和音频支持
    HTML5中引入了一些新的视频和音频相关的标签,以下是其中一些常用的标签:
  4. Canvas绘图
    HTML5引入了Canvas标签,可以用于在网页中绘制图形和动画。它提供了一个矩形区域,用于在其中绘制图像、文本、图形以及动态的图形和动画效果。
  5. Web存储
    HTML5提供了localStorage和sessionStorage两种本地存储方式,使得网页可以在本地存储数据,并且可以跨页面访问。
  6. 地理定位
    HTML5提供了navigator.geolocation对象,可以通过浏览器获取用户的地理位置信息。
  7. Web Workers
    HTML5提供了Web Workers机制,使得网页可以通过JavaScript创建多个线程,提高页面的性能和响应速度。
  8. Web Socket
    HTML5提供了WebSocket协议,可以实现全双工通信,使得网页可以实时地和服务器进行交互。
  9. CSS3支持
    HTML5和CSS3是一起发布的,HTML5提供了对CSS3的支持,使得开发者可以更加方便地实现各种动画效果和布局。

11. 常见的HTML块级元素、行内元素、行内块元素分别有哪些?

  1. 块级
    1
    2
    3
    4
    5
    6
    7
    <p>:用于表示段落。
    <h1> - <h6>:用于表示标题,h1 是最高级别的标题。
    <ul><ol><li>:用于创建无序列表和有序列表。
    <div>:用于分组和布局页面元素。
    <table><tr><td>等:用于创建表格。
    <hr>:用于创建水平线。
    <pre>:用于展示预格式化的文本,其中的空格、回车等会保留在输出结果中。
  2. 行内
    1
    2
    3
    4
    5
    6
    <a>:用于创建超链接。
    <span>:用于包含文本和其他行内元素,可以用于实现文本的样式和布局效果。
    <b><i><u><strong><em><small><sup><sub>等:用于对文本进行修饰和强调。
    <br>:用于强制换行。
    <code><var><kbd>等:用于表示计算机代码和用户输入。
    <q><cite><blockquote>等:用于表示引用和短文本块。
  3. 行内块
    1
    2
    3
    4
    5
    6
    <img>:用于插入图片,可以通过设置其宽度和高度来控制图片的大小,但是在默认情况下,它是一个行内块级元素。
    <button>:用于创建按钮。
    <input>:用于创建输入框和表单元素。
    <select>:用于创建下拉菜单。
    <textarea>:用于创建多行文本输入框。
    <label>:用于创建表单标签。

12. 块级元素、行内元素、行内块元素区别是什么?

一、块级元素:
1.总是从新的一行开始。
2.宽高可控。(margin、padding都可以设置)
3.没有设置宽高时,默认为100%。
4.可以包含块级元素和行内元素。
5.块级文字元素不能放入其他块级元素。
6.大多为结构标签。

二、行内元素:
1.和其他元素都在一行。
2.高度、宽度以及外边距上下都是不可控的。
3.宽高就是内容的高度,依靠自身字体大小和图形支撑结构的,不可以改变。
4.行内元素只能行内元素,不能包含块级元素。
5.行内元素的paddding左右可以设置。
6.margin只能够设置水平方向的边距,即:margin-left和margin-right,设置margin-top和margin-bottom无效。
7.块级大多为结构性标记。

三、行内块级元素:
综合块级元素与行内元素的特性,可设宽高(默认是内容宽高),也可以设置内外边距。

13. localStorage和sessionStorage和cookie的区别

一、存储的时间有效期不同

1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
3、localStorage的有效期是在不进行手动删除的情况下是一直有效的

二、存储的大小不同
1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)

三、与服务端的通信
1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信

14. CSS3新特性

1、选择器:CSS3引入了新的选择器,如伪类选择器、伪元素选择器等,使得选择元素更加灵活和精确。
2、边框圆角:CSS3允许通过 border-radius 属性为元素的边框添加圆角,创建圆形、椭圆形或具有不同角度的矩形边框。
3、盒阴影:使用 box-shadow 属性,可以为元素添加投影效果,包括阴影的颜色、大小、模糊度和偏移量等。
4、渐变:CSS3引入了线性渐变和径向渐变,允许在元素的背景中创建平滑过渡的颜色效果。
5、过渡:通过使用 transition 属性,可以实现在元素状态改变时平滑地过渡属性值,如颜色、大小、位置等,提供更丰富的动画效果。
6、动画:CSS3的 @keyframes 规则允许创建复杂的动画效果,通过定义关键帧和过渡细节来控制动画的执行。
7、变形:使用 transform 属性,可以对元素进行旋转、缩放、倾斜和平移等变换操作,创造出令人惊艳的效果。
8、字体:CSS3提供了更多的字体控制选项,包括使用 @font-face 规则引入自定义字体文件,以及设置字体的粗细、斜体、大小调整和字间距等。
9、多列布局:通过 column-count 和 column-width 等属性,可以将文本内容分成多列显示,类似报纸或杂志的版面布局。
10、媒体查询:媒体查询允许根据设备的特性和屏幕尺寸来适应不同的样式和布局。通过媒体查询,可以创建响应式网页设计,使网页在不同设备上显示良好。
11、弹性盒子布局: Flexbox 是一种用于创建灵活且自适应布局的模型。它通过定义容器和项目之间的关系,实现了更简洁和可伸缩的布局方式,使得元素在不同屏幕尺寸下能够自动调整和对齐。
12、网格布局: Grid 布局是一个强大的二维网格系统,可用于更复杂的布局需求。它允许将页面分割为行和列,控制项目在网格中的位置和大小,实现灵活的网格布局。
13、过滤效果:CSS3的 filter 属性允许应用各种图形效果到元素上,如模糊、亮度调整、对比度调整、灰度化、色彩反转等,为图像和元素添加特殊的视觉效果。

15. ES6新特性

  1. 块级作用域:ES6引入了let和const关键字,可以在块级作用域中声明变量。使用let声明的变量只在当前作用域内有效,避免了变量提升和全局命名冲突的问题。而使用const声明的常量是一个只读变量,一旦被赋值,就不能再改变。
  2. 箭头函数:箭头函数是ES6中的一种新的函数声明方式,使用箭头(=>)取代了传统的function关键字。箭头函数具有更简洁的语法,并且自动绑定了上下文,解决了回调函数中this指向问题。
  3. 解构赋值:解构赋值是一种从数组或对象中提取值并赋值给变量的语法。在ES6中,可以使用解构赋值语法快速获取数组或对象中的元素,简化了代码编写和数据交换。
  4. 默认参数:ES6引入了函数的默认参数,允许在函数定义时为参数提供默认值。如果调用时未传递参数,将使用默认值。这样可以简化函数的使用,并且可以传递部分参数,而不是全部参数。
  5. 扩展运算符:扩展运算符可以将数组或对象展开,提取出其中的元素。在函数调用或数组和对象字面量中,使用…语法可以将数组或对象展开成独立的元素,或将多个元素合并成数组或对象。
  6. 模板字符串:模板字符串是一种更方便的字符串拼接方式,使用反引号(`)定义字符串,并可以在其中插入变量和表达式,提高了代码的可读性和可维护性。
  7. 类和模块:ES6引入了类(class)的语法糖,使得面向对象编程更加简洁和易用。类可以通过extends关键字实现继承,使用super关键字调用父类的方法。此外,ES6还引入了模块化的概念,通过import和export关键字可以方便地导入和导出模块。
  8. 迭代器和生成器:ES6中引入了迭代器和生成器的概念,可以简化处理集合和异步编程的复杂度。迭代器是一个包含next()方法的对象,可以按照定义的顺序逐个返回值。而生成器是一种特殊的函数,可以通过yield关键字将状态保存下来,并在需要的时候恢复执行。
  9. Promise对象:Promise是异步编程的一种解决方案,可以避免回调地狱和提供更好的错误处理。Promise对象可以表示一个异步操作的最终完成或失败,并能够链式调用和处理多个异步操作。
  10. 模块化导入和导出:ES6中的模块化语法可以更好地组织和管理代码,提供了import和export关键字,以及export default关键字来导入和导出模块。

16. 阻止a标签跳转有几种方法

  1. <a href="javascript:;">aaaaa</a>
  2. <a href="https://leonus.cn" onclick="return false">aaaaa</a>
  3. <a href="https://leonus.cn" onclick="event.preventDefault()">aaaaa</a>

17. 浏览器输入URL后发生了什么

1、DNS域名解析。
2、建立TCP连接。
3、发送HTTP请求。
4、服务器处理请求。
5、返回响应结果。
6、关闭TCP连接。
7、浏览器解析HTML。
8、浏览器布局渲染。

18. 清除浮动的几种方法

一、 额外标签法
给谁清除浮动,就在其后额外添加一个空白标签 。
优点: 通俗易懂,书写方便。(不推荐使用)
缺点: 添加许多无意义的标签,结构化比较差。
给元素small清除浮动(在small后添加一个空白标签clear(类名可以随意),设置clear:both;即可)

二、 父级添加overflow方法
可以通过触发BFC的方式,实现清楚浮动效果。必须定义width或zoom:1,同时不能定义height,使用overflow:hidden时,浏览器会自动检查浮动区域的高度
优点: 简单、代码少、浏览器支持好
缺点: 内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素。不能和position配合使用,因为超出的尺寸的会被隐藏。

三、使用after伪元素清除浮动
:after方式为空元素的升级版,好处是不用单独加标签了。IE8以上和非IE浏览器才支持:after。zoom(IE专有属性)可解决ie6,ie7浮动问题(较常用推荐)
优点: 符合闭合浮动思想,结构语义化正确,不容易出现怪问题(目前:大型网站都有使用,如:腾迅,网易,新浪等等)
缺点: 由于IE6-7不支持:after,使用zoom:1

四、使用before和after双伪元素清除浮动(较常用推荐)

三、参考文献