前端高频面试题(15K级别)

1.简单描述一下 Babel 的编译过程?

首先,Babel的作用是 从一种源码到另一种源码,充当转换编译器的作用,可以简述为 解析(解析JS代码)->转换(解析和修改AST)->重建(将修改后的AST转换成另一种JS代码)

2.JavaScript 中的数组和函数在内存中是如何存储的?

  • 数组,JS里的数组主要就是 以连续内存形式存储的FixedArray、以哈希表形式存储的HashTable

  • 函数,函数属于引用数据类型,存储在堆中,在栈内存中只是存了一个地址来表示对堆内存中的引用。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

3.发布 / 订阅模式和观察者模式的区别是什么?

在观察者模式中,被观察者通常会维护一个观察者列表。当被观察者的状态发生改变时,就会通知观察者。

在发布订阅模式中,具体发布者会动态维护一个订阅者的列表:可在运行时根据程序需要开始或停止发布给对应订阅者的事件通知。

区别在于发布者本身并不维护订阅列表(它不会像观察者一样主动维护一个列表),它会将工作委派给具体发布者(相当于秘书,任何人想知道我的事情,直接问我的秘书就可以了);订阅者在接收到发布者的消息后,会委派具体的订阅者来进行相关的处理。

4.如何处理浏览器中表单项的密码自动填充问题?

表单中当input是password类型时,打开浏览器会自动填充浏览器存储的密码,在input中加入autocomplete="new-password"即可解决。之所以new-password能够解决off失效的原因是autocomplete属性的有效值只有on和off,默认值是on,如果autocomplete的属性是除on和off外的值,那么就是个无效值,那么浏览器就会放弃对该属性的执行。

5.Hash 和 History 路由的区别和优缺点?

hash 路由模式的实现主要是基于下面几个特性:

  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。

history 路由模式的实现主要基于存在下面几个特性:

  • pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
  • 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

6.JavaScript 中的 const 数组可以进行 push 操作吗?为什么?

可以,也可以进行splice()操作。

const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容

7.JavaScript 中对象的属性描述符有哪些?分别有什么作用?

  • Configurable(可配置性)

可配置性决定是否可以使用delete删除属性,以及是否可以修改属性描述符的特性,默认值为true

  • Enumerable(可枚举性)

可枚举性决定属性是否出现在对象的属性枚举中,比如是否可以通过for-in循环返回该属性,默认值为true

  • Writable(可写性)

可写性决定是否可以修改属性的值,默认值为true

  • Value(属性值)

属性值包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值为undefined

  • getter

在读取属性时调用的函数。默认值为undefined

  • setter

在写入属性时调用的函数。默认值为undefined

8.JavaScript 中 console 有哪些 api ?

console.clear()

console.log()

console.info()

console.warn()

console.error()

console.time()

console.timeEnd()

9.简单对比一下 Callback、Promise、Generator、Async 几个异步 API 的优劣?

  • 首先callback不是异步API,它是早年JS异步编程实现的一种手段。
  • Promise是社区为了解决回调地狱的问题在ES6版本提出的一种解决方案;
  • enerator也是一种异步编程解决方案,它最大的特点就是可以交出函数的执行权,Generator 函数可以看出是异步任务的容器,需要暂停的地方,都用 yield 语法来标注;
  • Async/await是 ES7 中提出的新的异步解决方案,async 是 Generator 函数的语法糖,async/await 的优点是代码清晰(不像使用 Promise 的时候需要写很多 then 的方法链)。async/await 不仅仅是 JS 的异步编程的一种方式,其可读性也接近于同步代码,让人更容易理解。

10.Object.defineProperty 有哪几个参数?各自都有什么作用?

Object.defineProperty(object, propertyname, descriptor)

  • object 必需。要在其上添加或修改属性的对象。这可能是一个本机 JavaScript对象(即用户定义的对象或内置对象)或 DOM 对象。
  • propertyname 必需。一个包含属性名称的字符串。
  • descriptor 必需。属性描述符。它可以针对数据属性或访问器属性。

它内部的descriptor参数如下:

  • value

