知识记录

面试题

1.Js的数据类型有哪些?他们的区别是什么?

基本数据类型:Number String Boolean Null Undefined Symbol(ES6) (直接存储在内存中的,占用固定的内存空间;赋值是通过将值直接复制给变量来完成的;作为参数传递时,传递的是值的副本)

引用数据类型 :狭义的对象(object)、 数组(array)、函数(function) (引用数据类型的变量实际上存储的是对象在内存中的引用,通过引用访问和操作对象的属性和方法;赋值是将对象的引用赋给变量;作为参数传递时,传递的是引用的副本)

2.判断数据类型有几种方法?

typeof运算符:

无法分辨Array、null和Object

instanceof 运算符:

原理是检查右边构造函数的原型对象(prototype),是否在左边对象的原型链上;

等同于:右边构造函数.prototype.isPrototypeOf(左边对象)

因此同一个实例对象,可能会对多个构造函数都返回true。

var d = new Date();
d instanceof Date // true
d instanceof Object // true

Object.prototype.toString.call方法

不能细分为谁谁的实例

3.作用域和作用域链

作用域:规定变量和函数的可使用范围称作作用域

作用域链:每个函数都有一个作用域,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链

4.原型和原型链

原型:原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型 ​ 原型链:每个对象都拥有一个原型对象,同时原型对象也可能拥有原型,这样一层一层,最终指向 null ,这种关系被称为原型链。

5.什么是闭包?

闭包是什么:JS中内层函数可以访问外层函数的变量,使内部私有变量不受外界干扰,起到保护和保存的作用,我们把这个特性称作闭包。 好处: 隔离作用域,保护私有变量; 让我们可以使用回调,操作其他函数内部; 变量长期驻扎在内存中,不会被内存回收机制回收,即延长变量的生命周期; 坏处:内层函数引用外层函数变量,内层函数占用内存,如果不释放内存,过多时,易引起内存泄露。 引用场景: for循环中的保留i的操作 、防抖(多次触发只执行最后一次)和节流 (规定时间内只触发第一次)

6.内存泄露、垃圾回收机制

内存泄露:指我们无法在通过js访问某个对象,而垃圾回收机制却认为该对象还在被引用,因此垃圾回收机制不会释放该对象,导致该块内存永远无法释放,积少成多,系统会越来越卡以至于崩溃

垃圾回收机制:就是垃圾收集器按照固定的时间间隔,周期性地寻找那些不再使用的变量,然后将其清除或释放内存。(标记清除/引用计数)

7.浅拷贝和深拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。

深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改变原对象。

8.如何改变this指向(call、apply与bind区别)

call、bind、apply 都是 JavaScript 中用于改变函数执行上下文(即 this 指向)的方法。

传参: call、bind可以传递很多个参数,apply只有两个参数,第一个参数要绑定的对象、第二个参数为数组;

返回: call和apply方法是直接调用函数并改变函数上下文,而bind方法则是返回一个新函数,稍后调用时绑定指定的上下文。

9.箭头函数和普通函数的区别

箭头函数是普通函数的简写,但是它不具备普通函数的很多特性;

箭头函数的this指向它定义时所在的对象,而不是调用时所在的对象;

没有arguments对象,不能使用arguments;

不会进行函数提升;

不能作为构造函数。

10.什么是web缓存?

web缓存主要指的是两部分:浏览器缓存和http缓存。

浏览器缓存包括:

localStorage:永久保存,以键值对保存,存储空间5M。  sessionStorage:关闭页签/浏览器时清空,存储空间5M。  cookie:随着请求发送,通过设置过期时间删除(大概4kb)。  localStorage/sessionStorage是window的属性,cookie是document的属性。

http缓存:当Web请求抵达缓存时, 如果本地有“已缓存的”副本,就可以从本地存储设备而不是原始服务器中提取这个文档。

优点:

减少不必要的网络传输,节约宽带(就是省钱)

更快的加载页面(就是加速)

减少服务器负载,避免服务器过载的情况出现。(就是减载)

缺点:占内存(有些缓存会被存到内存中)

http缓存又分为强制缓存和协商缓存。

11.从 URL 输入到页面展现到底发生什么?

