春招前端笔试面试合集4
vue怎么引入一个枚举,在template引入枚举(常量,对象)并应用这个枚举?怎么管理项目里的枚举?
可以将枚举定义为常量或对象,并将其导入Vue组件中。然后,在模板中,可以使用该枚举的属性或键来访问其值。
要管理项目中的枚举,可以将它们定义为常量或对象,并将它们放在单独的文件中。这些文件可以命名为constants.js
或enums.js
,并将它们导出供项目中的其他文件使用。另外,也可以使用第三方库来管理和使用枚举,例如enumify
或enums
等库。
js延迟加载的方法?
defer属性
可以将<script>
标签的defer
属性设置为true
,以便在HTML文档解析完成之后再执行JavaScript文件。这样,浏览器会将脚本下载并延迟执行,直到整个文档解析完成。这种方式不会阻塞文档的解析,因此能够更快地加载页面。
动态加载
使用JavaScript代码可以在页面加载后动态加载JavaScript文件。这种方法可以在需要时加载脚本,从而提高页面加载速度。
es6模块和commonjs规范不同点?
vue的data某个属性发生变化,页面会立即方发生变化吗?
导出方式不同
ES6模块使用export
关键字来导出模块中的变量、函数或类
export default function() { /* ... */ };
而CommonJS规范使用module.exports
和exports
对象来导出模块中的变量、函数或类
module.exports = function() { /* ... */ };
导入方式不同
ES6模块使用import
关键字来导入其他模块中的变量、函数或类,
import { name } from "./module.js";
而CommonJS规范使用require()
函数来导入其他模块中的变量、函数或类
const name = require("./module.js");
算法1
设计函数生成所有有效的括号组合。输入:n = 3(数字)输出:((())),(()()),(())(),()(()),()()()
function generateParenthesis(n) { const result = []; const dfs = (left, right, str) => { if (left === n && right === n) { // 如果左右括号都用完了,将字符串加入结果中 result.push(str); return; } if (left < n) { // 如果左括号还没用完,可以添加左括号 dfs(left + 1, right, str + '('); } if (right < left) { // 如果右括号还没用完,可以添加右括号 dfs(left, right + 1, str + ')'); } }; dfs(0, 0, ''); return result; } // 测试 console.log(generateParenthesis(3)); // ["((()))","(()())","(())()","()(())","()()()"]
首先定义一个result
数组来存储所有有效的括号组合,然后定义一个递归函数dfs
,它有三个参数:left
表示左括号已经使用的数量,right
表示右括号已经使用的数量,str
表示当前生成的括号组合字符串。
在每次递归时,先判断是否已经生成了n
个左括号和n
个右括号,如果是,则将当前字符串加入结果中并返回。否则,判断左括号是否已经用完,如果没有,则可以添加左括号;判断右括号是否已经用完,如果没有且右括号数量小于左括号数量,则可以添加右括号。
最后,调用dfs
函数开始生成所有有效的括号组合,并返回结果数组。
算法2
给定排序数组,原地删除重复的元素,返回移除后数组的长度
算法3
红绿灯算法,先红灯亮3秒,然后黄灯1秒,绿灯3秒,不断循环
function removeDuplicates(nums) { let i = 0; for (let j = 1; j < nums.length; j++) { if (nums[j] !== nums[i]) { // 如果当前数字不等于前一个数字,将其赋值到下一个位置 i++; nums[i] = nums[j]; } } return i + 1; // 返回数组的新长度 } // 测试 const nums = [1, 1, 2, 2, 2, 3]; console.log(removeDuplicates(nums)); // 3 console.log(nums); // [1, 2, 3, 2, 2, 3]
首先定义一个指针i
,表示不重复的数字的最后一个位置,初始值为0。然后遍历数组,用指针j
表示当前数字的位置。如果当前数字不等于前一个数字,将其赋值到i+1
位置,并将指针i
加1。遍历结束后,i+1
表示数组的新长度。
需要注意的是,这个方法是原地修改数组的,因此在测试时需要注意原数组也会被修改。
- 讲一下vue2的技术点,平时怎么用的
- 响应式数据绑定:Vue2 的核心是响应式数据绑定机制,它可以使数据和 UI 同步变化。在 Vue2 中,我们可以使用 data 属性来定义数据,将数据和模板绑定在一起,当数据发生变化时,模板会自动更新。
- 组件化开发:Vue2 支持组件化开发,允许开发者将页面划分为多个独立组件,每个组件都有自己的数据和逻辑。Vue2 组件可以通过 template 定义 UI,通过 props 传递数据,通过 event 发送和接收消息。
- 单向数据流:Vue2 的数据流是单向的,父组件可以通过 props 传递数据给子组件,子组件不能直接修改父组件的数据,而是需要通过 event 向父组件发送消息,由父组件来修改数据。这种单向数据流可以使应用更加可控,减少数据变化的复杂性。
- 生命周期钩子:Vue2 提供了多个生命周期钩子函数,允许开发者在组件生命周期的不同阶段执行代码。例如,可以在 created 钩子中初始化数据,在 mounted 钩子中操作 DOM 元素,在 destroyed 钩子中清理资源。
- 指令和过滤器:Vue2 提供了多个指令和过滤器,允许开发者在模板中添加逻辑。例如,可以使用 v-if 指令控制元素的显示和隐藏,使用 v-for 指令遍历数组生成列表,使用 v-bind 指令绑定元素属性等。
在实现一个交互式页面时,我们可以使用 Vue2 来组件化开发,通过响应式数据绑定实现 UI 和数据的同步,使用指令和过滤器来添加逻辑,使用生命周期钩子函数来控制组件的行为等。这些技术点可以大大提高开发效率和代码可维护性。
- 组件数据传递方式
- Props:父组件通过 props 属性向子组件传递数据。子组件可以通过 props 属性来接收这些数据。这种方式实现了单向数据流,父组件的数据可以传递到子组件,但子组件不能直接修改父组件的数据。
- 事件:子组件可以通过事件向父组件发送消息。子组件可以使用 $emit 方法触发一个自定义事件,并向父组件传递数据。父组件可以通过 v-on 或 @ 指令监听子组件触发的事件,接收子组件传递过来的数据。
- 插槽:父组件可以向子组件插入内容,子组件可以使用 slot 插槽来渲染这些内容。父组件可以通过向子组件传递具名插槽来控制子组件的渲染,子组件可以在插槽中访问父组件的数据。
- Vuex:Vuex 是一个专门为 Vue 应用程序开发的状态管理库。它将所有组件的状态集中存储在一个共享的数据源中,组件可以通过 Vuex 中的 getter 和 mutation 访问和修改数据。Vuex 可以实现组件之间的数据共享和通信。
- props 子组件可以修改值吗
在 Vue 中,父组件通过 props 属性向子组件传递数据,而子组件默认不能修改 props 的值。这是因为 Vue 的数据流是单向的,父组件通过 props 将数据传递给子组件,子组件接收 props 作为自己的属性来使用,但是子组件不能直接修改 props 的值。
如果需要在子组件中修改 props 的值,可以使用一个具有本地状态的计算属性来代替 props,并将这个计算属性的值传递给子组件。在计算属性中可以对 props 的值进行修改,但是修改后的值只会在子组件中生效,不会影响到父组件的数据。
另外,如果子组件确实需要修改 props 的值,并希望这些修改能够影响到父组件的数据,可以使用 Vue 中的自定义事件和 v-model 指令来实现。子组件可以通过 $emit
方法触发一个自定义事件,并将修改后的数据作为参数传递给父组件,父组件可以在事件处理函数中接收子组件传递过来的数据,并修改自己的数据。在父组件中使用 v-model 指令绑定子组件的数据,可以让子组件的修改直接影响到父组件的数据。
- 不用emit方法,子组件可以修改父组件的数据吗
可以通过在父组件中定义一个方法,并将这个方法通过 props 传递给子组件,子组件可以在需要修改父组件数据的时候调用这个方法,将修改后的数据作为参数传递给父组件,父组件可以在方法中修改自己的数据。父组件定义了一个 updateMessage
方法,并将这个方法通过 update-message
props 传递给子组件。子组件可以通过 updateParentMessage
方法调用父组件的 updateMessage
方法,将修改后的数据作为参数传递给父组件,父组件在 updateMessage
方法中修改自己的数据。这样就可以实现子组件修改父组件的数据的效果,而不需要使用 $emit
方法。
- 组件跟插件的区别
组件是 Vue 中的一个重要概念,可以将一个页面划分成多个独立的组件,每个组件负责自己的逻辑和 UI,组件之间可以进行数据传递和通信。组件可以在 Vue 的模板中通过标签的形式引用和使用,可以是全局组件,也可以是局部组件。
插件是一种扩展 Vue 功能的方式,通过给 Vue 添加全局方法或者属性来扩展 Vue 的功能,比如 Vue Router 和 Vuex 等就是 Vue 的插件。插件通常是一个对象或者函数,可以通过 Vue.use() 方法来安装插件,并将插件添加到 Vue 中。插件可以提供一些全局功能或者在所有组件中混入一些方法或者属性。
- 写一个简单的ajax调用。
function ajax(url, method, data, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { callback(xhr.responseText); } }; xhr.open(method, url, true); if (method === 'POST') { xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); } xhr.send(data); } // 调用示例 ajax('https://example.com/api/data', 'GET', null, function(responseText) { console.log(responseText); });
- get请求的数据放在哪里
数据是通过 URL 的查询参数传递的,即将参数拼接在 URL 的末尾
- post请求数据放在哪里
对于 POST 请求,数据通常是通过请求主体传递的,即通过请求体中携带的数据来传递。请求主体的格式可以是多种多样的,例如 JSON、form-data、x-www-form-urlencoded 等等。在使用 POST 请求发送数据时,需要添加额外的请求头来告知服务器请求主体的格式。
- post请求需要添加额外请求头吗,写一下
- Content-Type: application/json:表示请求主体为 JSON 格式。
- Content-Type: application/x-www-form-urlencoded:表示请求主体为 x-www-form-urlencoded 格式。
- Content-Type: multipart/form-data:表示请求主体为 form-data 格式,常用于上传文件等操作。
- onreadystatechange是干什么的
onreadystatechange 是一个 XMLHttpRequest 对象的事件处理函数,在每次 readyState 属性发生变化时都会被调用。
XMLHttpRequest 是一种用于向服务器发送 HTTP 请求和接收服务器响应的 JavaScript 对象。当我们向服务器发送一个请求时,XMLHttpRequest 会开启一个异步请求,即在后台向服务器发送请求,并通过 onreadystatechange 事件来获取请求的响应。
在发送请求后,XMLHttpRequest 的 readyState 属性会发生变化,一般会依次变为以下五个值:
- 0: 请求未初始化,open() 方法还未调用。
- 1: 服务器连接已建立,open() 方法已经调用,但 send() 方法还未调用。
- 2: 请求已接收,send() 方法已经调用,且头部和状态已经可获得。
- 3: 请求处理中,下载中,responseText 属性已经包含部分数据。
- 4: 请求已完成,且响应已就绪,此时可以通过 responseText 属性获取响应数据。
每当 readyState 属性的值发生变化时,都会触发 XMLHttpRequest 的 onreadystatechange 事件,这时我们可以通过检查 readyState 属性的值,来判断请求的状态是否已经改变。当 readyState 变为 4 时,表示请求已经完成,我们就可以通过 responseText 属性来获取服务器返回的数据了
- http状态码
- 1xx: 信息提示
- 2xx: 成功
- 3xx: 重定向
- 4xx: 客户端错误
- 5xx: 服务器错误
- 304和浏览器缓存
304表示请求的资源未发生变化,可以直接使用缓存中的资源。当浏览器请求一个资源时,如果该资源已经被缓存且缓存未过期,则服务器可以返回一个HTTP 304状态码,告诉浏览器使用缓存中的资源而不需要再次从服务器下载。
浏览器缓存主要分为两种:
- 强缓存:浏览器在请求资源时,先检查该资源是否存在缓存中,如果存在且未过期,则直接使用缓存中的资源而不向服务器发起请求。强缓存可以通过设置响应头信息中的Cache-Control和Expires字段来控制缓存策略。
- 协商缓存:当缓存过期或者浏览器发送了一个带有Cache-Control: no-cache的请求时,浏览器会向服务器发送一个请求,服务器在收到请求后检查资源是否发生了变化,如果未发生变化则返回状态码304,告诉浏览器可以直接使用缓存中的资源。协商缓存可以通过设置响应头信息中的ETag和Last-Modified字段来控制缓存策略。
- 点击页面刷新跟f5强制刷新会使用缓存吗
- 点击页面刷新按钮或使用浏览器的刷新功能,浏览器会首先检查缓存是否过期,如果未过期,则使用缓存,否则重新从服务器获取资源。这种方式称为“普通刷新”。
- 按下F5强制刷新时,浏览器会直接向服务器请求最新版本的资源,并且忽略缓存。这种方式称为“硬性刷新”。
- cache-control有哪些属性值
- public:表示响应可以被任何中间节点缓存。
- private:表示响应只能被单个用户缓存,不能被共享缓存使用。
- max-age:表示缓存的最长时间,单位为秒。
- no-cache:表示响应可以被缓存,但需要先向服务器验证资源是否发生了变化,如果未发生变化,则可以直接使用缓存中的资源。
- no-store:表示响应不能被缓存,每次都需要向服务器请求资源。
- no-cache 和 no-store分别代表什么
no-cache和no-store都表示响应不能被简单地缓存,但它们之间的区别在于,no-cache需要向服务器验证资源是否发生了变化,而no-store则完全禁止了缓存,每次都需要向服务器请求资源。
no-cache通常用于缓存资源需要时时更新的场景,例如在线图库或金融交易网站,而no-store通常用于缓存敏感数据或需要保证每次请求都是最新的场景,例如银行卡信息或密码等。
- 外边距塌陷
外边距塌陷(Margin collapsing)指的是两个相邻元素之间的垂直外边距会合并为一个外边距的现象,导致元素之间的间距比预期的要大。外边距塌陷通常发生在垂直方向上,水平方向上的外边距不会发生合并。
外边距塌陷的解决方法如下:
- 给其中一个元素添加边框或内边距:由于边框和内边距会阻止外边距的合并,因此在其中一个元素上添加边框或内边距可以避免外边距的塌陷。
- 使用浮动或绝对定位:浮动和绝对定位可以阻止外边距的合并,因此在需要避免外边距塌陷的元素上使用浮动或绝对定位可以解决这个问题。
- 父元素添加 overflow 属性:给父元素添加 overflow 属性可以防止其高度塌陷,从而避免外边距的合并。
- 使用 BFC:BFC(块级格式化上下文)是一个独立的渲染区域,可以防止外边距塌陷。可以将需要避免外边距塌陷的元素放在一个 BFC 中,例如给元素添加 float、display: inline-block 或者 overflow: hidden 等属性。
- flex有哪些属性
- flex-direction:设置主轴的方向(row、row-reverse、column、column-reverse)。
- justify-content:设置主轴上子元素的对齐方式(flex-start、flex-end、center、space-between、space-around)。
- align-items:设置交叉轴上子元素的对齐方式(flex-start、flex-end、center、baseline、stretch)。
- align-content:设置多根轴线的对齐方式(flex-start、flex-end、center、space-between、space-around、stretch)。
- flex-wrap:设置是否换行(nowrap、wrap、wrap-reverse)。
- flex-grow:设置子元素的放大比例,默认为0,即不放大。
- flex-shrink:设置子元素的缩小比例,默认为1,即如果空间不足,所有子元素将缩小。
- flex-basis:设置子元素在主轴上的基准大小。
- flex:是flex-grow、flex-shrink和flex-basis的缩写,依次设置子元素的放大比例、缩小比例和基准大小。
- flex:1 代表的是什么
flex: 1 表示子元素在剩余空间中按比例分配,相当于 flex-grow: 1,flex-shrink: 1,flex-basis: 0%;如果有多个子元素,且它们的 flex 值都是 1,那么它们将等分剩余空间。
- 手写水平垂直居中的方式
- 使用Flex布局:在父元素上设置 display: flex 和 justify-content: center、align-items: center 即可。
- 使用绝对定位:在父元素上设置 position: relative,在子元素上设置 position: absolute 和 top: 50%、left: 50% 和 transform: translate(-50%, -50%) 即可。
- 使用表格布局:在父元素上设置 display: table,然后在一个内部元素上设置 display: table-cell 和 vertical-align: middle,另一个内部元素上设置 text-align: center 即可。
- 使用Grid布局:在父元素上设置 display: grid 和 justify-content: center、align-items: center 即可。
- 写一下子盒子宽高不确定的情况
当子盒子的宽高不确定时,可以通过以下几种方式来解决:
- 使用 Flex 布局:在父元素上设置
display: flex
,并且给子元素设置flex-grow: 1
,这样子元素就会自动填满父元素的剩余空间。 - 使用绝对定位:在父元素上设置
position: relative
,并且给子元素设置position: absolute
、top: 0
、left: 0
、right: 0
、bottom: 0
,这样子元素就会占满整个父元素。 - 使用 Grid 布局:在父元素上设置
display: grid
,并且给子元素设置grid-row: 1 / span 2
、grid-column: 1 / span 2
,这样子元素就会占据整个网格。
- translate属性
用于设置元素的位置,它可以通过 translateX
、translateY
、translateZ
来分别控制元素在水平方向、竖直方向、Z 轴方向上的移动。
还可以使用 translate3d
来同时控制元素在三个方向上的移动,其语法为 translate3d(x, y, z)
,其中 x
、y
、z
分别表示在三个方向上的移动距离。
- const 改变一个obj属性会发生什么
使用 const
定义的变量是一个常量,它的值不能被重新赋值。但是,如果这个常量是一个对象或数组,虽然不能重新赋值,但其属性或元素是可以被修改的。
- 使用es6方式对数组去重
const res = new Set([1, 2, 1, 3]); console.log([...res]);
- ['1', '2', '3'].map(parseint)输出什么
[1, NaN, NaN]parseInt()
函数可以接受两个参数,第一个是要被解析的字符串,第二个是进制数。在这个例子中,map()
函数在每个元素上调用 parseInt()
函数时,将该元素作为第一个参数传递给 parseInt()
,而 map()
函数在调用时会自动传递当前元素在数组中的索引作为 parseInt()
函数的第二个参数,因此实际上的调用为:
parseInt('1', 0)
,将'1'
作为十进制数解析为1
parseInt('2', 1)
,由于使用了非法的进制数1
,解析失败返回NaN
parseInt('3', 2)
,由于使用了非法的进制数2
,解析失败返回NaN
- promise里面报错了外面用try cache可以捕获的到吗
可以捕获到。如果 Promise 中发生了错误并且没有被捕获,那么这个错误将会向外部冒泡,直到被 try-catch 语句捕获或成为未捕获的全局错误。因此,如果你的 Promise 中有可能会出现错误,最好在 Promise 内部使用 try-catch 语句来捕获和处理错误,而不是依赖于外部的 try-catch 语句。
- 平时如何处理git冲突的
获取最新的代码
在合并冲突之前,需要确保本地代码是最新的。可以使用 git pull
命令来获取远程代码库中最新的代码。
查找冲突
一旦获取了最新的代码,可以开始合并分支。git merge,如果合并分支时发生了冲突,Git 将会提示哪些文件发生了冲突。
解决冲突
可以使用 Git 自带的工具(如 git mergetool
)来解决冲突,也可以手动编辑代码文件来解决冲突。在手动解决冲突时,需要查看文件的差异,并决定哪些部分需要保留,哪些需要删除,以及如何合并它们。
提交变更
当解决完所有冲突后,可以使用 git add
命令来将解决冲突的文件标记为已解决。使用 git commit 命令提交修改。
- 如果分支合并错了怎么办
暂停合并操作
如果还没有完成合并操作,可以使用 git merge --abort
命令来取消合并。
回滚合并操作
如果已经提交了错误的合并结果,可以使用 git revert
命令来回滚合并提交。该命令会生成一个新的提交,该提交包含撤销合并的更改。
手动解决冲突
如果出现了合并冲突,需要手动解决冲突。可以使用 git status
命令查看哪些文件出现了冲突,然后打开相应的文件进行修改,最后使用 git add
命令将修改后的文件添加到暂存区。
使用图形化工具
可以使用图形化工具如 GitKraken、SourceTree 等来帮助解决合并冲突。这些工具提供了可视化的界面,可以更直观地展示冲突的位置,帮助用户进行修改。
- 多行表头如何封装
多行表头可以通过使用<th>
元素嵌套的方式来实现,将多个单元格合并为一个表头单元格。
在Promise中,使用setTimeout时会将回调函数添加到宏任务队列中,而不是微任务队列中。
根据事件循环的执行顺序,当当前任务完成时,事件循环会首先执行所有微任务队列中的任务,然后再执行宏任务队列中的任务。因此,使用setTimeout时,回调函数将在所有微任务执行完成后被添加到宏任务队列中,并在宏任务队列中等待执行。