属性的值,默认为 undefined。

  • writable

该属性是否可写,如果设置成 false,则任何对该属性改写的操作都无效(但不会报错),对于像前面例子中直接在对象上定义的属性,这个属性该特性默认值为为 true。

  • configurable

如果为false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化,对于像前面例子中直接在对象上定义的属性,这个属性该特性默认值为为 true。。

  • enumerable

是否能在for-in循环中遍历出来或在Object.keys中列举出来。对于像前面例子中直接在对象上定义的属性,这个属性该特性默认值为为 true。

  • get

一旦目标对象访问该属性,就会调用这个方法,并返回结果。默认为 undefined。

  • set

一旦目标对象设置该属性,就会调用这个方法。默认为 undefined。

11.Object.defineProperty 和 ES6 的 Proxy 有什么区别?

Proxy的优势如下

  • Proxy可以直接监听整个对象而非属性。
  • Proxy可以直接监听数组的变化。
  • Proxy有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的。
  • Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;
  • Proxy做为新标准将受到浏览器产商重点持续的性能优化,也就是传说中的新标准的性能红利。

Object.defineProperty 的优势如下

  • 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平。

Object.defineProperty 不足在于:

  • Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。
  • Object.defineProperty不能监听数组。是通过重写数据的那7个可以改变数据的方法来对数组进行监听的。
  • Object.defineProperty 也不能对 es6 新产生的 Map,Set 这些数据结构做出监听。
  • Object.defineProperty也不能监听新增和删除操作,通过 Vue.set()和 Vue.delete来实现响应式的。

12.为什么要使用 TypeScript ? TypeScript 相对于 JavaScript 的优势是什么?

首先,不一定非要用TS,大型业务产品、多人协作写大堆的业务代码不适合TS。

1.为JavaScript、IDE和实践(如静态检查)提供了高效的开发工具。(主要)

2.其他的比如强大的类型系统,泛型支持、模块支持等等(次要)

13.Vue 2.x 模板中的指令是如何解析实现的?

指令本质上就是一个 JavaScript 对象,对象上挂着一些钩子函数,无论是官方提供的指令,还是自定义指令,一个指令从第一次被绑定到元素上到最终与被绑定的元素解绑,它会经过以下几种状态:

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

了每个状态的钩子函数,这样我们就可以让指令在不同状态下做不同的事情。当虚拟DOM渲染更新的时候会触发create、update、destory这三个钩子函数,从而就会执行updateDirectives函数来处理指令的相关逻辑,执行指令函数,让指令生效。

14.简要说明 Vue 2.x 的全链路运作机制?

  • 初始化以及挂载init, mount
  • 在进行模板编译compile,将template编译为渲染函数render function
  • 执行render function生成Virtual DOM, render function => VNode tree
  • 再进行响应式依赖收集,render function => getter, setter => Watcher.update => patch。以及使用队列进行异步更新的策略。
  • 最后通过diff算法后进行patch更新视图

15.如何理解 Vue 是一个渐进式框架?

渐进式代表的含义是:没有多做职责之外的事。

你可以使用jsx开发,你也可以写template;你可以使用vue全家桶,你也可以把它做为某个业务的轻量视图,随你,不强求不主张。

16.Vue 里实现跨组件通信的方式有哪些?

  • 父子通信:

父向子传递数据是通过 props,子向父是通过 events(emit);通过父链/子链也可以通信(emit);通过父链 / 子链也可以通信(emit);通过父链/子链也可以通信(parent / children);ref也可以访问组件实例;provide/injectAPI;children);ref 也可以访问组件实例;provide / inject API;children);ref也可以访问组件实例;provide/injectAPI;attrs/$listeners

  • 兄弟通信:

Bus;Vuex

  • 跨级通信:

Bus;Vuex;provide / inject API、attrs/attrs/attrs/listeners

17.Vue 中响应式数据是如何做到对某个对象的深层次属性的监听的?

使用watch并且搭配deep:true 就可以实现对对象的深度监听

18.MVVM、MVC 和 MVP 的区别是什么?各自有什么应用场景?

MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式。

  • 耦合性低
  • 重用性高
  • 生命周期成本低

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

  • 模型与视图完全分离,我们可以修改视图而不影响模型
  • 可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
  • 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
  • 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)

MVVM 本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。

  • 低耦合
  • 可重用性
  • 独立开发
  • 可测试

19.什么是 MVVM 框架?

MVVM,特点是采用双向绑定(data-binding): View的 变动,自动反映在View Model,反之亦然。这样开发者就不用处理接收事件和View更新的工作,框架已经帮你做好了。

20.Vue CLI 3.x 有哪些功能?Vue CLI 3.x 的插件系统了解?

插件系统是给vue项目提供可选功能的npm包,如:Babel/TypeScript 转译、ESLint 集成、unit和 e2e测试 等

21.Vue CLI 3.x 中的 Webpack 是如何组装处理的?

对比vue-cli2,cli3 最主要的就是生成的项目中,进行webpack配置的文件没有了。cli3的脚手架封装了webpack绝大部分配置,使得生成的项目更加清晰,但是在开发中免不了会有自己的个性需求,来添加一些自己的项目配置,此时只需在项目的根目录下新建一个vue.config.js文件即可。而webpack中是通过 resolve.alias 来实现此功能的。在vue.config.js中修改webpack的配置,可以通过configureWebpack方法。

22.Vue 2.x 如何支持 TypeScript 语法?

  • 配置ts-loader,tsconfig
  • 增加类型扩展,让ts识别vue文件
  • vue文件中script里面换成ts写法, 需要增加几个ts扩展的package, 比如vue-property-decorator

23.Webpack 中 Loader 和 Plugin 的区别是什么?

在webpack中 Loader 就是负责完成项目中各种各样资源模块的加载,从而实现整体项目的模块化,而 Plugin 则是用来解决项目中除了资源模块打包以外的其他自动化工作,对比 Loader 只是在模块的加载环节工作,而插件的作用范围几乎可以触及 Webpack 工作的每一个环节。

24.如何发布开发项目的特定文件夹为 Npm 包的根目录?

一般情况下,npm包的根目录时node_modules,可以使用package.json的directories属性里的directories.lib,更改 Npm 包的根目录。

25.Npm 包中 peerDependencies 的作用是什么?

peerDependencies的目的是提示宿主环境去安装满足插件peerDependencies所指定依赖的包,然后在插件import或者require所依赖的包的时候,永远都是引用宿主环境统一安装的npm包,最终解决插件与所依赖包不一致的问题。

26.如何优雅的调试需要发布的 Npm 包?

  • 在需要调试的npm包目录下结构下的控制台输入npm link 这个命令会把当前包映射到本地的一个全局的npm包里面;
  • 在引用的目录结构下的控制台输入 npm link 包名称 这个命令会把本地引用的这个npm包的路径定位到全局的npm包下;
  • 全局的npm包相当于一个中转站,在编辑区域与引用区域之间中转。

27.了解 Git (Submodule)子模块吗?简单介绍一下 Git 子模块的作用?

子模块是进行开发和需求进行对接将需求文档作为子模块项目,嵌入开发人员的项目中。子模块的使用既可以减少需求或设计人员的git操作,又可以及时的将doc文档发布到项目的目录文件下,而且不会对开发人员的项目产生任何影响。

28.Git 如何修改已经提交的 Commit 信息?

  • git rebase -i <commit id> 列出 commit 列表
  • 找到需要修改的 commit 记录,把 pick 修改为 edit 或 e,:wq 保存退出
  • 修改 commit 的具体信息git commit --amend,保存并继续下一条git rebase --continue,直到全部完成
  • 中间也可跳过或退出git rebase (–skip | --abort)

29.Git 如何撤销 Commit 并保存之前的修改?

  • 查看commit git log --pretty=oneline
  • 撤销到上一个commit,但是保存当前的修改。git reset --soft <commit>
  • 修改成功。重建分支,进行提交。

30.Git 如何 ignore 被 commit 过的文件?

  • 删除 track 的文件 (已经 commit 的文件)
  • 在 .gitignore 文件中添加忽略规则