首先进行 DNS 域名解析,找到真实 IP ,向服务器发起请求,服务器交给后台处理完成后返回数据,浏览器接收⽂件( HTMLJSCSS 、图象等)并对加载到的资源进⾏语法解析,从而构建DOM树等相应的内部数据结构并渲染页面。

12.setState是同步的还是异步的?

setState在React合成事件和生命周期方法中是异步的,在setTimeout和原生事件处理中是同步的。但是,从React 18开始,所有的setState调用都会自动进行批量处理(异步)。

13.前端性能优化

网络优化:压缩资源、代码拆分(比如拆分成多个小模块按需加载)、CDN加速、优化http请求(比如合并小图标为雪碧图、内联关键 CSS 和 JavaScript 代码等)

页面渲染优化:

懒加载;

防抖和节流;

避免重排与重绘:

直接操作 DOM 元素几何属性、改变布局等会触发重排;修改元素颜色、背景等外观属性引发重绘。减少这类操作,批量修改样式,使用 CSS 过渡动画替代即时 DOM 变动;

优化CSS加载顺序:将关键 CSS (用于首屏渲染的样式)放在文档头部加载,确保页面渲染样式尽早可用;非关键 CSS 放底部异步加载,不阻塞页面渲染。

内存管理优化:

及时清理变量:不再使用的变量、定时器、事件监听,要适时清除,防止内存泄漏;

合理使用闭包。

代码质量优化:

移除冗余代码;

优化算法逻辑;

Tree Shaking(它自动剔除未引入模块代码,打包出更精简的生产包)。

14.前端首屏加载优化

减少入口文件体积,例如使用路由懒加载;

静态资源本地缓存,例如采用http缓存和localStorage;

UI框架按需加载,例如Element UI按需引入要使用的组件;

组件重复打包,例如在webpackconfig文件中,修改CommonsChunkPlugin的配置minChunks: 3,表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件

图片资源压缩,例如使用雪碧图、使用线字体图标

使用SSR。

15.为什么使用vuex?

组件间数据共享:Vuex可以将数据共享给多个组件共同使用,避免了数据的重复获取和频繁更新,提高了代码的效率和复用性。

复杂状态的管理:当项目中的状态和数据交互变得复杂时,Vuex可以通过集中式存储和管理,将状态的变化和交互逻辑统一管理,提高了代码的可维护性和可读性。

异步操作的处理:Vuex可以将异步操作进行集中处理,使得异步操作的流程更加清晰和易于管理,也可以避免异步操作带来的错误和风险。

用户状态的管理:Vuex可以用于管理用户的登录状态、个人信息等敏感信息,使得应用更加安全和稳定。

代码的组织和模块化:Vuex可以将复杂的业务逻辑和状态管理进行模块化,使得代码更加清晰、易于理解和维护。

可预测性和调试:Vuex提供了一种可预测的状态管理模式,可以清晰地了解状态的变化和流向,方便进行调试和测试。

16.Webpack打包流程。

首先会从配置文件和 Shell 语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数;初始化完成后会调用Compiler的run来真正启动webpack编译构建过程,webpack的构建流程包括compilation(开始编译)、make(从入口点分析模块及其依赖的模块,创建这些模块对象 )、build(构建模块)、seal(封装构建结果)、emit阶段,执行完这些阶段就完成了构建过程。

image-20241206170815127

17.Webpack热更新

当代码文件修改并保存之后,webapck通过watch监听到文件发生变化,会对代码文件重新打包生成两个模块补丁文件manifest(js)和一个(或多个)updated chunk(js),将结果存储在内存文件系统中,通过websocket通信机制将重新打包的模块发送到浏览器端,浏览器动态的获取新的模块补丁替换旧的模块。

18.js事件循环机制

JS 主线程不断的循环往复的从任务队列中读取任务,执行任务,这种运行机制称为事件循环(event loop)

浏览器的事件循环(event loop)中分成宏任务和微任务。JS 中任务分成同步任务和异步任务。

  1. 宏任务(macro task)

JS 中主栈执行的大多数的任务,例如:定时器,事件绑定,ajax,回调函数,node中fs操作模块等就是宏任务

  1. 微任务(micro task)

promise, async/await, process.nextTick等就是微任务。

JS 中任务的执行顺序优先级是:主栈全局任务(宏任务) > 宏任务中的微任务 > 下一个宏任务。所以 promise(微任务) 的执行顺序优先级高于setTimeout定时器。

