1.不会冒泡的事件有哪些?
答:focus、blur、load、unload、stop、readystatechange、scroll
以下是一些不会冒泡的事件列表:
- focus:元素获得焦点时触发,不会冒泡。
- blur:元素失去焦点时触发,不会冒泡。
- load:资源加载完成时触发,不会冒泡。
- unload:资源卸载时触发,不会冒泡。
- stop:某些媒体播放停止时触发,不会冒泡。
- readystatechange:文档或元素状态变化时触发,不会冒泡。
- scroll:元素滚动时触发,不会冒泡。
这些事件的特点是仅作用于目标元素本身,不会向上传播到父元素。
2.mouseEnter与mouseOver有什么区别?
答:mouseEnter只会在鼠标首次移入时触发函数,不会冒泡
mouseOver每次进入元素或子元素的边界时触发,包括从子元素移动到父元素,会冒泡
3.MessageChannel是什么?使用场景?
答:是一个JavaScript的API,可以用于浏览器中不同的标签页之间的通信,通过端口传递消息
核心特点:
1.可以双向通信:通道两端均可发送和接收消息
2.结构化克隆算法,支持传输复杂的对象,但是函数、DOM节点的那个不可克隆类型会被忽略
3.跨上下文兼容性
使用场景:
1.跨标签页通信
2.主线程与Web Workr通信
3.微前端架构
4.async、await原理?
答:他是异步操作的语法糖,为了解决回调函数的回调地域问题,引入的promise 写成了链式调用。
async 函数本质上返回一个 Promise 对象。当函数内部执行到 await 时,会暂停当前函数的执行,等待 Promise 解析完成。如果 await 后的表达式是一个非 Promise 值,它会自动被包装成 Promise.resolve。
5.Proxy能监听到对象中的对象的引入吗?
答:可以,当使用Proxy包装对象时,可以为这个对象中的任何属性设置拦截器,包括属性值是对象的情况。但是默认情况下不能自动进行自动深度监听嵌套,需要手动处理
6.如何能让var [a,b] = {a:1,b:1}解构赋值成功?
javascript
const obj = {a: 1, b: 1};
const arr = Object.values(obj); // 转换为 [1, 1]
const [a, b] = arr;
console.log(a, b); // 输出 1, 1
可以这样转,但是需要注意
- 数组解构要求右侧必须是可迭代对象
- 解构失败时变量值为
undefined,除非设置默认值
7.下面这段代码会输出什么?
javascript
foo();
var foo;
function foo()
{
console.log(1);
}
foo = function(){
console.log(2)
}
输出1,函数会在最前面,然后在是变量定义,但是一般来讲,函数声明优先级高于变量声明。
- 函数表达式(如
foo = function(){...})在赋值时才生效,不会提升函数体。
8.描述下面代码的执行结果
javascript
foo(typeof a);
function foo(){
console.log(this);
console.log(p)
console.log(typeof b)
}
let b = 0;
-
变量
a和typeof a
a未声明,但typeof a不会报错,而是返回字符串"undefined"。因此foo的参数是"undefined",但函数内部未使用参数。 -
函数与变量提升
function foo被提升到作用域顶部,因此可以在定义前调用。
let b = 0不会被提升,在foo内部访问typeof b时,由于暂时性死区(TDZ),b被视为未声明,返回"undefined"。但实际不会执行到此步。 -
错误中断
console.log(p)的引用错误会阻止后续的console.log(typeof b)执行。
9.什么是作用域链?
作用域链由执行上下文的变量对象(VO/AO)和外部环境的引用构成。每个函数在被调用时都会创建一个新的执行上下文,并将其变量对象添加到作用域链的前端。
- 全局作用域:位于作用域链的最外层,包含全局变量和函数。
- 局部作用域:函数内部的作用域,可以访问自身变量和外部作用域的变量。
10.bind、call、apply有何区别,如何实现一个bind?
bind
创建一个新函数,将指定的this值和参数绑定到原函数,调用时需手动执行。
语法:func.bind(thisArg, arg1, arg2...)
call
立即调用函数,显式指定this值和逐个传递的参数。
语法:func.call(thisArg, arg1, arg2...)
apply
立即调用函数,显式指定this值,参数以数组形式传递。
语法:func.apply(thisArg, [argsArray])
核心区别
-
执行时机 :
bind返回绑定后的函数,不立即执行;call/apply立即执行。 -
参数形式 :
call接收参数列表,apply接收参数数组。javascriptFunction.prototype.myBind = function(context, ...bindArgs) { const originalFunc = this; return function(...callArgs) { return originalFunc.apply(context, [...bindArgs, ...callArgs]); }; }; // 示例 const obj = { value: 42 }; function logValue(a, b) { console.log(this.value + a + b); } const boundFunc = logValue.myBind(obj, 1); boundFunc(2); // 输出: 45 (42 + 1 + 2)
11.common.js和es6中模块引入的区别?
1.common.js是nodejs默认采用的模块系统,主要用于服务器端开发,模块引入使用require和module.exports语法,模块同步加载,首次加载后会缓存结果,后续调用直接返回缓存。适用于文件系统环境
2.es6
ES6 模块是 ECMAScript 标准的一部分,支持静态分析,适用于浏览器和现代 Node.js 环境。使用 import 和 export 语法。
模块在编译时静态解析,支持异步加载(如动态 import()),适合浏览器环境。
12.说说 vue3 中的响应式设计原理?
答:是基于Proxy和ReflectAPI实现的,是通过ref、reactive的那个函数实现的数据劫持,依赖收集以及触发更新。
Proxy 代理对象 通过 Proxy 拦截对象的读取(get)和修改(set)操作,在访问属性时收集依赖,在修改属性时触发更新
javascript
const proxy = new Proxy(target, {
get(target, key, receiver) {
track(target, key) // 依赖收集
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(target, key) // 触发更新
}
})
reactive() 处理对象类型数据,返回 Proxy 代理对象
ref() 处理基本类型数据(如 number、string),通过 .value 访问
effect() 用于创建响应式副作用,Vue 的组件渲染本质上是一个 effect
13.script标签放在header里和放在body底部里有什么区别?
答:
将<script>标签放在<head>中会导致浏览器在解析HTML时立即下载并执行脚本,这会阻塞DOM的构建和页面渲染。若脚本较大或网络延迟较高,用户会看到较长时间的白屏。
放在<body>底部(闭合标签</body>之前)时,脚本会在DOM树构建完成后执行,用户能更快看到页面内容,适合非关键性脚本。
14.下面代码中,点击"+3"按钮后,age 的值是什么?
javascript
import {usestate }from 'react'
export default function counter(){
const [age,setAge]= useState(42);
function increment(){
setAge(age + 1);
return
<h1>Your age:{age}</h1>
<button onclick={()=>{
increment();
increment();
increment();
}}>+3</button>
</>
);
点击后 age 的值
点击"+3"按钮后,age 的值会是 43 而非预期的 45。这与 React 的状态更新机制有关。
原因分析
React 的 setState 在事件处理函数中是批量处理的。当连续调用同一个状态的更新函数时,React 会将它们合并:
js
function increment() {
setAge(age + 1); // 所有调用都基于初始值 42
}
三次 increment() 调用相当于:
js
setAge(42 + 1);
setAge(42 + 1);
setAge(42 + 1);
如需实现+3效果,应采用函数式更新:
jsx
function increment() {
setAge(a => a + 1); // 基于最新状态更新
}
15.Vue中,created和mounted两个钩子之间调用时间差值受什么影响?
答:
网络请求与异步操作
若在created中发起异步请求(如API调用),响应时间会直接影响两个钩子之间的时间差。异步操作未完成时,mounted可能已触发,导致差值增大。
DOM渲染复杂度
页面DOM结构复杂度影响渲染速度。组件模板越复杂,Vue生成虚拟DOM并挂载到真实DOM的时间越长,导致created与mounted间隔增加。
组件嵌套深度
嵌套层级深的组件需要更多时间完成子组件的初始化。父组件的mounted需等待所有子组件挂载完成,这会延长与created的时间差。
浏览器性能与资源加载
浏览器性能较差或存在未加载完成的资源(如图片、样式文件)时,DOM渲染会被阻塞,导致mounted延迟执行,差值扩大。
动态组件与懒加载
使用动态组件(如<component :is>)或路由懒加载时,组件资源的加载时间会被计入渲染流程,从而延长两个钩子之间的间隔。
16.vue中,推荐在哪个生命周期发起请求?
答:
- 关键数据优先在
created中加载以减少白屏时间。 - 非关键或 DOM 依赖的操作可放在
mounted。 - 对于复杂逻辑,结合
watch或路由守卫处理动态数据更新。
17.为什么Node在使Hes module时必须加上文件扩展名?
答:
模块解析机制差异 ES modules 是 ECMAScript 标准的一部分,设计上要求明确的文件路径。Node.js 实现时遵循了这一规范,避免隐式文件扩展名解析带来的歧义。CommonJS 允许省略扩展名,因为它是 Node.js 特有的非标准实现。
浏览器兼容性对齐 浏览器在加载 ES modules 时要求完整的 URL(包括扩展名)。Node.js 的 ES modules 设计有意与浏览器行为保持一致,减少开发者在不同环境下的认知差异。
性能优化考虑 显式扩展名减少了文件系统查找次数。CommonJS 会尝试匹配 .js、.json、.node 等扩展名,而 ES modules 直接通过完整路径定位文件,提升加载速度。
18.package.json 文件中的 devDependencies 和 dependencies 对象有什么区
别?
答:devDependencies 包含开发阶段的依赖项,不会随着项目发布到生产环境。安装时使用 --save-dev 或 -D 标志:
dependencies项目运行时必须的依赖项,会随项目一同发布到生产环境。安装时默认使用 --save 或 -S 标志(可省略):
19. React Portals 有什么用?
答:React Portals 提供了一种将子节点渲染到父组件 DOM 层次结构之外的 DOM 节点的解决方案
1.解决模态框和弹窗的层级问题
2.脱离当前 DOM 结构
20.react 和 react-dom 是什么关系?
答:React 是一个用于构建用户界面的 JavaScript 库,专注于组件化开发和状态管理。React-DOM 是 React 的官方渲染器,负责将 React 组件渲染到浏览器 DOM 中。
React 提供核心逻辑和组件化能力,包括虚拟 DOM、状态管理、生命周期等。React-DOM 提供与浏览器 DOM 交互的具体实现,将 React 的虚拟 DOM 转换为真实 DOM。
在 Web 开发中,React 和 React-DOM 通常一起使用。React 负责组件逻辑,React-DOM 负责渲染到网页。对于非浏览器环境(如 React Native),会使用其他渲染器替代 React-DOM。
注意:React 和 React-DOM 需要保持版本一致。不同版本的 API 可能有差异,版本不匹配可能导致兼容性问题。安装时应确保两者版本号相同