在 .gitignore 文件中添加 ignore 条目, 如: .DS_Store 提交 .gitignore 文件: git commit -a -m “添加ignore规则”

  • 推送到远程仓库让 ignore 规则对于其他开发者也能生效

31.在使用 Git 的时候如何规范 Git 的提交说明(Commit 信息)?

用Commitizen,Commitizen 是一个撰写符合上面 Commit Message 标准的一款工具。在push操作时检查commit的信息,使用正则检查是否匹配(比如使用angular的git规范),不符合的不允许Push。

32.ESLint 和 Prettier 的区别是什么?两者在一起工作时会产生问题吗?

这俩解决的不是一个问题,ESLint 主要解决的是代码质量问题;Prettier主要解决的是代码风格问题。两者在一起会产生问题。

33.如何调试 Node.js 代码?如何调试 Node.js TypeScript 代码?在浏览器中如何调试 Node.js 代码?

从nodejs8开始,node去掉了_debugger , 内部集成了inspect , 以往使用node-inspect实现的在线调试不再可用.node8开始要用新方法了。

  • 在服务端用inspect模式运行nodejs
node --inspect-brk=0.0.0.0:8080 index.js
  • 打开chrome浏览器 地址栏输入chrome://inspect,在弹出的界面中输入ip:port即可调试。

34.CDN 服务如何实现网络加速?

CDN的工作原理就是将您源站的资源缓存到位于全球各地的CDN节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回您的源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。

35.WebSocket 使用的是 TCP 还是 UDP 协议?

是基于TCP的,websocket的协议是在TCP/IP协议簇的应用层,和http在同一层。

36.什么是单工、半双工和全双工通信?

  • 单工数据传输只支持数据在一个方向上传输;
  • 半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
  • 全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

37.简单描述 HTTP 协议发送一个带域名的 URL 请求的协议传输过程?(DNS、TCP、IP、链路)

38.输入地址回车后

  • 浏览器通过请求得到一个HTML文本
  • 渲染进程解析HTML文本,构建DOM树
  • 解析HTML的同时,如果遇到内联样式或者样式脚本,则下载并构建样式规则(stytle rules),若遇到JavaScript脚本,则会下载执行脚本。
  • DOM树和样式规则构建完成之后,渲染进程将两者合并成渲染树(render tree)
  • 渲染进程开始对渲染树进行布局,生成布局树(layout tree)
  • 渲染进程对布局树进行绘制,生成绘制记录
  • 渲染进程的对布局树进行分层,分别栅格化每一层,并得到合成帧
  • 渲染进程将合成帧信息发送给GPU进程显示到页面中

39.Cookie 可以在服务端生成吗?Cookie 在服务端生成后的工作流程是什么样的?

可以。HTTP 协议中的 Cookie 包括 Web Cookie 和浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。

40.Session、Cookie 的区别和关联?如何进行临时性和永久性的 Session 存储?

  • Session

客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session 对象,存储结构为 ConcurrentHashMap。Session 弥补了 HTTP 无状态特性,服务器可以利用 Session 存储客户端在同一个会话期间的一些操作记录。

  • Cookies

HTTP 协议中的 Cookie 包括 Web Cookie 和浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。