19.服务端渲染(SSR)

将组件在服务端直接渲染成 HTML 字符串,作为服务端响应返回给浏览器,最后在浏览器端将静态的 HTML“激活”(hydrate) 为能够交互的客户端应用。

优点:

更快的首屏加载:无需等到所有的 JavaScript 都下载并执行完成之后才显示。数据获取过程在首次访问时在服务端完成,相比于从客户端获取,可能有更快的数据库连接。

统一的心智模型:可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端框架之间来回切换。

更好的 SEO:搜索引擎爬虫可以直接看到完全渲染的页面。

20.Vue2和Vue3的区别

设计理念上:Vue2是基于Options API而Vue3是基于Composition API

模板编译上:Vue2是直接将模板全部编译成虚拟dom树,每次组件更新时,即使静态内容未发生变化,整个虚拟 DOM 树仍然会重新创建;而Vue3则采用了静态树提升和动态节点追踪机制,将这些静态内容提升到渲染函数的外部,只生成一次,标记动态节点,运行时仅更新这些真正需要变化的部分。

响应式系统上:Vue2是基于Object.defineProperty,通过递归劫持对象的每个属性来实现对数据访问和修改的拦截,但是无法监听新增或删除属性,因此添加了setdelete作为补充;Vue3是基于ES6的新特性Proxy的捕获器(trap)实现,捕获所有对对象的操作,劫持的是整个对象,而不是单个属性,这使得新增和删除属性、数组操作都能被监控,只有在访问嵌套对象时才会进行代理操作(懒代理)。

组件实现上:Vue2的组件是基于 Vue.extend 创建的,组件本质上是构造函数的实例;Vue3 的组件基于函数式实现,使用 setup 方法初始化逻辑,组件树的更新通过 Fragment 提升性能。

diff算法上:

Vue 2 使用的是基于递归的双指针,Vue 3 使用的是基于数组的动态规划。  Vue 2 会对整个组件树进行完整的遍历和比较; Vue 3的静态节点只会在首次渲染时被处理,后续更新时会跳过静态子树的比较,只对动态节点进行更新。  Vue 2 对于列表渲染(v-for)时的元素重新排序会比较低效,需要通过给每个元素设置唯一的 key 来提高性能;Vue 3在列表渲染时,通过跟踪元素的移动,可以更好地处理元素的重新排序。

生命周期上:Vue 2的beforeCreate和created在Vue 3被setup()替代,beforeDestroy变成了onBeforeUnmount(),destroyed变成了onUnmounted(),其他钩子则是变成了onXxxx的形式。

其他:

使用TS重写,提供了更好的TS支持

支持Tree-shaking

引入了Teleport组件

21.说说你对插槽的理解?

插槽本质上是对子组件的扩展,通过<slot>插槽向子组件内部指定位置传递内容,分为默认插槽、具名插槽和作用域插槽三种。

22.什么是重绘和重排

重排是指重新计算网页布局的过程,而重绘则是根据新的布局信息重新绘制网页的过程。它们的区别在于,重排会导致元素的尺寸、位置、内容等属性的变化,因此需要重新计算布局信息;而重绘则是在元素的位置和尺寸等属性不变的情况下,重新绘制元素的样式。

23.requestIdleCallback和requestAnimationFrame

当每秒绘制的帧数(FPS)达到 60 时,页面是流畅的,小于这个值时,用户会感觉到卡顿。

1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms。所以我们书写代码时力求不让一帧的工作量超过 16ms。

一帧内需要完成如下六个步骤的任务:处理用户的交互

  • JS 解析执行

  • 帧开始。窗口尺寸变更,页面滚去等的处理

  • requestAnimationFrame(rAF)

  • 布局

  • 绘制

上面六个步骤完成后没超过 16 ms,说明时间有富余,此时就会执行 requestIdleCallback 里注册的任务。

即,requestAnimationFrame每一帧必定会执行,requestIdleCallback是捡浏览器空闲来执行任务。

假如浏览器一直处于非常忙碌的状态,requestIdleCallback 注册的任务有可能永远不会执行。

因为它发生在一帧的最后,此时页面布局已经完成,所以不建议在 requestIdleCallback 里再操作 DOM,这样会导致页面再次重绘。

