我有100个问题想问你(前端)

1. 语义化标签的作用是什么?常用的语义化标签有哪些?

  • 作用:提升代码可读性、SEO 友好、便于屏幕阅读器解析。
  • 常用标签<header>(头部)、<nav>(导航)、<main>(主体)、<article>(文章)、<section>(区块)、<aside>(侧边栏)、<footer>(底部)等。

2. HTML5 新增了哪些语义化标签?

新增标签包括:<header><nav><main><article><section><aside><footer><figure>(图文)、<figcaption>(图文说明)、<time>(时间)、<mark>(标记)等。

3. 块级元素与行内元素的区别?

维度块级元素行内元素
布局独占一行,宽度默认 100%同排显示,宽度由内容决定
样式属性可设置宽高、margin/padding 全方向生效宽高无效,margin/padding 仅水平生效
示例<div><p><h1><span><a><strong>

4. 盒模型由哪些部分组成?标准盒模型与 IE 盒模型的区别?

  • 组成:内容(content)、内边距(padding)、边框(border)、外边距(margin)。
  • 区别
    • 标准盒模型:width/height = 内容区域宽高
    • IE 盒模型:width/height = 内容+内边距+边框(可通过box-sizing: border-box启用)。

5. CSS 选择器的优先级是怎样计算的?

