常见前端面试题总结

本文深入讲解JavaScript中的闭包、深拷贝与浅拷贝的区别、异步机制、数组方法等核心概念,并探讨Vue中的组件通信、v-model原理及vue-router模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

深拷贝浅拷贝

  • 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存(分支)
    1. 浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。
    2. 如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
  • 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象,是“值”而不是“引用”(不是分支)
    1. 拷贝第一层级的对象属性或数组元素
    2. 递归拷贝所有层级的对象属性和数组元素
    3. 深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大

如何理解js的异步

JS是一门单线程的语言,这是因为它运行在浏览器的渲染主线程中,而渲染主线程只有一个。而渲染主线程承担着诸多的工作,渲染页面、执行JS都在其中运行。
如果使用同步的方式,就极有可能导致主线程产生阻塞,从而导致消息队列中的很多其他任务无法得到执行。这样一来,一方面会导致繁忙的主线程白白的消耗时间,另一方面导致页面无法及时更新,给用户造成卡死现象。
所以浏览器采用异步的方式来避免。具体做法是当某些任务发生时,比如计时器、网络、事件监听,主线程将任务交给其他线程去处理,自身立即结束任务的执行,转而执行后续代码。当其他线程完成时,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。
在这种异步模式下,浏览器永不阻塞,从而最大限度的保证了单线程的流畅运行。

数组的方法

1.shift 删除数组中的第一个元素
2.pop 删除数组中的最后一个元素
3.unshift 增加元素在数组的前面
4.push 增加元素在数组的后面
5.map 循环,并且返回新的数组
6.forEach 循环,遍历
7.filter 过滤,筛选出数组中的满足条件的,并且返回新的数组
8.concat 合并数组
9.find 查找出第一个符合条件中的数组元素
10.findIndex 查找出第一个符合条件中的数组元素,所在的索引位置
11.flat 将多维数组转为一维数组
12.join将数组转为字符串
13.reverse 颠倒数组中的顺序
14.every检测数组中元素是否都是符合条件 === Boolean
15.some检测数组中元素是否有满足条件的元素 === Boolean
16.splice(start,n,添加元素) 开始位置 删除个数,添加元素
17.sort 排序
18.slice(start,end) 选中[start.end)之间的元素
19.indexOf 查找值所在的位置
20.includes 查看数组中是否存在此元素
21.copyWithin( ) 指定位置的成员复制到其他位置
22.fill( )填充数组
23.Array.from( )方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map
24.Array.of( ) 用于将一组值,转换为数组
25.flatMap( )只能展开一层数组-----flat 降维 与 map 有返回值的遍历 的结合

Cookie、Session、localStorage区别

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
  4. 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
  5. localStorage (当前)仅支持将字符串作为值,并且为了做到这一点,需要先将对象进行字符串化(存储为JSON-string),然后才可以定义值的长度限制

查看以下console.log输出什么

var a=[];
var b=a;
a[2]=2;
b[3]=3;
console.log(a.length);
console.log(b.length);
console.log(a);
console.log(b);
//输出   4、4、[空 ã2, 2, 3]、[空 ã2, 2, 3]
function Obj() {this.a = 100;}
Obj.prototype.a = 300;
Obj.a = 200;
var obj = new Obj();
console.log(obj.a); //100
setTimeout(function () {
    console.log(1)
})
new Promise(function (resolve) {
    console.log(2)
    resolve();
}).then(function () {
    console.log(3)
})
console.log(4)
//结果 2 4 3 1

vue相关面试题

组件通信

组件通信常用方法有以下8种

  • props
  • $emit/ $on
  • $children/ $parent
  • $attrs/ $listeners
  • ref
  • $root
  • eventbus 事件总线
  • vuex
    根据组件之间关系讨论组件通信可分为
  • 父子组件
    • props/$emit/$parent/ref/$attrs
  • 兄弟组件
    • $parent/$root/eventbus/vuex/pinia
  • 跨层级关系
    • eventbus/vuex/provide+inject/pinia
v-model的原理
  • v-model 本质上不过是语法糖,可以用v-model指令在表单 <input><textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。v-model 会忽略所有表单元素的 valuecheckedselected 特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
  • v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
    • texttextarea 元素使用 value 属性和input事件;
    • checkbox radio 使用 checked 属性和 change 事件;
    • select 字段将 value 作为 prop 并将change作为事件。
v-if和v-for哪个优先级更高

回答范例:

  1. 实践中不应该把v-for和v-if放一起
  2. 在vue2中,v-for的优先级是高于v-if,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件,哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会比较浪费;另外需要注意的是在vue3中则完全相反,v-if的优先级高于v-for,所以v-if执行时,它调用的变量还不存在,就会导致异常
  3. 通常有两种情况下导致我们这么做:
    • 为了过滤列表中的项目(比如v-for="user in users" v-if="user.isActive" )。此时定义一个计算属性(比如activeUsers),让其返回过滤后的列表即可(比如users.filter(u=>u.isActive) ')。
    • 为了避免渲染本应该被隐藏的列表(比如v-for="user in users" v-if="shouldShowUsers" )。此时把v-if移动至容器元素上(比如ulol)或者外面包一层template即可
ref和toRef区别
  1. ref本质是拷贝,修改响应式数据不会影响原始数据;toRef的本质是引用关系,修改响应式数据会影响原始数据
  2. ref数据发生改变,界面会自动更新;toRef当数据发生改变是,界面不会自动更新
  3. toRef传参与ref不同;toRef接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性
ref和reactive区别
  • 从定义数据角度对比:
    • ref用来定义:基本类型数据
    • reactive用来定义:对象(或数组)类型数据
    • 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象
  • 从原理角度对比:
    • ref通过Object.defineProperty()getset来实现响应式(数据劫持)。
    • reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
  • 从使用角度对比:
    • ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value
    • reactive定义的数据:操作数据与读取数据:均不需要.value
计算属性和watch区别
  1. 计算属性在调用时需要在模板中渲染,修改计算所依赖元数据;watch在调用时只需修改元数据。
  2. 计算属性默认深度依赖,watch默认浅度观测。
  3. 计算属性适合做筛选,不可异步;watch适合做执行异步或开销较大的操作。
vue-router 有几种模式
  1. hash模式
    • 在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端
    • 单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
    • 每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。
    • 可通过window.location.hash属性读取 hash 值,并且 window.location.hash 这个属性可读可写。
    • 使用 window.addEventListener("hashchange", fun) 可以监听 hash 的变化
  2. history模式
  3. abstract模式
  4. 总结
    1. hash 和 history 的使用方式差不多,hash 中路由带 # ,但是使用简单,不需要服务端配合,站在技术角度讲,这个是配置最简单的模式,本人感觉这也是 hash 被设为默认模式的原因
    2. history 模式需要服务端配合处理404的情况,但是路由中不带 # ,比 hash 美观一点。
    3. abstract 模式没有使用浏览器api,可以放到node环境或者桌面应用中, 本人感觉是对 spa应用 的兜底和能力扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值