24.useMemo和useCallback区别和使用场景

useMemo和useCallback都是用来优化性能的Hooks,作用都是通过判断依赖项是否改变来决定是否更新值。

区别是:

useMemo 缓存的结果是回调函数中return回来的值,主要用于缓存计算结果的值,通过减少不必要的复杂计算来优化性能

useCallback缓存的结果是函数,主要用于缓存函数,一般用于给子组件传递回调函数时,减少子组件的渲染次数,从而优化性能。需要注意的是,useCallback应该和React.memo配套使用,缺了一个都可能导致性能不升反而下降。

拓展点:

因为函数式组件每次任何一个state发生变化,会触发整个组件更新,一些函数是没有必要更新的,此时就应该缓存起来,提高性能,减少对资源的浪费。

25.http和https的区别

HTTP 的连接很简单,是无状态的,信息是明文传输;HTTPS 是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全,但是也更耗费服务器资源,使用 HTTPS 协议需要到 CA申请证书。

HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。

HTTP 和HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。

26.http的特点

工作于客户端/服务端的架构之上;

服务程序规模小而且通信速度很快;

允许传输任意类型的数据对象;

无连接:通信双方都不长久的维持对方的任何信息;

无状态:数据包的发送、传输和接收都是相互独立的。

27.Promise

Promise是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大。

优点:解决了回调地狱的问题、更好地进行错误捕获、更适合处理一次性的结果

缺点:

当处于pending状态时无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

只能有一个最终值或一个最终错误,无法同时返回多个值

如果不设置回调函数,Promise内部抛出的错误,不会反应到外部

一旦新建它就会立即执行,无法中途取消

28.Vue和React的区别

React 是一个用于构建用户界面的 JavaScript 库,而 Vue 则是一个用于构建 Web 应用程序的 渐进式框架。

React采用的是单向数据流,需要手动setState;Vue是响应式数据驱动的设计思想,可以双向数据绑定,修改数据自动更新视图。

28.RESTful Api的优缺点

优点:

简单直观:RESTful 风格使用标准的 HTTP 方法(GET、POST、PUT、DELETE 等 )来对应资源的读取、创建、更新、删除操作。

可扩展性强

跨平台兼容性好

良好的缓存支持

客户端与服务器之间仅通过资源的表述来交互

缺点:

缺乏统一标准规范

版本管理复杂

安全问题:由于 RESTful 依赖 HTTP 协议,数据传输过程中如果没有额外加密(如 HTTPS),信息易被窃取篡改。而且 RESTful 接口难以直接实现复杂的权限控制与身份验证逻辑,往往要借助外部的鉴权、授权方案来补充。

不适用于实时性要求高的场景

 

 

拓展知识点

1.React Hooks

useState - 状态钩子

接收状态的初始值作为参数,返回一个数组,分别是状态值和更新该状态值的函数 。

const [text, setText] = useState('Hello, World');

useContext - 共享状态钩子

用于访问 React context 在组件树中传递的数据,而不必通过每个组件传递 props,接收一个Context对象,返回该给Context对象提供的状态。

// 父组件
// 使用 React Context API,在组件外部建立一个 Context。
const AppContext = React.createContext({});

// 父组件组件封装代码
// 通过AppContext.Provider将状态提供给子组件共享
<AppContext.Provider value={{
   username: 'superasome'
}}>
   <div className="App">
       <Navbar/>
       <Message/>
   </div>
</AppContext.Provide>

// 子组件中获取共享的状态 - 以Navbar组件为例
const Navbar = () => {
   const {username} = useContext(AppContext);
   return (
       <div className="navbar">
           <p>AwesomeSite</p>
           <p>{username}</p>
       </div>
  );
}

useReducer - action钩子

接受 Reducer 函数和状态的初始值作为参数,返回一个数组,分别是当前状态值和发送action的dispatch函数。

const [state, dispatch] = useReducer(reducer, initialState);

useEffect - 副作用钩子

用于执行副作用操作。第一个参数是一个回调函数;第二个参数是一个数组,用于给出Effect的依赖项。当第二个参数被省略时,每次组件渲染就会执行Effect。

useEffect(()  =>  {
 // Async Action
}, [dependencies])

useCallback