优先级从高到低:

  1. !important(最高,不建议滥用);
  2. 行内样式(style属性,权重 1000);
  3. ID 选择器(#id,权重 100);
  4. 类 / 伪类 / 属性选择器(.class/:hover/[type],权重 10);
  5. 标签 / 伪元素选择器(div/::after,权重 1);
  6. 通配符 / 继承样式(权重 0)。
  • 规则:权重叠加比较(如#id .class权重为 110),权重相同则 “后写的覆盖先写的”。

6. BFC 是什么?有哪些触发条件?

  • BFC(块级格式化上下文):是 CSS 的渲染隔离区域,内部元素的布局不受外部影响,外部也不影响内部。
  • 触发条件
    • 根元素(<html>);
    • 浮动元素(float: 非none);
    • 绝对 / 固定定位(position: absolute/fixed);
    • 溢出隐藏(overflow: 非visible);
    • 弹性 / 网格容器(display: flex/grid)。

7. 清除浮动的常见方式有哪些?

  1. 额外标签法:在浮动元素后加空标签(如<div style="clear: both;"></div>);
  2. 父元素触发 BFC:给父元素加overflow: hidden/display: flex等;
  3. 伪元素法(推荐):
    .parent::after {
      content: "";
      display: block;
      clear: both;
      visibility: hidden;
      height: 0;
    }
    .parent { zoom: 1; /* 兼容IE */ }
    

8. position 有哪些属性值?它们的区别是什么?

属性值定位基准是否脱离文档流特点
static默认,无定位忽略定位属性(top/left 等)
relative自身初始位置不影响其他元素布局
absolute最近的非 static 父元素父元素无定位则相对于根元素
fixed视口(浏览器窗口)滚动时位置固定
sticky视口 + 自身初始位置否(滚动时临时脱离)滚动到阈值时变为 fixed

9. flex 布局常用属性有哪些?

  • 容器属性
    • display: flex(启用 flex);
    • flex-direction(主轴方向:row/column);
    • justify-content(主轴对齐:flex-start/center/space-between);
    • align-items(交叉轴对齐:flex-start/center/stretch);
    • flex-wrap(是否换行:nowrap/wrap)。
  • 项目属性
    • flex(缩写:flex-grow(放大)、flex-shrink(缩小)、flex-basis(基准宽高));
    • align-self(单独设置交叉轴对齐);
    • order(项目顺序,默认 0,值越小越靠前)。

10. rem、em、vw、vh、px 的区别及使用场景?

单位基准场景
px固定像素精确控制(如边框、小图标)
em父元素字体大小局部响应式(如按钮内边距)
rem根元素(html)字体大小全局响应式(如页面布局)
vw视口宽度的 1%全屏适配(如宽度占比)
vh视口高度的 1%全屏适配(如高度占比)

11. JavaScript 的基本数据类型有哪些?

  • 基本类型(值类型):Number(数字)、String(字符串)、Boolean(布尔)、Undefined(未定义)、Null(空)、Symbol(唯一标识)、BigInt(大整数)。
  • 引用类型Object(对象)、Array(数组)、Function(函数)等。

12. == 和 === 的区别?

  • ==松散相等,会自动类型转换后比较值(如1 == "1"true)。
  • ===严格相等,不做类型转换,同时比较值和类型(如1 === "1"false)。

13. null 和 undefined 的区别?

类型含义场景
undefined变量已声明但未赋值未传参的函数形参、访问不存在的对象属性
null主动表示 “空值”主动清空对象引用(如let obj = null
  • 共同点:==比较为truenull == undefined),===false

14. 浅拷贝与深拷贝的区别?

  • 浅拷贝:只复制对象的 “第一层” 属性,若属性是引用类型(如对象 / 数组),则复制的是引用地址(修改新对象会影响原对象)。
  • 深拷贝:复制对象的所有层级属性,新对象与原对象完全独立(修改新对象不影响原对象)。

15. 常用的深拷贝方式有哪些?

  1. JSON 序列化(简单场景):JSON.parse(JSON.stringify(obj))(缺点:不支持函数、Symbol、循环引用);
  2. 递归实现(自定义):遍历对象,逐层复制引用类型;
  3. 第三方库lodash.cloneDeep(obj)
  4. 结构化克隆structuredClone(obj)(ES2022,支持循环引用、Symbol 等)。

16. this 的指向规则是什么?

  1. 默认绑定:独立函数调用时,this指向全局对象(浏览器:window;Node:global;严格模式下为undefined);
  2. 隐式绑定:函数作为对象方法调用时,this指向调用该方法的对象;
  3. 显式绑定:通过call/apply/bind指定this指向;
  4. new 绑定:构造函数中,this指向新创建的实例对象;
  5. 箭头函数:无自身this,继承外层作用域的this

17. call、apply、bind 的区别?

  • 相同点:都能显式绑定this
  • 不同点:
    • call:参数是 “逗号分隔”(如fn.call(obj, a, b)),立即执行
    • apply:参数是 “数组 / 类数组”(如fn.apply(obj, [a, b])),立即执行
    • bind:返回一个绑定了 this 的新函数(需手动调用),参数可分多次传入。

18. 闭包是什么?有什么作用?

  • 闭包:函数能访问其定义时的外层作用域变量(即使外层函数已执行完毕),形成 “函数 + 外层作用域” 的组合。
  • 作用
    • 延长变量生命周期(实现数据缓存);
    • 实现私有变量(避免全局污染)。
  • 注意:滥用会导致内存泄漏,需及时释放引用。

19. 原型和原型链是什么?

  • 原型:每个函数都有prototype(原型对象),每个对象都有__proto__(指向其构造函数的prototype)。
  • 原型链:对象访问属性时,若自身没有,则通过__proto__向上查找其原型对象的属性,直到Object.prototype.__proto__(为null),形成的链式结构即为原型链。

20. new 操作符做了什么?

  1. 创建一个空对象
  2. 将空对象的__proto__指向构造函数的prototype
  3. 执行构造函数,将this绑定到新对象;
  4. 若构造函数返回 “引用类型”,则返回该引用;否则返回新对象。

21. JavaScript 的作用域链是如何形成的?

  • 作用域链:函数执行时,会创建 “执行上下文”,其中包含当前作用域的变量。若当前作用域找不到变量,则向上查找外层作用域的变量,直到全局作用域,形成的链式结构即为作用域链。
  • 形成时机:函数定义时(而非执行时)确定外层作用域。

22. Event Loop 机制是什么?

  • Event Loop:JavaScript 的异步执行机制(因 JS 是单线程),分为浏览器 Event LoopNode.js Event Loop
  • 浏览器 Event Loop流程:
    1. 执行同步代码(宏任务);
    2. 执行微任务队列中所有任务;
    3. 渲染页面(若有);
    4. 从宏任务队列取一个任务执行,重复步骤 2-4。
  • 宏任务setTimeoutsetIntervalDOM事件AJAX等;
  • 微任务Promise.then/catch/finallyMutationObserverprocess.nextTick(Node)等。

23. 宏任务和微任务有哪些?

  • 宏任务:浏览器:setTimeoutsetIntervalsetImmediate(IE)、DOM事件AJAXrequestAnimationFrame;Node:setTimeoutsetIntervalsetImmediateI/O操作
  • 微任务:浏览器:Promise.then/catch/finallyMutationObserver;Node:Promise.then/catch/finallyprocess.nextTickqueueMicrotask

24. Promise 的三种状态是什么?

  • pending(进行中):初始状态,未完成也未失败;
  • fulfilled(已完成):操作成功,状态不可逆,触发then回调;
  • rejected(已失败):操作失败,状态不可逆,触发catch回调。

25. async/await 是如何实现的?

async/awaitPromise+Generator 函数的语法糖:

  1. async函数返回一个Promise
  2. await会暂停async函数执行,等待右侧Promise状态变更;
  3. 底层通过 Generator 函数的 “暂停 / 恢复” 机制 + 自动执行器(如co库)实现。

26. 防抖与节流的区别?

  • 防抖(debounce):事件触发后,延迟一段时间执行函数;若期间再次触发,则重新计时(如搜索框输入后延迟查询)。
  • 节流(throttle):事件触发后,在一段时间内只执行一次函数;若期间再次触发,不执行(如滚动监听、按钮防重复点击)。

27. 什么是函数柯里化?

  • 柯里化:将接收多个参数的函数,转换为 “接收单个参数,返回接收剩余参数的新函数” 的过程。
  • 示例:
    // 普通函数
    function add(a, b, c) { return a + b + c; }
    // 柯里化后
    function curryAdd(a) {
      return function(b) {
        return function(c) {
          return a + b + c;
        }
      }
    }
    curryAdd(1)(2)(3); // 6
    
  • 作用:参数复用、延迟执行。

28. 什么是高阶函数?

  • 高阶函数:满足以下任一条件的函数:
    1. 接收函数作为参数
    2. 返回函数作为结果
  • 示例:Array.mapsetTimeoutPromise.then

29. 什么是函数式编程?

  • 函数式编程:一种编程范式,核心是 “将运算视为函数运算”,特点:
    • 函数是 “一等公民”(可作为参数 / 返回值);
    • 纯函数(无副作用、相同输入必返回相同输出);
    • 避免可变数据,优先使用不可变数据;
    • 常用特性:柯里化、高阶函数、递归等。

30. let、const、var 的区别?

维度varletconst
作用域函数 / 全局作用域块级作用域块级作用域
变量提升存在(声明提升,值为 undefined)不存在(暂存死区)不存在(暂存死区)
重复声明允许不允许不允许
可修改否(常量,引用类型内部可改)

31. 箭头函数与普通函数的区别?

  • this指向:箭头函数无自身this,继承外层作用域的this;普通函数this指向调用者;
  • 构造函数:箭头函数不能作为构造函数(无prototype,不能用new);
  • arguments:箭头函数无arguments对象(需用剩余参数...args);
  • 简写:箭头函数支持 “单表达式自动返回”(如x => x*2)。

32. 模板字符串的作用和优点

  • 作用:用反引号()包裹的字符串,支持**多行书写**和**变量插值**(${变量 / 表达式}`)。
  • 优点
    • 多行字符串无需拼接(更简洁);
    • 变量 / 表达式嵌入更直观(避免+拼接)。
  • 示例:
    const name = "Alice";
    const str = `Hello ${name},
    today is ${new Date().getDay()}.`;
    

33. 解构赋值的使用方式

  • 数组解构:按顺序匹配,支持默认值、剩余参数。
    const [a, b, c = 3, ...rest] = [1, 2]; // a=1, b=2, c=3, rest=[]
    
  • 对象解构:按属性名匹配,支持重命名、默认值。
    const { name: userName, age = 18 } = { name: "Bob" }; // userName="Bob", age=18
    
  • 其他场景:函数参数解构、嵌套解构等。

34. 展开运算符(...)的应用场景

  1. 数组 / 对象拷贝(浅拷贝):
    const arr = [...[1,2,3]];
    const obj = { ...{a:1} };
    
  2. 数组 / 对象合并
    const arr1 = [1,2, ...[3,4]]; // [1,2,3,4]
    const obj1 = {a:1, ...{b:2}}; // {a:1, b:2}
    
  3. 函数参数展开
    const fn = (a,b) => a+b;
    fn(...[1,2]); // 3
    

35. Map 与 Object 的区别?

维度ObjectMap
键类型只能是字符串 / 符号任意类型(对象 / 函数等)
键顺序无序(数字键会排序)插入顺序
长度获取需手动遍历计算size属性直接获取
遍历方式for...in/Object.keysfor...of/forEach
性能频繁增删时性能一般频繁增删时性能更优

36. Set 的使用场景是什么?

Set是 “无重复元素的集合”,场景:

  1. 数组去重[...new Set(arr)]);
  2. 存储不重复的标识(如 ID);
  3. 快速判断元素是否存在(set.has(val))。

37. Symbol 的作用是什么?

  • 作用:创建 “唯一的标识”,避免属性名冲突。
  • 场景:
    1. 定义对象的私有属性(无法被for...in遍历);
    2. 定义常量(确保唯一性);
    3. 作为对象属性名(避免重名)。

38. Proxy 与 Reflect 的作用

  • Proxy:用于拦截对象的操作(如属性读取、赋值、删除等),可实现数据代理、数据劫持(Vue3 响应式的核心)。示例:
    const proxy = new Proxy({a:1}, {
      get(target, key) { return target[key] * 2; }
    });
    proxy.a; // 2
    
  • Reflect:将对象的操作(如deleteget)封装为函数方法,与 Proxy 配合使用,使拦截操作更规范。示例:Reflect.get(target, key)等价于target[key]

39. ES Module 的导入和导出方式有哪些?

  • 导出(export)
    1. 命名导出:export const a = 1; 或 export { a, b };
    2. 默认导出:export default function() {}(一个模块只能有一个默认导出)。
  • 导入(import)
    1. 命名导入:import { a, b as B } from './mod.js';
    2. 默认导入:import mod from './mod.js';
    3. 全部导入:import * as mod from './mod.js';

40. 浏览器的渲染流程是怎样的?

  1. 解析 HTML:生成 DOM 树;
  2. 解析 CSS:生成 CSSOM 树;
  3. 构建渲染树:合并 DOM 树和 CSSOM 树,只包含可见元素;
  4. 布局(Layout):计算元素的位置和大小(回流);
  5. 绘制(Paint):将元素绘制到图层(重绘);
  6. 合成(Composite):将图层合并,显示到屏幕。

41. 重绘与回流的区别?

  • 回流(重排):元素的布局属性(如宽高、位置)变化,导致浏览器重新计算布局并生成渲染树(代价高)。
  • 重绘:元素的样式属性(如颜色、背景)变化,但布局未变,浏览器仅重新绘制元素(代价较低)。
  • 关系:回流必然触发重绘,重绘不一定触发回流。

42. 输入 URL 到页面显示经历哪些过程?

  1. URL 解析:判断是否为合法 URL;
  2. DNS 解析:将域名解析为 IP 地址;
  3. 建立 TCP 连接:三次握手;
  4. 发送 HTTP 请求:携带请求头、请求体;
  5. 服务器处理请求:返回 HTTP 响应(状态码、响应头、响应体);
  6. 关闭 TCP 连接:四次挥手(或复用连接);
  7. 浏览器渲染页面:解析 HTML/CSS/JS,生成页面(见第 40 题)。

43. 跨域的产生原因是什么?

跨域是浏览器的同源策略限制:当页面的 “协议、域名、端口” 与请求的资源不一致时,即产生跨域。

  • 同源:协议、域名、端口完全相同(如http://a.com:80https://a.com:80不同源)。

44. 常见的跨域解决方案有哪些?

  1. CORS(跨域资源共享):服务器端设置响应头(如Access-Control-Allow-Origin: *);
  2. JSONP:利用<script>标签的跨域特性,仅支持 GET 请求;
  3. 代理服务器:本地开发用 webpack-dev-server 代理,生产用 Nginx 反向代理;
  4. postMessage:页面间跨域通信(如 iframe);
  5. WebSocket:不受同源策略限制。

45. cookie、session、localStorage、sessionStorage 的区别?

维度cookiesessionlocalStoragesessionStorage
存储位置客户端服务器端(依赖 cookie)客户端客户端
存储大小约 4KB无限制(服务器内存)约 5MB约 5MB
生命周期可设置过期时间会话结束(或超时)永久(除非手动删除)标签页关闭后删除
通信随请求发送到服务器服务器端维护仅客户端,不发请求仅客户端,不发请求

46. 浏览器缓存机制有哪些?

分为强缓存协商缓存,优先级:强缓存 > 协商缓存。

47. 强缓存与协商缓存的区别?

维度强缓存协商缓存
判断方式浏览器直接判断本地缓存需向服务器发送请求判断
响应头Cache-Control(如max-age=3600)、ExpiresLast-Modified/If-Modified-SinceETag/If-None-Match
状态码200(from memory/disk cache)304(Not Modified)
性能无请求,性能高有请求,性能一般

48. Service Worker 的作用是什么?

  • Service Worker:运行在浏览器后台的 “脚本”,独立于页面,可实现:
    1. 离线缓存(PWA 核心,缓存资源后离线可访问);
    2. 消息推送;
    3. 后台同步;
    4. 拦截请求(类似代理)。

49. HTTP 和 HTTPS 的区别?

维度HTTPHTTPS
协议基础基于 TCP基于 TCP+SSL/TLS 加密
端口80443
安全性明文传输,不安全加密传输,安全
证书无需证书需要 CA 证书(需购买 / 申请)
性能速度快因加密解密,速度稍慢

50. HTTP1.1、HTTP2、HTTP3 的区别?

维度HTTP1.1HTTP2HTTP3
传输方式文本传输二进制帧传输基于 QUIC(UDP)传输
并发请求同域名最多 6-8 个连接多路复用(单连接多请求)更高效的多路复用
头部压缩无(重复头部冗余)HPACK 压缩QPACK 压缩
其他特性长连接(Keep-Alive)服务器推送、优先级更低延迟(基于 UDP)

51. 常见的 HTTP 状态码有哪些?

  • 1xx(信息):100(继续);
  • 2xx(成功):200(OK)、201(创建成功)、204(无内容);
  • 3xx(重定向):301(永久重定向)、302(临时重定向)、304(未修改);
  • 4xx(客户端错误):400(请求错误)、401(未授权)、403(禁止访问)、404(资源不存在);
  • 5xx(服务器错误):500(服务器内部错误)、502(网关错误)、503(服务不可用)。

52. TCP 三次握手的过程是什么?

三次握手是为了建立可靠的 TCP 连接

  1. 客户端→服务器:发送 SYN 包(同步序列编号),请求建立连接,客户端进入 SYN_SENT 状态;
  2. 服务器→客户端:回复 SYN+ACK 包(同步 + 确认),服务器进入 SYN_RCVD 状态;
  3. 客户端→服务器:回复 ACK 包(确认),双方进入 ESTABLISHED 状态,连接建立。

53. XSS 攻击是什么?如何防御?

  • XSS(跨站脚本攻击):攻击者向页面注入恶意脚本,当用户访问时,脚本执行(如窃取 Cookie)。
  • 防御方式
    1. 输入过滤(转义特殊字符,如<&lt;);
    2. 输出编码(渲染时对用户输入进行编码);
    3. 设置 Cookie 的HttpOnly属性(禁止 JS 读取 Cookie)。

54. CSRF 攻击是什么?如何防御?

  • CSRF(跨站请求伪造):攻击者诱导用户在已登录的情况下,向目标网站发送恶意请求(如转账)。
  • 防御方式
    1. 验证请求来源(检查Referer/Origin头);
    2. 使用 CSRF Token(请求携带随机 Token,服务器验证);
    3. 二次验证(如验证码、密码确认)。

55. 中间人攻击是什么?

  • 中间人攻击:攻击者在 “客户端与服务器” 的通信链路中,伪装成 “中间节点”,拦截、篡改双方的通信内容(如伪造证书窃取 HTTPS 数据)。
  • 防御:使用 HTTPS(验证证书合法性)、数字签名等。

56. Token 和 Session 的区别?

维度TokenSession
存储位置客户端(Cookie/Storage)服务器端(内存 / 数据库)
扩展性支持分布式(无状态)需共享 Session(如 Redis)
安全性签名防篡改,可过期依赖 Cookie,易受 CSRF 攻击
适用场景前后端分离、移动端传统 Web 应用

57. JWT 的结构组成是什么?

JWT(JSON Web Token)由三部分组成,用.分隔:

  1. Header(头部):Base64 编码,包含算法(如 HS256)和类型;
  2. Payload(载荷):Base64 编码,包含用户信息、过期时间等(不要存敏感信息,可被解码);
  3. Signature(签名):用 Header 的算法,对Header.Payload+ 密钥签名,用于验证 Token 合法性。

58. webpack 的核心概念有哪些?

  • 入口(entry):项目的入口文件(如entry: './src/index.js');
  • 出口(output):打包后的输出路径和文件名(如output: { path: './dist', filename: 'bundle.js' });
  • loader:处理非 JS 文件(如css-loader处理 CSS,babel-loader转译 ES6);
  • plugin:扩展 webpack 功能(如HtmlWebpackPlugin生成 HTML,MiniCssExtractPlugin提取 CSS);
  • 模式(mode)development(开发,不压缩)/production(生产,压缩)。

59. loader 和 plugin 的区别?

  • loader:用于转换文件内容(处理非 JS 模块),运行在打包过程的 “模块解析阶段”;
  • plugin:用于扩展 webpack 功能(如优化、生成文件),运行在打包过程的 “整个生命周期”,可监听 webpack 事件。

60. Vite 和 webpack 的区别?

维度webpackVite
打包方式基于 “打包”(先打包再启动)基于 “原生 ES 模块”(按需编译)
启动速度慢(依赖越多越慢)快(按需加载)
热更新慢(需重新打包)快(仅更新变化的模块)
适用场景大型复杂项目中小型项目、Vue/React 项目

61. Tree Shaking 是什么?

  • Tree Shaking:webpack 的优化功能,用于删除代码中未使用的部分(“死代码”),只打包被引用的代码。
  • 条件:代码需是 ES Module(静态导入 / 导出),且在production模式下自动启用。

62. Code Splitting 的作用是什么?

  • Code Splitting(代码分割):将打包后的代码拆分为多个小文件,作用:
    1. 减少首屏加载时间(只加载必要的代码);
    2. 实现按需加载(如路由懒加载);
    3. 利用浏览器缓存(公共代码单独打包)。

63. 前端模块化方案有哪些?

  • CommonJS:Node.js 的模块化方案,同步加载(如require/module.exports);
  • ES Module:ES6 的模块化方案,异步加载(如import/export);
  • AMD:浏览器端异步加载(如require.js);
  • CMD:浏览器端异步加载(如sea.js,按需加载)。

64. CommonJS 与 ES Module 的区别?

维度CommonJSES Module
加载方式同步(Node)/ 动态异步 / 静态
导出方式值拷贝(修改不影响原模块)引用(修改影响原模块)
执行时机运行时加载编译时加载
适用环境Node.js浏览器 + Node.js(需配置)

65. npm、yarn、pnpm 的区别?

维度npmyarnpnpm
速度慢(早期)快(缓存)更快(硬链接 + 符号链接)
安全性中等(依赖扁平但可能重复)高(锁文件更严格)高(无重复依赖)
依赖结构扁平结构(可能重复)扁平结构非扁平结构(节省空间)

66. Vue2 与 Vue3 的核心区别?

  • 响应式原理:Vue2 用Object.defineProperty(无法监听新增属性);Vue3 用Proxy(支持新增属性、数组下标);
  • API 风格:Vue2 用 Options API(选项式);Vue3 支持 Composition API(组合式)+Options API;
  • 性能:Vue3 编译优化(如静态提升)、体积更小;
  • 其他:Vue3 支持多根节点、Teleport、Composition API 等新特性。

67. Vue 中组件通信方式有哪些?

  1. 父子通信:父→子(props),子→父($emit/v-on);
  2. 祖孙通信provide/inject
  3. 兄弟通信EventBus(Vue2)/mitt(Vue3);
  4. 全局状态管理:Vuex/Pinia;
  5. 路由参数:通过$route.query/$route.params传递。

68. v-if 和 v-show 的区别?

  • v-if条件渲染,条件不满足时,元素会被 “从 DOM 中移除”(切换开销大);
  • v-show条件显示,条件不满足时,元素会被 “设置为display: none”(切换开销小);
  • 场景:频繁切换用v-show,条件少变用v-if

69. ref 和 reactive 的区别?

  • ref:用于基本类型 / 引用类型,访问时需用.value(模板中自动解包);
  • reactive:仅用于引用类型,返回响应式代理对象,访问时无需.value
  • 场景:基本类型用ref,对象 / 数组用reactive

70. watch 与 computed 的区别?

维度watchcomputed
作用监听数据变化,执行异步 / 复杂逻辑依赖数据,计算并缓存结果
触发时机数据变化时触发依赖变化且被使用时触发
返回值无(回调函数)有(返回计算结果)
缓存有(依赖不变则复用结果)

71. nextTick 的作用是什么?

nextTick用于等待 DOM 更新完成后执行回调(因为 Vue 的 DOM 更新是异步的)。

  • 场景:修改数据后,需立即操作更新后的 DOM(如获取元素高度)。
  • 示例:
    this.msg = "new";
    this.$nextTick(() => {
      // 此时DOM已更新
      console.log(this.$el.textContent); // "new"
    });
    

72. Vue 的生命周期有哪些?

  • Vue2 生命周期
    • 创建阶段:beforeCreate(实例创建前)→created(实例创建后,无 DOM);
    • 挂载阶段:beforeMount(挂载前)→mounted(挂载后,可操作 DOM);
    • 更新阶段:beforeUpdate(更新前)→updated(更新后);
    • 销毁阶段:beforeDestroy(销毁前)→destroyed(销毁后)。
  • Vue3 生命周期:组合式 API 中用onBeforeMount/onMounted等钩子函数,与 Vue2 对应。

73. keep-alive 的作用是什么?

keep-alive是 Vue 的内置组件,用于缓存组件实例,避免组件频繁创建 / 销毁,提升性能。

  • 场景:路由切换时缓存页面(如列表页→详情页,返回列表页不重新请求数据)。
  • 常用属性:include(缓存哪些组件)、exclude(不缓存哪些组件)。

74. diff 算法的基本原理是什么?

Vue 的 diff 算法是同级比较,核心是 “最小化 DOM 操作”:

  1. 同级比较:只比较同一层级的节点,不跨层级比较;
  2. key 的作用:通过key标识节点唯一性,快速判断节点是 “复用” 还是 “新增 / 删除”;
  3. 比较规则
    • 若节点类型不同,直接替换;
    • 若节点类型相同,比较key和属性,复用节点并更新属性;
    • 列表比较时,通过key减少移动操作。

75. 虚拟 DOM 是什么?

  • 虚拟 DOM:用JS 对象描述真实 DOM 的结构(如{ tag: 'div', props: { id: 'app' }, children: [] })。
  • 作用:
    1. 减少 DOM 操作(通过 diff 算法计算最小更新量);
    2. 跨平台(同一虚拟 DOM 可渲染到浏览器、小程序等)。

76. slot 插槽的类型有哪些?

  • 默认插槽:无名称的插槽,用<slot>表示;
  • 具名插槽:有名称的插槽,用name属性区分(如<slot name="header"></slot>);
  • 作用域插槽:子组件向父组件传递数据的插槽(如<slot :data="list"></slot>,父组件用v-slot="scope"接收)。

77. Teleport 的作用是什么?

Teleport(瞬移)是 Vue3 的特性,用于将组件的 DOM 节点 “移动” 到指定的 DOM 位置(如<body>),同时保持组件的逻辑归属不变。

  • 场景:弹窗、对话框(避免父组件样式影响)。
  • 示例:
    <Teleport to="body">
      <div class="modal">弹窗内容</div>
    </Teleport>
    

78. provide 和 inject 的使用场景是什么?

provide/inject是 Vue 的祖孙组件通信方式

  • 祖先组件用provide提供数据;
  • 后代组件用inject注入数据;
  • 场景:深层嵌套的组件通信(避免 props 逐层传递)。

79. Composition API 与 Options API 的区别?

维度Options APIComposition API
代码组织按选项(data/methods)分类按功能逻辑分类
复用性依赖 mixins(易冲突)用组合函数(更灵活)
类型支持较差(需装饰器)友好(TS 支持更好)
可读性大项目中逻辑分散逻辑聚合,更易维护

80. React 和 Vue 的核心区别?

维度ReactVue
响应式原理状态驱动(setState 触发重新渲染)数据劫持(Vue2:Object.defineProperty;Vue3:Proxy)
模板语法JSX(HTML 嵌入 JS)模板语法(HTML+Vue 指令)
生态更丰富(适合大型项目)更轻量(适合中小型项目)
灵活性高(自由度大)中等(约定大于配置)

81. 什么是 JSX?

JSX 是 React 的语法扩展,允许在 JS 中写 HTML 结构(如<div>Hello</div>),最终会被 Babel 转译为React.createElement调用。

  • 特点:支持表达式嵌入({变量})、条件渲染、列表渲染等。

82. 什么是 Hooks?

Hooks 是 React 16.8 的特性,用于在函数组件中使用状态和生命周期等特性(替代类组件)。

  • 常用 Hooks:useState(状态)、useEffect(副作用)、useContext(上下文)、useRef(引用)等。

83. useEffect 与 useLayoutEffect 的区别?

  • useEffect:在DOM 渲染完成后执行(异步,不阻塞渲染);
  • useLayoutEffect:在DOM 渲染完成前执行(同步,阻塞渲染);
  • 场景:操作 DOM 样式且需立即生效时用useLayoutEffect,其他场景用useEffect

84. 懒加载的实现方式有哪些?

  • 路由懒加载:Vue 用() => import('./Page.vue'),React 用React.lazy(() => import('./Page.jsx'))
  • 图片懒加载
    1. 监听滚动事件,判断图片是否进入视口;
    2. IntersectionObserver API(更高效);
    3. 原生loading="lazy"属性。

85. 预加载的方式有哪些?

  • link 预加载
    <link rel="preload" href="style.css" as="style"> <!-- 预加载资源 -->
    <link rel="prefetch" href="page2.js"> <!-- 预取下一页面资源 -->
    
  • JS 动态创建资源new Image().src = 'img.jpg'
  • webpack 预加载:用/* webpackPrefetch: true */标记模块。

86. 图片优化的策略有哪些?

  1. 格式选择:WebP/AVIF(更小体积)、PNG(透明图)、JPG(照片);
  2. 压缩体积:用工具(如 TinyPNG)压缩;
  3. 懒加载(见第 84 题);
  4. CDN 加速:用 CDN 加载图片;
  5. 响应式图片srcset/sizes(不同设备加载不同尺寸)。

87. 如何减少白屏时间?

  1. 优化资源加载:压缩 JS/CSS、图片懒加载、路由懒加载;
  2. CDN 加速:静态资源用 CDN;
  3. 服务端渲染(SSR):Vue 用 Nuxt,React 用 Next;
  4. 预加载关键资源preload关键 CSS/JS;
  5. 骨架屏:先显示骨架屏,再渲染内容。

88. 长列表渲染如何优化?

  • 虚拟列表:只渲染 “当前视口内的元素”,复用 DOM(如vue-virtual-scrollerreact-window);
  • 分页加载:分批次请求数据,每次加载部分内容;
  • 懒渲染:只渲染可见区域的元素,滚动时加载其他元素。

89. 数组去重的方式有哪些?

  1. Set(最简单):[...new Set(arr)]
  2. filter+indexOfarr.filter((item, index) => arr.indexOf(item) === index)
  3. reduce+includes
    arr.reduce((prev, curr) => prev.includes(curr) ? prev : [...prev, curr], [])
    
  4. 对象键值对:利用对象属性唯一性去重。

90. 字符串反转如何实现?

  1. split+reverse+joinstr.split('').reverse().join('')
  2. for 循环
    let res = '';
    for (let i = str.length - 1; i >= 0; i--) res += str[i];
    
  3. 递归str === '' ? '' : reverse(str.slice(1)) + str[0]

91. 如何判断一个字符串是否为回文?

回文:正读和反读都相同(如 “abcba”)。

  • 方法:比较字符串与反转后的字符串是否相等:
    function isPalindrome(str) {
      const reversed = str.split('').reverse().join('');
      return str === reversed;
    }
    

92. 实现一个深拷贝函数

function deepClone(obj, map = new WeakMap()) {
  // 处理null/基本类型
  if (obj === null || typeof obj !== 'object') return obj;
  // 处理循环引用
  if (map.has(obj)) return map.get(obj);
  
  // 处理数组/对象
  const clone = Array.isArray(obj) ? [] : {};
  map.set(obj, clone);
  
  // 遍历属性
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], map);
    }
  }
  return clone;
}

93. 实现一个防抖函数

function debounce(fn, delay) {
  let timer = null;
  return function(...args) {
    // 清除之前的定时器
    if (timer) clearTimeout(timer);
    // 重新计时
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

94. 实现一个节流函数

function throttle(fn, delay) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    // 时间差大于delay则执行
    if (now - lastTime >= delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

95. 实现 Promise.all

Promise.all = function(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let count = 0;
    const len = promises.length;
    
    for (let i = 0; i < len; i++) {
      Promise.resolve(promises[i])
        .then(res => {
          results[i] = res;
          count++;
          // 所有Promise完成后resolve
          if (count === len) resolve(results);
        })
        .catch(err => reject(err)); // 任一失败则reject
    }
  });
};

96. 前缀和的原理和应用场景是什么?

  • 原理:前缀和数组preSum中,preSum[i]表示原数组前i个元素的和(preSum[0] = 0preSum[i] = preSum[i-1] + arr[i-1])。
  • 应用场景:快速计算 “数组某区间的和”(如求[l, r]的和:preSum[r+1] - preSum[l])。

97. 递归和迭代的区别?

  • 递归:函数调用自身,将大问题分解为小问题(代码简洁,但可能栈溢出);
  • 迭代:用循环重复执行代码(无栈溢出风险,但代码较繁琐);
  • 示例:计算斐波那契数列:
    • 递归:function fib(n) { return n <= 1 ? n : fib(n-1) + fib(n-2); }
    • 迭代:function fib(n) { let a=0,b=1; for(let i=2;i<=n;i++) { [a,b] = [b,a+b]; } return b; }

98. 时间复杂度与空间复杂度的区别?

  • 时间复杂度:描述算法执行时间随输入规模增长的趋势(如 O (1)、O (n)、O (logn));
  • 空间复杂度:描述算法所需额外空间随输入规模增长的趋势(如 O (1)、O (n));
  • 目标:设计 “时间复杂度低 + 空间复杂度低” 的算法。

99. 栈和队列的区别?

  • 栈(Stack):“后进先出”(LIFO),仅允许在一端(栈顶)操作;
  • 队列(Queue):“先进先出”(FIFO),允许在一端(队尾)入队,另一端(队头)出队;
  • 应用:栈(函数调用栈、括号匹配);队列(任务队列、广度优先搜索)。

100. 常见的排序算法有哪些?

算法时间复杂度(平均)空间复杂度稳定性
冒泡排序O(n²)O(1)稳定
选择排序O(n²)O(1)不稳定
插入排序O(n²)O(1)稳定
快速排序O(nlogn)O(logn)不稳定
归并排序O(nlogn)O(n)稳定
堆排序O(nlogn)O(1)不稳定
<think>好的,用户问的是在图片上点一个点如何确定像素坐标。我需要先理解这个问题。用户可能是在开发图像处理应用或者网页,需要获取用户点击位置的坐标。首先,得考虑不同的平台,比如是网页前端、桌面应用还是移动端。不同的平台有不同的方法。如果是网页的话,通常用HTML5的Canvas来处理。用户点击图片时,图片可能被绘制在Canvas上,这时候可以通过事件监听获取鼠标点击的位置,再转换成Canvas上的坐标。需要注意图片在Canvas中的位置和缩放情况,否则坐标可能会有偏差。比如,如果图片被缩放或者有边距,就要调整坐标计算。对于桌面应用,比如使用Python的Tkinter或者PyQt,可能需要绑定鼠标点击事件,获取事件对象的x和y属性。同样要考虑窗口布局和图片的实际显示位置,确保坐标正确。 移动端的话,比如Android或iOS,触屏事件的处理类似,获取触摸点的坐标,并转换为相对于图片的坐标。这里可能需要处理视图的布局和可能的缩放。另外,用户可能没有说明具体平台,所以需要给出通用的思路,或者选择常见的情况,比如网页前端作为例子。代码示例用HTML/JavaScript比较直观,因为前端处理用户交互比较常见。 然后,我需要给出步骤:1.将图片放入Canvas,2.监听点击事件,3. 计算相对于Canvas的坐标,4.调整缩放或偏移后的实际像素坐标。代码示例要展示如何获取正确的坐标,包括处理图片的缩放情况。 接下来,解释代码的时候,要说明各个部分的作用,比如getBoundingClientRect用来获取Canvas的位置,减去偏移量得到正确的坐标。还要提到如果图片有缩放,需要将坐标除以缩放比例得到实际像素位置。 可能的相关问题包括其他平台的实现方法,如何处理不同缩放情况,或者如何将坐标保存或处理。用户可能还想知道如何在不同编程语言或框架中实现类似功能,比如Python的GUI库或者移动开发。这时候需要列出相关问题,覆盖不同方面,帮助用户深入理解。</think>平台和工具中获取图片点击位置的像素坐标方法不同,以下是网页前端和Python桌面应用的实现方案: 一、网页前端实现方案(HTML+JavaScript): ```html <!DOCTYPE html> <html> <body> <!-- 显示图片的canvas元素 --> <canvas id="myCanvas" width="800" height="600"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // 加载图片 const img = new Image(); img.src = 'your_image.jpg'; img.onload = () => { // 将图片绘制到canvas上(可添加缩放逻辑) ctx.drawImage(img, 0, 0, canvas.width, canvas.height); }; // 点击事件监听 canvas.addEventListener('click', (event) => { // 获取canvas边界信息 const rect = canvas.getBoundingClientRect(); // 计算实际像素坐标 const scaleX = canvas.width / rect.width; // 水平缩放比例 const scaleY = canvas.height / rect.height; // 垂直缩放比例 const x = (event.clientX - rect.left) * scaleX; const y = (event.clientY - rect.top) * scaleY; console.log(`像素坐标:(${Math.round(x)}, ${Math.round(y)})`); }); </script> </body> </html> ``` 二、Python桌面应用实现方案(使用tkinter): ```python import tkinter as tk def get_pixel(event): # 直接获取事件坐标(原点在图片左上角) x, y = event.x, event.y print(f"像素坐标:({x}, {y})") root = tk.Tk() img = tk.PhotoImage(file="your_image.png") label = tk.Label(root, image=img) label.pack() label.bind("<Button-1>", get_pixel) # 绑定左键点击事件 root.mainloop() ``` 实现原理说明: 1. 网页方案通过Canvas元素承载图片,通过计算鼠标事件位置与Canvas元素的相对位置关系,考虑可能的缩放比例后得出实际像素坐标 2. 桌面方案直接使用GUI框架提供的事件坐标参数,tkinter的坐标系统直接对应图片像素坐标 3. 都需要注意坐标系原点位置(通常左上角为原点(0,0)) 4. 需要处理图片缩放时的坐标换算问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值