前言:小编最近一直专心于在打怪升级中,本次笔试和面试打算也做一次总结,直接上干货...
线上笔试部分:
1. 代码分析题 :
for(var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i)
}, 0 )
}
for(let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i)
}, 0 )
}
2. 代码分析题:
function getType(...args) {
console.log(typeof args)
}
getType(18)
3. 问答题:px、rem、em、vw、vh 的区别?
1. px(像素):像素是最常见的单位,表示屏幕上的一个物理像素点。它是一个绝对单位,
具有固定的大小,不随页面缩放而改变。使用px单位可以精确地控制元素的尺寸。
2. rem(根元素字体尺寸):`rem`是相对单位,它相对于根元素(通常是`<html>`元素)
的字体尺寸。如果根元素的字体大小为16px,那么1rem等于16px。当根元素的字体大小
发生改变时,所有使用rem单位的元素尺寸会按比例调整。rem单位适合用于响应式设计,
可以根据根元素的字体大小来自适应调整。
3. em(父元素字体尺寸):`em`也是相对单位,它相对于父元素的字体尺寸。例如,如果
父元素的字体大小为16px,那么1em等于16px。如果一个元素的字体大小设置为2em,那
么它的字体大小将是父元素字体大小的两倍。em单位的计算是相对于父元素的字体大小,
因此在嵌套结构中使用时,会累计计算。
4. vw(视窗宽度的百分比):`vw`表示视窗(viewport)宽度的百分比。1vw等于视窗宽度
的1%。例如,如果视窗宽度为1000px,那么1vw等于10px。vw单位适合用于创建响应式布
局,可以根据视窗宽度自动调整元素的尺寸。
5. vh(视窗高度的百分比):`vh`表示视窗高度的百分比。1vh等于视窗高度的1%。例如,
如果视窗高度为800px,那么1vh等于8px。vh单位也适合用于创建响应式布局,可以根
据视窗高度自动调整元素的尺寸。
4. 事件分发的整个阶段?
1. 捕获阶段(Capture Phase):
- 事件从根节点(通常是`window`对象)向下传播,经过DOM树的层级结构。
- 在每个层级的节点上,会触发捕获阶段的事件处理程序(如果有)。
2. 目标阶段(Target Phase):
- 事件达到目标节点,即实际触发事件的节点。
- 在目标节点上,会触发事件的处理程序。
3. 冒泡阶段(Bubble Phase):
- 事件从目标节点开始向上传播,经过DOM树的层级结构。
- 在每个层级的节点上,会触发冒泡阶段的事件处理程序(如果有)。
5. get、post 的区别?
1. 数据传输方式:
- GET:通过URL的查询参数传输数据,将数据附加在URL的末尾,以键值对的形式进行
传输。例如:`https://example.com/api?param1=value1¶m2=value2`
- POST:通过请求的主体(Body)传输数据,将数据作为请求的一部分发送。数据
不会直接暴露在URL中。
2. 数据长度限制:
- GET:由于数据通过URL传输,对URL长度有限制,不同浏览器和服务器对URL长度
的限制可能不同,一般限制在几千个字符。
- POST:对数据长度没有特定限制,但服务器和网络设备可能有自己的限制。
3. 数据安全性:
- GET:数据暴露在URL中,可以被缓存、浏览器历史记录等保存下来,安全性
较低。适合传输非敏感数据。
- POST:数据不会暴露在URL中,相对安全,适合传输敏感数据,如密码、用户信息等。
4. 请求语义:
- GET:用于获取数据,请求具有幂等性,即对同一个URL多次GET请求的结
果应该是相同的,对服务器没有副作用。
- POST:用于提交数据,可能会对服务器产生副作用,如创建、修改或删除资源。
5. 缓存:
- GET:请求可以被浏览器缓存,下次请求相同URL时,可以直接从缓存中获取响应。
- POST:请求不会被浏览器缓存。
总结来说,GET适合用于获取数据、幂等操作,传输非敏感数据,而POST适合用于提交数据、
有副作用的操作,传输敏感数据。在实际应用中,根据具体需求和场景选择合适的请求方法。
6. 常见的块级元素和内联元素有哪些? 有什么区别?
常见的块级元素和内联元素如下:
块级元素:
- `<div>`
- `<p>`(这个是块级元素,小编总是当成行内元素了...)
- `<h1>`-`<h6>`
- `<ul>`
- `<ol>`
- `<li>`
- `<table>`
- `<form>`
- `<header>`
- `<footer>`
- `<section>`
- `<article>`
内联元素:
- `<span>`
- `<a>`
- `<strong>`
- `<em>`
- `<img>`
- `<input>`
- `<label>`
- `<button>`
- `<select>`
- `<textarea>`
- `<i>`
- `<code>`
区别总结如下:
1. 显示方式:
- 块级元素:默认情况下,块级元素会独占一行,即宽度自动填满父容器。块级元素可以
设置宽度、高度、内外边距等属性。
- 内联元素:内联元素在一行内显示,宽度由内容决定,不能设置宽度、高度和上下内外
边距,水平方向上的内外边距和边框会影响元素所占的空间。
1. 嵌套规则:
- 块级元素:可以包含其他块级元素和内联元素。
- 内联元素:不能包含块级元素,只能包含其他内联元素或文本。
1. 默认样式:
- 块级元素:块级元素会独占一行,通常具有明显的外边距(上下空间),如`<p>`、`<h1>`等。
- 内联元素:内联元素会在同一行内显示,没有明显的外边距,如`<span>`、`<a>`等。
1. CSS布局:
- 块级元素:块级元素可以通过CSS属性进行布局控制,可以设置宽度、高度、浮动等属性。
- 内联元素:内联元素的布局受限,不能设置宽度、高度和浮动等属性。
需要注意的是,通过CSS的`display`属性可以修改元素的显示方式,使块级元素表现为内联
元素,或将内联元素转换为块级元素。
7. 你对盒子模型的理解?
盒子模型是CSS中用于描述和布局元素的一个概念。它将每个元素看作是一个矩形的盒子,
这个盒子包含内容、内边距(padding)、边框(border)和外边距(margin)四个部分,
这些部分组成了元素的可视化框架。
盒子模型的组成部分如下:
1. 内容区(Content):盒子内部用来显示实际内容的区域,例如文本、图像等。它的
大小由内容的宽度和高度决定。
2. 内边距(Padding):内容区与边框之间的空白区域,用于控制内容与边框之间的间距。
内边距的大小由`padding-top`、`padding-right`、`padding-bottom`和`padding-left`
属性来定义。
3. 边框(Border):包围内容和内边距的线条或规则,用于界定盒子的边界。边框的样式、
宽度和颜色由`border-style`、`border-width`和`border-color`属性来定义。
4. 外边距(Margin):边框与相邻元素之间的空白区域,用于控制盒子与其他元素之间
的间距。外边距的大小由`margin-top`、`margin-right`、`margin-bottom`
和`margin-left`属性来定义。
在CSS中,`有两种常见的盒子模型`:`标准盒子模型(content-box)`和`IE盒子模型(border-box)`。
1. 标准盒子模型(content-box):
- 在标准盒子模型中,元素的宽度和高度仅包括内容区域(content)的大小。
- 内容区域的宽度和高度通过设置`width`和`height`属性来定义。
- 内边距(padding)、边框(border)和外边距(margin)都会增加元素的实际尺寸。
1. IE盒子模型(border-box):
- 在IE盒子模型中,元素的宽度和高度包括了内容区域(content)、内边距(padding)和边框(border)的大小。
- 内容区域的宽度和高度通过设置`width`和`height`属性来定义,但这些属性值包括了内边距和边框的尺寸。
- 外边距(margin)不会增加元素的实际尺寸,仍然是从元素的边界开始计算。
可以通过CSS的`box-sizing`属性来指定使用哪种盒子模型,默认值是`content-box`。
.box {
box-sizing: content-box;
}
.box {
box-sizing: border-box;
}
8.如何让一个元素水平竖直居中?
.container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
position: relative;
}
.element {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container {
position: relative;
}
.element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.container {
display: table;
width: 100%;
height: 100%;
}
.element {
display: table-cell;
text-align: center;
vertical-align: middle;
}
9. 代码题:
data:[
{name : 'zs', age : 18},
{name : 'ls', age : 19},
{name : 'ww', age : 18},
{name : 'zl', age : 19}
]
function solutiuon(data) {
data = data.filter( (item) => {
return item.age !== 19
})
return data
}
10. 代码题:写一个选择排序
function selectionSort(arr) {
const len = arr.length;
for (let i = 0; i < len - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex !== i) {
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
}
return arr;
}
const array = [64, 25, 12, 22, 11];
console.log(selectionSort(array));
线上面试部分(第一轮技术面试):
1. 纯CSS如何实现无线旋转?(小编当时只想到了transform:rotate();说的是结合js可以实现,但是面试官追问我能不能使用纯CSS实现,我说我不会,紧接着他下面就问我动画的实现,面试完才恍然大悟,也就是可以结合动画实现啊...)
<div class="box"></div>
.box {
width: 100px;
height: 100px;
background-color: red;
animation: spin 3s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
2.请你说说CSS动画
CSS动画是一种通过CSS属性和关键帧来创建动态效果的技术。它可以用于网页中的元素,
使其在特定时间内发生平滑的变化,产生各种视觉上的动态效果。CSS动画通常使用`@keyframes`
规则和`animation`属性来定义和控制动画效果。
以下是CSS动画的基本概念和使用方法:
1. `@keyframes`规则:`@keyframes`规则用于定义动画的关键帧。它可以指定动画在不同时间点上的样式状态。关键帧由百分比(0%到100%)或关键字(如`from`和`to`)表示。
例如:
@keyframes myAnimation {
0% {
}
50% {
}
100% {
}
}
2.`animation`属性:`animation`属性用于将动画应用于元素。它可以指定动画的名称、
持续时间、动画曲线、延迟时间、重复次数等。
例如:
.myElement {
animation-name: myAnimation;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-delay: 1s;
animation-iteration-count: infinite;
}
上述代码将应用名为`myAnimation`的动画到`.myElement`元素上,动画持续时间为2秒,
使用了缓入缓出的动画曲线,延迟1秒后开始播放,无限循环播放。
3. 动画属性缩写:`animation`属性还有一个缩写形式,可以将多个动画属性合并到一个声明中。
例如:
.myElement {
animation: myAnimation 2s ease-in-out 1s infinite;
}
上述代码与前面的示例相同,将所有的动画属性合并到了一个声明中。
通过使用`@keyframes`规则和`animation`属性,可以创建各种类型的动画效果,
如渐变、旋转、平移、缩放、淡入淡出等。可以通过调整关键帧的样式状态、动画
的持续时间和动画属性的设置来控制动画的效果和行为。
需要注意的是,CSS动画是在浏览器中通过GPU加速来执行的,因此通常比使用JavaScript
实现的动画效果更高效,能够提供更流畅的用户体验。
3. 如何使用CSS画一个圆?
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background-color: red;
}
4. 如何清除浮动
1. 使用空的额外元素并应用清除浮动样式:
.clearfix::after {
content: "";
display: table;
clear: both;
}
在需要清除浮动的父元素上添加一个类名(例如`.clearfix`),然后使用伪元素 `::after`
来创建一个空元素,并应用 `clear: both;` 样式。这将使该空元素在父元素的末尾清除浮动。
示例用法:
<div class="parent clearfix">
<div class="float-left">浮动元素 1</div>
<div class="float-left">浮动元素 2</div>
</div>
2. 使用父元素设置`overflow: hidden;`或`overflow: auto;`样式:(建立BFC)
.parent {
overflow: hidden;
}
在父元素上设置 `overflow: hidden;` 或 `overflow: auto;` 样式,会创建一个新的
BFC(块级格式化上下文),从而清除浮动效果。这是因为 BFC 会包含浮动元素,并阻止其溢出。
示例用法:
<div class="parent">
<div class="float-left">浮动元素 1</div>
<div class="float-left">浮动元素 2</div>
</div>
3. 使用父元素设置`display: flex;
.parent {
display: flex;
}
将父元素的 `display` 属性设置为 `flex`,会创建一个新的弹性容器,并自动清除浮动效果。这是因为弹性容器会自动调整其内部元素的布局,不需要特别处理浮动。
示例用法:
<div class="parent">
<div class="float-left">浮动元素 1</div>
<div class="float-left">浮动元素 2</div>
</div>
5. js如何创建dom节点、追加类名、孩子节点和添加事件监听?
1. 可以使用 `document.createElement()` 方法来创建 DOM 节点。以下是创建 DOM 节点的示例:
const divElement = document.createElement('div');
2. 追加类名:可以使用 `classList.add()` 方法来向元素追加一个或多个类名。
const element = document.getElementById('myElement');
element.`lassList.add`('newClass');
3. 添加子节点:可以使用 `appendChild()` 方法将一个新的子节点添加到指定的父节点中。
const parent = document.getElementById('parentElement');
const newChild = document.createElement('div');
parent.appendChild(newChild);
4. 添加事件监听:可以使用 `addEventListener()` 方法来为元素添加事件监听器,
以便在特定事件发生时执行相应的操作。
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log('按钮被点击了');
});
6.js 的数据类型?
`数据类型`是指存储简单数据值的数据类型,它们在内存中占据固定的空间,
并按值进行比较。JavaScript 中有以下基本数据类型:布尔类型(Boolean)、
数字类型(Number)、字符串类型(String)、空值(Null)、未定义(Undefined)
和符号类型(Symbol)。
`用数据类型`是指存储对象的引用的数据类型,它们在内存中占据不同大小的空间,
并按引用进行比较。JavaScript 中的引用数据类型包括对象(Object)、数组(Array)、
函数(Function)、日期(Date)和正则表达式(RegExp)等。
基本数据类型和引用数据类型之间的区别主要体现在以下几个方面:
1. 存储方式:基本数据类型的值直接存储在变量中,而引用数据类型存储的是对象的引用(内存地址)。
2 复制行为:基本数据类型的赋值是将值复制到新变量,互不影响。而引用数据
类型的赋值是将引用复制到新变量,它们引用同一个对象,修改其中一个会影响到另一个。
3 比较行为:基本数据类型通过值进行比较,只要值相等就视为相等。引用数据
类型的比较是通过引用进行的,只有当两个变量引用同一个对象时才视为相等。
4 可变性:基本数据类型是不可变的,一旦创建,就无法修改其值。而引用数据
类型是可变的,可以修改对象的属性和状态。
7. null 和undefined 的区别?
1. undefined:表示声明了一个变量,但没有给它赋值。它是一个表示"无"的原始值。当一个变量被声明但没有赋值时,默认其值为 undefined。函数没有返回值时,默认返回 undefined。对象属性没有赋值时,默认值也是 undefined。
示例:
let a;
console.log(a);
function foo() {
}
console.log(foo());
const obj = {};
console.log(obj.property);
2. null:表示一个被明确赋值为"空"或"无"的值。它是一个表示"空"的特殊对象值。当你想明确表示一个变量为空时,可以赋值为 null。
示例:
let a = null;
console.log(a);
虽然 null 和 undefined 都表示没有值,但它们的用法和含义略有不同。undefined 表示未
初始化或缺少值,而 null 表示明确赋值为空。在某些情况下,它们可以互相转换:
- 当将变量赋值为 null 时,它的值变为 null,表示空。
- 当将变量赋值为 undefined 时,它的值变为 undefined,表示未初始化或缺少值。
- null 是一个字面量,可以直接赋值给变量。
- undefined 是全局对象的一个属性,不是一个字面量,可以通过将变量赋值为 undefined
或不给变量赋值来得到 undefined。
在使用时,通常建议使用 null 来明确表示一个变量为空,而不要将变量设置为undefined,
除非特定情况需要明确表示未初始化。
8. js 作用域?
JavaScript 的作用域(Scope)是指变量、函数和对象在代码中可访问的范围。作用域控制着变量
的可见性和生命周期,决定了它们在代码中的可访问性和可用性。
在 JavaScript 中,有以下几种作用域:
1. 全局作用域(Global Scope):全局作用域是在整个 JavaScript 程序中都可访问的最外层
作用域。在全局作用域中声明的变量和函数可以被程序中的任何部分访问。
2. 函数作用域(Function Scope):函数作用域是在函数内部声明的变量所拥有的作用域范围。
这意味着在函数内部声明的变量对函数内部可见,而在函数外部无法访问。
3 块级作用域(Block Scope):块级作用域是在花括号({})内部声明的变量所拥有的作用
域范围。在 ES6(ECMAScript 2015)之前,JavaScript 中没有块级作用域,只有全局作
用域和函数作用域。但通过使用 let 和 const 关键字,可以在 if 语句、循环和其他代码
块中创建块级作用域。
作用域规定了变量的可见性和生命周期。变量在其作用域内可访问,超出作用域则无法访问。
当变量超出其作用域范围时,它可能会被垃圾回收机制回收内存。
JavaScript 的作用域是基于词法作用域(Lexical Scope)的,也称为静态作用域。词法作用
域是在编码阶段确定的,而不是在运行时。它使用代码中的变量和函数的声明位置来确定其作用
域,而不是根据代码执行的上下文。
9. js 闭包?
JavaScript 中的闭包(Closure)是指函数以及它所创建的作用域的组合。闭包允许函数访问其词法作用域(定义时的作用域)之外的变量。
闭包的特点如下:
1. 内部函数可以访问外部函数的变量和参数,即使外部函数已经执行完毕。
2 闭包函数可以将外部函数的变量保存在内存中,不会被垃圾回收机制回收,从而延长了变量的生命周期。
闭包的常见应用包括:
1. `封装私有变量`:通过闭包可以创建私有变量,只能通过内部函数访问,外部无法直接修改。
2 `创建函数工厂`:通过将某个通用的函数传递给一个外部函数,并在外部函数中返回该函数,
可以创建具有不同上下文的函数。
3 `实现模块化`:通过闭包可以将一组相关的函数和数据封装在一个作用域内,防止全局命名
空间的污染,并提供模块化的代码结构。
下面是一个简单的闭包示例:
function outerFunction() {
var outerVariable = 'Hello';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
var closure = outerFunction();
closure();
在上述示例中,outerFunction 是一个外部函数,内部定义了一个变量 outerVariable
和一个内部函数 innerFunction。innerFunction 作为闭包被返回,并在外部函数执行
后仍然可以访问 outerVariable。
闭包在 JavaScript 中是一个强大且常用的概念,可以实现许多有用的模式和功能。
然而,过度使用闭包可能导致内存泄漏和性能问题,因此在使用闭包时需要注意合理
使用和释放资源。
10. 说说你对input框的理解
输入框(input)是 HTML 表单中常用的元素,用于接收用户的输入数据。它提供了各种类型
的输入控件,例如文本框、密码框、单选按钮、复选框等。
输入框的作用是通过用户输入的数据收集信息、进行交互和实现用户与应用程序的互动。在 Web
开发中,输入框是构建各种表单、搜索功能、登录页面等交互性组件的基础。
HTML 中的输入框使用 `<input>` 元素来创建,通过指定不同的 `type` 属性来定义输入框
的类型。以下是一些常见的输入框类型:
- `text`:用于接收文本输入。
- `password`:用于接收密码输入,显示为掩码字符。
- `email`:用于接收电子邮件输入,浏览器会验证输入是否符合电子邮件格式。
- `number`:用于接收数字输入。
- `checkbox`:用于选择一个或多个选项。
- `radio`:用于选择单个选项。
- `file`:用于上传文件。
- `date`:用于选择日期。
- 等等。
除了 `type` 属性,输入框还可以具有其他属性,如 `id`、`name`、`value` 、`placeholder`
等,用于标识和设置输入框的属性和值。可以使用 JavaScript 或服务器端代码来访问和操作输入框的值。
11. 追问: input 框的聚焦、失焦和改变事件分别怎么表示呢
在 JavaScript 中,可以使用事件监听器(Event Listeners)来处理输入框的聚焦、失焦和改变事件。以下是它们的常用事件和对应的事件监听方法:
1. 聚焦事件(Focus Event):当用户将焦点移动到输入框时触发。
- 事件名:`focus`
- 事件监听方法:`addEventListener('focus', callbackFunction)`
示例:
const inputElement = document.getElementById('myInput');
inputElement.addEventListener('blur', function() {
console.log('Input element blurred');
});
2. 失焦事件(Blur Event):当输入框失去焦点时触发。
- 事件名:`blur`
- 事件监听方法:`addEventListener('blur', callbackFunction)`
示例:
const inputElement = document.getElementById('myInput');
inputElement.addEventListener('blur', function() {
console.log('Input element blurred');
});
3. 改变事件(Change Event):当输入框的值发生改变时触发(通常是在输入框失去焦点后)。
- 事件名:`change`
- 事件监听方法:`addEventListener('change', callbackFunction)`
示例:
const inputElement = document.getElementById('myInput');
inputElement.addEventListener('change', function() {
console.log('Input value changed');
});
12. call、apply、bind 的区别?
`call`、`apply` 和 `bind` 都是 JavaScript 中用于更改函数执行上下文(this)的方
法。它们的区别主要在于传递参数和函数调用的时间。
1. `call` 方法:
`call` 方法是在函数调用时立即改变函数的执行上下文(this)并调用函数。它可以接收
多个参数,第一个参数指定函数执行时的上下文(this),后续参数是函数调用时的参数。
语法:`function.call(thisArg, arg1, arg2, ...)`
示例:
function greet(name) {
console.log(`Hello, ${name}! I'm ${this.title}.`);
}
const person = {
title: 'Mr.'
};
greet.call(person, 'John');
2. `apply` 方法:
`apply` 方法和 `call` 方法类似,也用于改变函数的执行上下文。但它接收一个数组作为参数,
在函数调用时将数组的元素作为参数传递给函数。
语法:`function.apply(thisArg, [argsArray])`
示例:
function greet(name) {
console.log(`Hello, ${name}! I'm ${this.title}.`);
}
const person = {
title: 'Mr.'
};
greet.apply(person, ['John']);
3. `bind` 方法:
`bind` 方法也用于改变函数的执行上下文,但它不会立即调用函数,而是返回一个新的函数,
该函数绑定了指定的上下文。可以稍后调用返回的函数。
语法:`function.bind(thisArg[, arg1, arg2, ...])`
示例:
function greet(name) {
console.log(`Hello, ${name}! I'm ${this.title}.`);
}
const person = {
title: 'Mr.'
};
const boundGreet = greet.bind(person);
boundGreet('John');
13. 数组常用方法有哪些?
推荐大家去看看小编的另一篇文章,传送门如下:
juejin.cn/post/734646…
14. 追问: push 会修改原数组吗, splice 呢? 数组如何去重?
答: `push` 方法和 `splice` 方法都可以修改原数组
1. 使用 Set:
const array = [1, 2, 3, 3, 4, 4, 5];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray);
2. 使用 filter 和 indexOf:
const array = [1, 2, 3, 3, 4, 4, 5];
const uniqueArray = array.filter((value, index, self) => {
return self.indexOf(value) === index;
});
console.log(uniqueArray);
3. 使用 reduce 和 includes:
const array = [1, 2, 3, 3, 4, 4, 5];
const uniqueArray = array.reduce((accumulator, current) => {
if (!accumulator.includes(current)) {
accumulator.push(current);
}
return accumulator;
}, []);
console.log(uniqueArray);
4. 使用 ES6 的 Map
const array = [1, 2, 3, 3, 4, 4, 5];
const uniqueArray = Array.from(new Map(array.map(item => [item, item])).values());
console.log(uniqueArray);
15. js 事件循环
JavaScript 事件循环(Event Loop)是一种用于处理异步操作的机制,它确保 JavaScript
运行时能够处理事件和回调函数,使得异步代码能够以非阻塞的方式执行。
JavaScript 引擎使用单线程来执行代码,即一次只能执行一个操作。然而,JavaScript
支持异步操作,例如定时器、网络请求、事件处理等,这些异步操作不会阻塞主线程的执行。
事件循环机制确保了异步操作的执行和回调函数的触发。
以下是 JavaScript 事件循环的基本流程:
1. `执行同步任务`(Synchronous Tasks):首先,JavaScript 引擎会执行当前调用栈
中的同步任务,按照代码的顺序逐行执行。
2. `执行微任务`(Microtasks):在同步任务执行完毕后,JavaScript 引擎会检查微任
务队列(Microtask Queue),并按照顺序执行其中的微任务。
3. `渲染页面更新`:如果需要进行页面渲染,JavaScript 引擎会执行渲染操作,更新页面
的显示。
4. `执行宏任务`(Macrotasks):在执行完所有的微任务后,JavaScript 引擎会检查宏
任务队列(Macrotask Queue),并选择其中的一个任务执行。
5. `重复上述步骤`:一次循环结束后,JavaScript 引擎会再次检查微任务队列,执行其中
的微任务,然后检查宏任务队列并执行一个宏任务。这个过程不断重复,形成了事件循环。
需要注意的是,微任务比宏任务具有更高的优先级,每执行完一个宏任务后,会立即执行所有
的微任务,而不是等待下一个宏任务。这是因为微任务通常用于执行一些高优先级的操作,如更新界面状态、处理异步结果等。
16. 常见的宏任务与微任务有哪些?(小编上个问题回答 js 循环机制时没答出来,被追问了)
常见的宏任务(Macrotasks)包括:
1. 定时器任务(setTimeout、setInterval):在指定的时间间隔后执行回调函数。
2. DOM 事件(click、load、change 等):当用户与页面交互或特定的事件发生时触发回调函数。
3. Ajax 请求的回调:在发送 Ajax 请求后,当请求返回时触发回调函数。
4. I/O 操作:例如读取文件、写入文件等。
5. requestAnimationFrame:用于执行动画效果的回调函数。
常见的微任务(Microtasks)包括:
1. Promise 的回调函数:在 Promise 对象状态改变时触发的回调函数,如 `then`、`catch`、`finally`。
2. MutationObserver 的回调函数:监测 DOM 变化,并在变化发生时触发的回调函数。
3. process.nextTick(Node.js 环境):在当前执行栈结束后、下一个事件循环开始之前触发的回调函数。
17. promise的构造函数是同步还是异步执行的?
Promise 的构造函数是同步执行的。
当创建一个 Promise 对象时,构造函数内的代码会立即执行。这意味着 Promise 对象的状态(pending、fulfilled、rejected)会立即确定,并且构造函数内的代码会立即执行相应的操作。
示例:
console.log('Before creating Promise');
const promise = new Promise((resolve, reject) => {
console.log('Inside Promise constructor');
});
console.log('After creating Promise');
在上述示例中,Promise 的构造函数内部的代码会立即执行,不会等待其他异步操作的完成。
因此,无论 Promise 内部是否包含异步操作,构造函数都会同步执行。
需要注意的是,虽然 Promise 的构造函数是同步执行的,但是在构造函数内部可以执行异步
的操作,例如定时器、网络请求等。在这种情况下,Promise 对象的状态会在异步操作完成
后改变,并触发相应的回调函数(`then`、`catch`、`finally`)。
总结而言,Promise 的构造函数是同步执行的,但是 Promise 对象本身可以用于处理异步
操作,以便更好地处理异步代码和异步结果。
18. vue 和 react 的区别?
1. 学习曲线和易用性:
- Vue.js 更易学和上手,对初学者友好。它提供了简洁的`模板语法`和直观的 API,
使开发者可以快速入门。
- React 的学习曲线相对陡峭,需要对 `JSX`(JavaScript XML)语法和组件生命
周期等概念进行理解。但一旦掌握,React 提供了更大的灵活性和可扩展性。
1. 组件化开发:
- Vue.js 采用单文件组件(Single-File Components),将 HTML 模板、CSS
样式和 JavaScript 代码组合在一个文件中,使得组件化开发更加直观和维护友好。
- React 使用 JSX,将组件的结构和逻辑都放在 JavaScript 文件中,通过
JavaScript 代码编写组件。
1. 响应式和数据流管理:
- Vue.js 使用`双向数据绑定`,即视图和数据之间的变化能够互相影响,通过
`v-model` 指令可以轻松实现数据的双向绑定。
- React 使用`单向数据流`,数据从父组件传递给子组件,子组件通过 props
接收数据,通过回调函数进行状态的更新。
1. 生态系统和社区支持:
- React 生态系统非常庞大,拥有丰富的第三方库和插件,如 React Router、
Redux、Axios 等。React 的社区活跃度高,有大量的学习资源和社区支持。
- Vue.js 生态系统也在不断壮大,拥有一些流行的第三方库和插件,如 Vue Router、
Vuex、Axios 等。尽管规模较小,但也有一个积极的社区。
1. 性能和渲染优化:
- Vue.js 在性能优化方面做了很多工作,使用了`虚拟 DOM `和异步更新策略,
能够更高效地处理组件的渲染和更新。
- React 通过`虚拟 DOM` 和`高效的 Diff 算法`,能够在 UI 更新时进行最小化的 DOM 操作,
提高性能。另外,React 还提供了钩子函数和生命周期方法,使得性能优化更加灵活。
19. v-cloak 是什么?
`v-cloak` 是 Vue.js 框架中的一个指令,用于解决在初始化渲染时由于数据加载延迟而导致
的闪烁问题。
当使用 Vue.js 渲染页面时,如果页面中包含使用 Vue.js 指令或插值表达式的元素,这些元
素在初始化渲染之前可能会显示原始的模板内容,这可能导致用户在页面加载时看到未经处理的
模板内容,然后在 Vue.js 完成初始化后才得到正确的渲染结果。这种现象通常被称为 "闪烁"。
为了解决这个问题,Vue.js 提供了 `v-cloak` 指令。该指令可以与 CSS 配合使用,确保在 Vue.js 完成初始化渲染之前,元素始终处于隐藏状态。
使用 `v-cloak` 指令的步骤如下:
1. 在 Vue.js 组件或根元素上添加 `v-cloak` 属性。
<div id="app" v-cloak>
<!-- Vue.js 组件内容 -->
</div>
2. 在 CSS 中定义 `v-cloak` 的样式,使元素始终处于隐藏状态。
[v-cloak] {
display: none;
}
当 Vue.js 初始化完成后,`v-cloak` 指令会被移除,元素会显示出来并正常渲染。
使用 `v-cloak` 指令可以有效解决初始化渲染时的闪烁问题,确保用户在页面加载时不会看到
未处理的模板内容。
20. v-if 与 v-show的区别
`v-if` 和 `v-show` 是 Vue.js 条件渲染的指令。
- `v-if` 在条件为 `false` 时,元素会完全销毁,条件变为 `true` 时重新创建元素。
- `v-show` 在条件为 `false` 时,元素仅隐藏,条件变为 `true` 时恢复显示。
主要区别:
- `v-if` 在初始渲染时可以减少开销,但切换时开销较大。
- `v-show` 在初始渲染时有开销,通过修改 CSS 的 `display` 属性来控制元素的显示
和隐藏,不会涉及元素的销毁和重新创建,切换开销较小。
适用场景:
- `v-if` 适合条件较少改变或需要根据条件动态创建和销毁元素的情况。
- `v-show` 适合频繁切换显示和隐藏的情况。
21. 组件间通信方式有哪些
1. Props 和事件(父子组件通信):
- 父组件通过 props 向子组件传递数据,并在子组件中使用 props 接收数据。
- 子组件可以通过触发事件(`$emit`)将数据发送给父组件。
2. 自定义事件(兄弟组件通信):
- 通过一个共同的父组件,兄弟组件通过触发事件(`$emit`)和监听事件(`$on`)来进行通信。
3. Vue 实例作为事件中心(任意组件通信):
- 可以创建一个空的 Vue 实例作为事件中心,用于组件之间的通信。
- 组件通过该事件中心的事件监听和触发来进行通信。
4. Vuex(状态管理):Vue3使用 Pinia
- Vuex 是 Vue.js 官方提供的状态管理库,用于管理应用程序的共享状态。
- 组件通过提交 mutations 或分发 actions 来修改和获取共享状态。
5. Provide / Inject(祖先与后代组件通信):
- 祖先组件通过 `provide` 提供数据,后代组件通过 `inject` 注入数据。
- 后代组件可以直接访问祖先组件提供的数据。
6. $refs(父组件引用子组件):
- 父组件可以通过 `ref` 属性引用子组件实例,从而直接调用子组件的方法或访问子组件的数据。
7. EventBus(简单的事件总线):
- 可以使用一个简单的事件总线实例来进行组件间的通信,类似于 Vue 实例作为事件中心的方式。
22. 介绍一下AJAX
AJAX(Asynchronous JavaScript and XML)是一种用于在 Web 应用程序中进行异步通信
的技术。它允许在不刷新整个页面的情况下,通过在后台与服务器进行数据交换,更新部分页
面内容。使用 XMLHttpRequest 对象来实现 AJAX 请求。它提供了发送请求、接收响应和处
理数据的功能。
示例:
function getData() {
var xhr = new XMLHttpRequest();
var url = "https://api.example.com/data";
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var responseData = JSON.parse(xhr.responseText);
document.getElementById("result").innerHTML = responseData.message;
}
};
xhr.open("GET", url, true);
xhr.send();
}
23. 你是如何封装axios的?(答案略)
24. 实习使用的技术栈
25. 你是如何做移动端适配的,有什么方案可以实现?简单展开讲一下
1. `媒体查询`(Media Queries):
使用 CSS3 的媒体查询可以根据屏幕尺寸应用不同的样式。通过设置不同的 CSS 规则,可以根据屏幕宽度、高度或设备类型等属性调整布局和样式。
2. `Viewport`:
Viewport 是移动设备上可见区域的窗口,可以通过设置 `<meta>` 标签中的 viewport 属性来控制网页的初始缩放级别、宽度和视口大小。
3. `弹性布局`(Flexbox):
弹性布局是一种灵活的布局模型,可以自适应不同屏幕尺寸。通过使用 flex 容器和 flex 项目,可以轻松地实现自适应的布局和排列。
4. `REM` 或 `EM` 单位:
使用相对单位 REM 或 EM 可以根据根元素的字体大小来调整元素的尺寸。通过设置根元素的字体大小为相对于屏幕宽度的比例,可以实现基于屏幕尺寸的自适应布局。
5. `百分比(%)`:
百分比单位可以相对于父元素的尺寸进行计算。通过将元素的宽度、高度、间距等属性设置为百分比值,可以实现基于父元素尺寸的自适应效果。
6. `vw`(视窗宽度单位)和`vh`(视窗高度单位):
vw 和 vh 是相对于视窗宽度和视窗高度的单位,可以根据屏幕尺寸进行自适应布局。1vw 等于视窗宽度的 1%,1vh 等于视窗高度的 1%。通过设置元素的宽度、高度、字体大小等属性为 vw 或 vh 单位,可以实现基于屏幕尺寸的自适应效果。
26. git 常用命令,git fetch 和 git pull 的区别是什么
27. 反问: 公司近期的技术栈,开发方向、企业氛围
结语:以上就是这家公司前两轮的笔试和面试内容啦,面试完差不多一个小时后HR就联系说说让我准备一下复试,到时候是前端技术负责人给我面试,所以加油吧,小编还在打怪升级的路上,希望我们能够前程似锦,祝你也祝我!!!