用于返回一个 memoized 版本的回调函数,防止不必要的渲染。第一个参数是回调函数,第二个参数是依赖数组。

const memoizedCallback = useCallback(
() => {
   // 回调函数体
},
[dependencies] // 依赖数组
);

useMemo

用于对计算结果进行记忆,避免在每次渲染时重复计算。第一个参数是回调函数,第二个参数是依赖数组。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useRef

useRef可以接受一个默认值,并返回一个含有current属性的可变对象; 使用场景: 1、获取子组件的实例(子组件需为react类继承组件); 2、获取组件中某个DOM元素; 3、用做组件的全局变量,useRef返回对象中含有一个current属性,该属性可以在整个组件色生命周期内不变,不会因为重复render而重复申明,类似于react类继承组件的属性this.xxx一样。原因:由于useState保存的变量会触发组件render,而使用useRef定义全局变量不会触发组件render;

const refContainer = useRef(initialValue);

useImperativeHandle

用于使用 ref 时暴露 DOM 元素的方法。

useImperativeHandle(ref, () => ({
 // 暴露的方法
}));

useLayoutEffect

与 useEffect 类似,但它在所有的 DOM 变更之后同步执行。这在需要读取 DOM 布局并同步触发重渲染时非常有用。

useLayoutEffect(() => {
 // 副作用操作
}, [dependencies]);

useDebugValue

用于在 React 开发者工具中显示自定义 hook 的标签。

useDebugValue(value);

2.React Native

本文作者:何以之

本文链接:https://www.cnblogs.com/serendipity-echo/p/18668591

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   何以之  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 残酷游戏 卫兰
  2. 2 明知做戏 吴雨霏
  3. 3 你,好不好? 周兴哲
  4. 4 我可以 蔡旻佑
  5. 5 云烟成雨 房东的猫
  6. 6 说散就散 JC 陈咏桐
  7. 7 我配不上你 夏天Alex
  8. 8 不再联系 夏天Alex
  9. 9 等我先说 夏天Alex
  10. 10 我知道他爱你 夏天Alex
  11. 11 多想在平庸的生活拥抱你 隔壁老樊
  12. 12 这一生关于你的风景 隔壁老樊
  13. 13 我曾 隔壁老樊
  14. 14 关于孤独我想说的话 隔壁老樊
  15. 15 过客 周思涵
  16. 16 备爱 周思涵
  17. 17 嚣张 en
  18. 18 海口 后弦
明知做戏 - 吴雨霏
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 夏至(蔡冕丽)

作曲 : 方文良

编曲 : 吴国恩

等你的汽水喝一半给你加片薄冰

等你的桌面满泄我总会打理重整

不想纯情

不够聪明

你未发现我的身影

得我帮你依照编码整理家里电影

只会得我一个帮你选购喜爱铃声

天天如常

估你心情

等一个眼神求证

一闪擦过如流星

怎么我为我做过的感到惊怕

就像爱吗我也不肯定恐怕

我以为存在吗

千变万化

从来不肯开口可相信吗

离谱吗

请你不要阻我喜欢你

明明是爱但你未说话你扮作闪避

这个沉默冷静的你亳无办法处理

其实我亦怕是错摸心理

总有天会等到好天气

游行示爱大叫着你在某大遍草地

等你无用退避不过仍然害羞的你

还是顾忌太不争气

明知做戏

即使你未太在意不感到惊讶

现在要说爱你请准备招架

勇气还存在吗

不要害怕

随时真的胆敢亲手送花

离谱吗

请你不要阻我喜欢你

明明是爱但你未说话你扮作闪避

这个沉默冷静的你亳无办法处理

其实我亦怕是错摸心理

总有天会等到好天气

游行示爱大叫着你在某大遍草地

等你无用退避不过仍然害羞的你

还是顾忌太不争气

明知做戏

不过不要阻我紧张你

如何令你愉快让我办妥为你准备

喜爱沉默冷静的你还是自信的你

仍愿意为你造一些惊喜

总有天会等到好天气

游行示爱大叫着你在某大遍草地

等你无用退避不过途人目光不理

期待贴着你的手臂

无须做戏

等你喜爱等你不爱就凭摘毫验证

想爱不爱偏爱不理亦同样难划清

天天如常

估你心情

不想扑索来求证

争取过趁还年青

终于你下决定来答应

太动听