服务器端session,如果你不指定session的存储时间,在你打开的浏览器中存储的值,是可以在新打开的框口内得到的,关闭后就自动消失(消失的其实是session_id,因为session的机制是依赖于cookie的(还可以依赖其他的)。

41.设置 Cookie 时候如何防止 XSS 攻击?

在服务器端设置cookie的时候设置 http-only, 这样就可以防止用户通过JS获取cookie。对cookie的读写或发送一般有如下字段进行设置:

  • http-only: 只允许http或https请求读取cookie、JS代码是无法读取cookie的(document.cookie会显示http-only的cookie项被自动过滤掉)。发送请求时自动发送cookie.
  • secure-only: 只允许https请求读取,发送请求时自动发送cookie。
  • host-only: 只允许主机域名与domain设置完成一致的网站才能访问该cookie。

设置Cookie,可以防止攻击者拿到正常用户的Cookie冒充身份非法调用网站接口。

42.简单描述一下用户免登陆的实现过程?可能会出现哪些安全性问题?一般如何对用户登录的密码进行加密?

在用户第一次登录成功的时候,后端会返回一个 Token,这个值Token 主要的作用就是用于识别用户的身份。相当于账号密码。正常情况下,前端给后端发送请求的时候,后端都需要先判断用户的身份,来返回相应的数据给用户。获取到Token后,你需要把 Token 存在 Cookie中。接着向服务器发送请求时,你从 Cookie 中取出 Token,在请求头中携带上 Token 。Token过期时间设置足够长,只要token没过期,这段时间用户都是免登录。

安全问题:其他人使用本机,实现免登录,无法在每次使用应用时验证用户的身份。提供了便捷,失去了安全校验。

对用户登录的密码进行加密,密码MD5化,不使用明文传输。

43.HTTP 中提升传输速率的方式有哪些?常用的内容编码方式有哪些?

  • 使用压缩技术把实体主体压小,在客户端再把数据解析。
  • 使用分块传输编码,将实体主体分块传输,当浏览器解析到实体主体就能够显示了。

常用的内容编码方式:

  • 非归零码
  • 曼彻斯特编码
  • 差分曼彻斯特编码

44.传输图片的过程中如果突然中断,如何在恢复后从之前的中断中恢复传输?

文件的断点续传,

前端工作

  • 为每一个文件切割块添加不同的标识
  • 当上传成功的之后,记录上传成功的标识
  • 当我们暂停或者发送失败后,可以重新发送没有上传成功的切割文件

后端工作

  • 接收每一个切割文件,并在接收成功后,存到指定位置,并告诉前端接收成功
  • 收到合并信号,将所有的切割文件排序,合并,生成最终的大文件,然后删除切割小文件,并告知前端大文件的地址

45.什么是代理?什么是网关?代理和网关的作用是什么?

代理是中间人,使用代理的主机发出的IP报文的目的IP是代理的,但是会在应用层里明确告诉代理,自己真实需求是什么。网关即Gateway,它是连接基于不同通信协议的网络的设备,使文件可以在这些网络之间传输。

46.HTTPS 相比 HTTP 为什么更加安全可靠?

因为 HTTPS 保证了传输安全,防止传输过程被监听、防止数据被窃取,可以确认网站的真实性(具体细节二面再说)。不过需要注意的是,即便使用 HTTPS 仍可能会被抓包,因为HTTPS 只防止用户在不知情的情况下通信被监听,如果用户主动授信,是可以构建“中间人”网络,代理软件可以对传输内容进行解密。

47.什么是对称密钥(共享密钥)加密?什么是非对称密钥(公开密钥)加密?哪个更加安全?

传统的对称式加密需要通讯双方都保存同一份密钥,通过这份密钥进行加密和解密。所以非对称加密也称为单密钥加密。在非对称加密中,加密和解密使用的是不同的密钥。非对称加密中的密钥分为公钥和私钥。公钥顾名思义就是公开的,任何人都可以通过公钥进行信息加密,但是只有用户私钥的人才能完成信息解密。非对称加密带来了一个好处,避免了对称式加密需要传输和保存同一份密钥的痛苦。

非对称加密一定比对称加密机密性更高吗? 不一定, 因为机密性高低是根据秘钥长度而变化的。而且非对称加密最大的问题,就是性能较差,无法应用于长期的通信。

48.你觉得 HTTP 协议目前存在哪些缺点?

HTTP不具备必要的安全功能,与最初的设计相比,现今的Web网站应用的HTTP协议的使用方式已发生了翻天覆地的变化。几乎现今所有的Web网站都会使用会话(session)管理、加密处理等安全性方面的功能,而HTTP协议内并不具备这些功能。

从整体上看,HTTP就是一个通用的单纯协议机制。因此它具备较多优势,但是在安全性方面则呈劣势。就拿远程登录时会用到的SSH协议来说,SSH具备协议级别的认证及会话管理等功能,HTTP协议则没有。另外在架设SSH服务方面,任何人都可以轻易地创建安全等级高的服务,而HTTP即使已架设好服务器,但若想提供服务器基础上的Web应用,很多情况下都需要重新开发。

因此,开发者需要自行设计并开发认证及会话管理功能来满足Web应用的安全。而自行设计就意味着会出现各种形形色色的实现。结果,安全等级并不完备,可仍在运作的Web应用背后却隐藏着各种容易被攻击者滥用的安全漏洞的Bug。

49.Webpack 中的插件机制是如何设计的?

Webpack 插件机制的目的是为了增强 Webpack 在项目自动化构建方面的能力。在webpack中 Loader 就是负责完成项目中各种各样资源模块的加载,从而实现整体项目的模块化,而 Plugin 则是用来解决项目中除了资源模块打包以外的其他自动化工作,对比 Loader 只是在模块的加载环节工作,而插件的作用范围几乎可以触及 Webpack 工作的每一个环节。

Webpack 的插件机制就是我们在软件开发中最常见的钩子机制。钩子机制也特别容易理解,它有点类似于 Web 中的事件。在 Webpack 整个工作过程会有很多环节,为了便于插件的扩展,Webpack 几乎在每一个环节都埋下了一个钩子。这样我们在开发插件的时候,通过往这些不同节点上挂载不同的任务,就可以轻松扩展 Webpack 的能力。

50.如何提升 Node.js 代码的运行稳定性?

  • 保障进程安全

由于一个用户的异常访问或者数据异常,加上没有做好异常处理和安全保护,直接导致了整个 Node.js 服务重启了,从而中断了所有人的请求,用户体验非常差。①由于 Node.js 使用的是 JavaScript,而JavaScript 是一个弱类型语言,因此在现网经常会引发一些由代码逻辑的异常导致的进程异常退出。②其次在 Node.js 中也经常会因为内存的使用不当,导致内存泄漏,当在 64 位系统中达到 1.4 G(32 位系统 0.7 G)时,Node.js 就会异常崩溃。③再而由于Node.js 的 I/O 较多也较为频繁,当启用较多 I/O 句柄,但是没有及时释放,同样会引发进程问题。

  • parameters error

关于 JSON.parse 很多时候我们都比较自然地将其他接口或者第三方的数据拿来解析,但是这里往往会忽略其非 JSON 字符串的问题,在这里需要进行try catch 异常判断。

  • other errors

当前 Node.js 的 Promise 应用越来越广泛了,因此对于 Promise 的 catch 也应该多进行重视,对于每个 Promise 都应该要处理其异常 catch 逻辑,不然系统会提示 warning 信息。还有一些常见的长连接的服务,比如 Socket、Redis、Memcache 等等,我们需要在连接异常时进行处理,如果没有处理同样会导致异常,比如 Socket 提供了 Socket.on(‘error’) 的监听。

  • 注意服务异常方面的内存泄露

设置最大临时缓存数,超出则不使用缓存;设置最大缓存句柄数,超出则不使用缓存;定时清理当前的临时缓存和句柄缓存。

  • 避免全局变量

一般情况下不建议使用全局变量,全局变量必须要有一定的上限和清理规则才能保证服务的安全。

  • 避免单例模块中的变量内存泄漏

要注意一个点,有些模块我们使用单例的模式,就是在每次 require 后都返回这个对象,这种情况也比较容易引发内存泄漏的问题。因为单例模式会引发每个用户访问的数据的叠加。

  • 主动关闭打开文件后未关闭的情况

一般打开文件句柄后,我们都应该主动关闭,如果未主动关闭,就会导致文件句柄越来越多,从而引发句柄泄漏问题。

51.Vue SSR 的工作原理?Vuex 的数据如何同构渲染?

在Vue SSR中,创建Vue实例、创建store和创建router都是套了一层工厂函数的,目的就是避免数据的交叉污染。在服务端只能执行生命周期中的created和beforeCreate,原因是在服务端是无法操纵dom。服务端渲染和客户端渲染不同,需要创建两个entry分别跑在服务端和客户端,并且需要webpack对其分别打包;SSR服务端请求不带cookie,需要手动拿到浏览器的cookie传给服务端的请求。SSR要求dom结构规范,因为浏览器会自动给HTML添加一些结构比如tbody,但是客户端进行混淆服务端放回的HTML时,不会添加这些标签,导致混淆后的HTML和浏览器渲染的HTML不匹配。

对于同构应用来说,我们必须实现客户端与服务端的路由、模型组件、数据模型的共享。Vuex是实现我们客户端和服务端的状态共享的关键,我们可以不使用vuex,但是我们得去实现一套数据预取的逻辑;可以尝试封装一个可以给组件们共享的EventBus,在main.js中export出我们的EventBus以便两个entry使用,接下来是我们的两个entry了。server用来匹配我们的组件并调用组件的asyncData方法去获取数据,client用来将预渲染的数据存储到我们eventBus中的data中。这样就相当于实现类Vuex的功能。

52.SSR 技术和 SPA 技术的各自的优缺点是什么?

SSR:

  • 更利于SEO。
  • 更利于首屏渲染
  • 服务端压力较大

SPA:

  • 页面之间的切换非常快
  • 一定程度上减少了后端服务器的压力(不用管页面逻辑和渲染)
  • 后端程序只需要提供API,完全不用管客户端到底是Web界面还是手机等
  • 不利于SEO
  • 首屏加载压力大

53.什么是单点登录?如何做单点登录?

单点登录是指在同一帐号平台下的多个应用系统中,用户只需登录一次,就可访问所有相互信任的应用系统。比如你在网页中登录了百度云盘,随后你再去贴吧发帖 是不需要二次登录的。

单点登录的本质就是在多个应用系统中共享登录状态。如果用户的登录状态是记录在 Session 中的,要实现共享登录状态,就要先共享 Session,比如可以将 Session 序列化到 Redis 中,让多个应用系统共享同一个 Redis,直接读取 Redis 来获取 Session。

因为不同的应用系统有着不同的域名,尽管 Session 共享了,但是一个企业不同应用的域名不同,依然可能出现跨站or跨域。

前端方面的实现方式:

  • 父域 Cookie
  • 认证中心
  • LocalStorage 跨域

手写

01.数组扁平化

const arr = [1, [2, [3, [4, 5]]], 6];

方法一:使用flat()

const res1 = arr.flat(Infinity);

方法二:使用reduce

const flatten = arr => {
   
  return arr.reduce((pre, cur) => {
   
    return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
  }, [])
}
const res4 = flatten(arr);

方法五:函数递归

const res5 = [];
const fn = arr => {
   
  for (let i = 0; i < arr.length; i++) {
   
    if (Array.isArray(arr[i])) {
   
      fn(arr[i]);
    } else {
   
      res5.push(arr[i]);
    }
  }
}
fn(arr);

02.数组去重

const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];

方法一:利用Set

const res1 = Array.from(**new** Set(arr));

方法二:两层for循环+splice

const unique1 = arr => {
   
  let len = arr.length;
  for (let i = 0; i < len; i++) {
   
    for (let j = i + 
  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
华为机试真库提供了100道算法,并提供了正确解法和解思路。这些目是华为机试真,大概率会考到原。如果你有任何问,可以在库中留言进行交流和探讨。 华为机试一般有三道算法,其中前两道属于简单或中等难度,分值为100分。第三道目为中等或困难难度,分值为200分。总分为400分,答时间为150分钟。过去通过150分即可,但现在分数要求可能有所提高。不管怎样,大家都要努力刷,争取拿高分。分数越高,评级就越高,工资待遇也越高。一般工资待遇是15K~30K*14~16,非常可观。 此外,如果你对华为机试真感兴趣,我还邀请你一同入驻我的博客。我的博客即将同步至腾讯云开发者社区,你可以在那里找到更多的资源和信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [华为OD机试真2022(JavaScript)](https://blog.csdn.net/weixin_40767375/article/details/125276961)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2023年华为笔试面试机考真100道(C/C++语言)](https://blog.csdn.net/weixin_38815609/article/details/125658519)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值