前言
给小伙伴分享一些我面试出现的题目,给还在备战面试的小伙伴一点点经验,也希望大佬多给我提提建议。让我们在这春暖花开、百花齐放的三四月拿下心仪的工作。
如果你对此感兴趣,可以看我上一篇文章 前端面试经验
请你说一下vue中computed和watch他们分别具有什么功能,有什么区别?
computed
计算属性是基于它们的依赖进行计算的属性,并且具有缓存机制。这意味着计算属性只有在其依赖的数据发生变化时才会重新计算,否则会返回之前缓存的值。
它支持缓存,只有依赖的数据发生了变化,才会重新计算
不支持异步,当Computed中有异步操作时,无法监听数据的变化
computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
watch
监视属性用于监听指定数据的变化,并在数据变化时执行指定的回调函数。与计算属性不同,监视属性不具有缓存机制,每次数据变化都会触发回调函数。
它不支持缓存,数据变化时,它就会触发相应的操作
支持异步
监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
总结
computed 计算属性是基于其它属性值的计算得出的属性,具有缓存性,只有依赖的属性值发生改变时才会重新计算。
watch 侦听器更像是一个观察者,用于监视特定数据的变化,无缓存性,每当被监听的数据变化时都会执行相应的回调函数。
代码题一
var a = 30
function foo(){
alert(a)
var a = 10
alert(a)
a = 20
function a() {}
alert(a)
}
foo()
function a(){}
10
20
这段代码考察的知识点包括:
变量声明提升:JavaScript 在执行代码前会将变量声明提升至作用域的顶部,但不会提升变量的赋值操作。
函数声明与变量声明的优先级:在同一个作用域内,函数声明的优先级高于变量声明,但如果变量已经被赋值,则函数声明不会覆盖该变量。
作用域链:函数内部能够访问外部作用域的变量,但如果函数内部有同名变量,则会优先访问函数内部的变量。
首先,在foo()函数内部,存在一个变量声明var a和一个函数声明function a() {}。因为函数声明会优先于变量声明,所以在执行alert(a)时,a 实际上是一个函数,即 function a() {},因此会输出 function a(){}。
然后,在 var a = 10 被执行之后,a 被重新赋值为 10。
在 a = 20 被执行之后,a 变量的值被更新为 20。
最后,在函数声明 function a() {} 被执行之后,由于此时 a 已经被赋值为 20,所以函数声明不会对 a 变量产生影响。
代码题二
let setSize = new Set()
setSize.add([1])
setSize.add([2])
console.log(setSize.size)
这段代码考察的知识点包括:
Set 集合的特性:Set 是一种集合类型,它存储独特的值,不允许重复。
JavaScript 中对象比较的特性:JavaScript 中的对象(包括数组)是按引用进行比较的,而不是按值进行比较的,因此两个相同内容的数组在内存中的地址不同,会被认为是不同的对象。
Set 集合的大小属性:通过 .size 属性可以获取 Set 集合中的元素数量。
这段代码创建了一个Set集合,并向集合中添加了两个不同的数组[1]和[2]。
setSize.add([1]) 添加了一个包含元素 1 的数组 [1] 到 Set 集合中。 setSize.add([2]) 添加了一个包含元素 2 的数组 [2] 到 Set 集合中。
由于这两个数组是不同的对象,它们虽然内容相同,但在内存中的地址是不同的,因此它们被认为是两个不同的值,都会被成功添加到 Set 集合中。
最后输出 Set 集合的大小。由于 Set 集合只包含了两个不同的数组,因此它的大小为2。
编程题一
红灯3秒亮一次,绿灯2秒亮一次,黄灯1秒亮一次;如何让三个灯不断交替重复亮灯?
function red() {
console.log("red");
}
function green() {
console.log("green");
}
function yellow() {
console.log("yellow");
}
const light = function (timer, cb) {
return new Promise(resolve => {
cb()
setTimeout(() => {
resolve()
}, timer)
})
}
const step = function () {
Promise.resolve().then(() => {
return light(3000, red)
}).then(() => {
return light(2000, green)
}).then(() => {
return light(1000, yellow)
}).then(() => {
return step()
})
}
step();
定义一个light()函数,它接受两个参数:timer和cb。这个函数返回一个 Promise。在函数内部,它首先执行传入的回调函数 cb(),然后通过 setTimeout 在timer毫秒后解决(resolve)这个 Promise。这就模拟了交通信号灯的变化和时间间隔。
在 Promise 链中,通过then()方法依次调用light()函数来控制灯的变化和时间间隔。首先是红灯,等待 3000 毫秒(3秒),然后是绿灯,等待 2000 毫秒(2秒),最后是黄灯,等待 1000 毫秒(1秒)。这些时间间隔分别对应红灯、绿灯和黄灯的显示时间。
编程题二
实现a,b两个对象值互换
let a = {a:1, value:1}
let b = {b:2, value:2}
let a = {a:1, value:1};
let b = {b:2, value:2};
let temp = Object.assign({}, a);
a = Object.assign({}, b);
b = Object.assign({}, temp);
console.log(a);
console.log(b);
通过创建一个临时变量temp,将对象a的值存储在其中。然后,将对象b的值赋给对象a,再将临时变量中存储的对象a的原始值赋给对象b。最后,输出了交换后的值。
编程题三
给定一个未经排序的整数数组,找到最长连续递增序列的长度。
例如,在数组 [1,3,5,4,7] 中,最长连续递增序列是 [1,3,5],其长度为 3。
function foo(nums) {
if (nums.length === 0) return 0;
let maxLength = 1; // 最长连续递增序列的长度
let currentLength = 1; // 当前连续递增序列的长度
for (let i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
currentLength++;
maxLength = Math.max(maxLength, currentLength); /
} else {
currentLength = 1;
}
}
return maxLength;
}
首先检查输入的数组是否为空,如果为空则直接返回 0,因为空数组没有连续递增序列。
在循环中,首先检查当前元素是否大于前一个元素。如果是,则说明当前元素在递增序列中,此时增加当前连续递增序列的长度currentLength++,并且更新最长连续递增序列的长度 maxLength,取当前长度和历史最长长度的最大值。如果不是,则当前递增序列中断,将 currentLength重新设置为 1。
最后,函数返回 maxLength,即最长连续递增序列的长度