面试题(高级)

前端 ⭐⭐⭐⭐⭐

一. JS原生

1. MVVM响应式原理 ⭐⭐⭐⭐⭐

以Vue举例:
MVVM响应式主要是通过Object.defineProperty配合发布订阅者模式来实现的, 对于Vue来说, 他内部是这么实现的:

① 实现了属性监听器
首先, Vue中data的属性会进行递归遍历, 将其中所有的属性以及数组元素进行Object.defineProperty绑定, 设置了属性的getter和setter监听, 其中,每个属性都会实例化一个该属性的订阅器对象, 该订阅器对象会在getter触发时收集视图更新回调方法, setter会通知该属性的视图更新方法去更新视图

② 绑定完属性监听后,Vue会对html模板进行解析
在解析过程中, Vue会递归遍历dom树, 获取dom中可被Vue识别的属性, 如双花括号, v-model, v-html等等, Vue会获取这些被识别的属性其中的值, 这些值是data中的一些属性, Vue会对这个属性的视图更新方法进行收集 , 将这个更新方法收集到每个属性独有的一个watcher对象中, 在收集的过程中, 会对旧值进行存储, 在这些值被调用的时候, 就触发了这些值对应的data的属性的getter, getter就会把视图更新方法收集到这个属性的订阅器中。当这些属性发生变化时, 会触发该属性的setter, setter会触发订阅器的通知方法,去遍历监听方法执行, 如果旧值不等于新值,则触发视图的更新回调

但是angular和Vue的双向绑定不是一个原理:
angular 是通过脏检测实现,angular 会将 UI 事件,请求事件,settimeout 这类延迟,的对象放入到事件监测的脏队列,当数据变化的时候,触发 $diget 方法进行数据的更新,视图的渲染

2. 箭头函数和普通函数的区别 ⭐⭐⭐⭐⭐

箭头函数是普通函数的简写,但是它不具备很多普通函数的特性
① this指向,箭头函数的this指向它定义时所在的对象,而不是他的调用者
② 函数声明不会提升
③ 没有arguments对象,不能使用arguments,如果要获取参数的话可以使用rest运算符
④ 没有yield属性,不能作为生成器Generator使用
⑤ 不能实例化
⑥ 没有自己的this,不能调用call和apply
⑦ 没有prototype,new关键字内部需要把新对象的_proto_指向函数的prototype

3. html5新特性有哪些 ⭐⭐⭐⭐

① canvas
② 用于播放的video和audio标签
③ 本地离线存储localStorage长期存储数据,浏览器关闭后数据不丢失
④ sessionStorage的数据在浏览器关闭后自动删除
⑤ 新增语意化更好的内容元素,比如 article、footer、header、nav、section
⑥ 新的技术webworker, websocket(长连接), Geolocation

4. 浏览器缓存有哪些 ⭐⭐⭐⭐⭐

① http缓存 是基于HTTP协议的浏览器文件级缓存机制。
② websql 这种方式只有较新的chrome浏览器支持,并以一个独立规范形式出现
③ indexDB 是一个为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API
④ Cookie 一般网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)
⑤ localstorage html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数据,加快下次页面打开时的渲染速度
⑥ sessionstorage 和localstorage类似,但是浏览器关闭则会全部删除,api和localstorage相同,实际项目中使用较少。
⑦ application cache 是将大部分图片资源、js、css等静态资源放在manifest文件配置中
⑧ cacheStorage 是在ServiceWorker的规范中定义的,可以保存每个serverWorker申明的cache对象
⑨ flash缓存 这种方式基本不用,这一方法主要基于flash有读写浏览器端本地目录的功能

可能会问到的扩展题:

4.1 cookie、localStorage、sessionStorage区别 ⭐⭐⭐⭐⭐

点击查看

5.HTTP各个请求方式的特点 ⭐⭐⭐⭐⭐

GET:
① 请求参数附加在url上
② 请求参数长度较短, ie为2048字节, 谷歌为8182字节(取决于各个浏览器url最大长度)
③ 请求数据可被缓存
④ 常用于查询操作, 因为速度快, 方便快捷

POST:
① 常用于数据的增删改, 大容量数据的传输, 文件上传, 表单提交, 或者参数量较大的查询操作
② 请求参数在Request body中,不附加在url上
③ 请求数据不会被缓存

DELETE:
常用于服务器数据的删除操作

PUT:
常用于服务器数据的更新操作

OPTION:
① 获取服务器支持的HTTP请求方法;
② 用来检查服务器的性能。

6. 原型和原型链 ⭐⭐⭐⭐⭐

原型: 原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型。

原型链: 多个__proto__组成的集合成为原型链

所有实例的__proto__都指向他们构造函数的prototype
所有的prototype都是对象,自然它的__proto__指向的是Object()的prototype
Object的隐式原型是null

所有的 JS 对象(JS 函数是 prototype)都有一个 proto 属性,指向它的原型对象。当试图访问一个对象的属性时,如果没有在该对象上找到,它还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

可能会问到的扩展题:

6.1 实现继承的方式 ⭐⭐⭐⭐

①原型继承
原理: 把父类的实例作为子类的原型
缺点:子类的实例共享了父类构造函数的引用属性 不能传参

②组合继承
原理: 在子函数中运行父函数,但是要利用call把父类的this改变一下,再在子函数的prototype里面new父类 ,使父类的原型中的方法也得到继承,最后改变子类的原型中的构造函数(constructor)

③寄生组合继承
原理: 在子函数中运行父函数,但是要利用call把父类的this改变一下, 然后在外部实例化父类, 将父类的构造方法改为子类, 然后, 将子类的prototype改为父类实例。
(扩展: 将子类的prototype改为父类实例原因: 将父类的构造方法改为子类后,子类的prototype指向父类实例,这样,在子类new的时候,父类的prototype属性会携带过来, 但是, 这么做的缺点就是子类原型链的属性丢失, 必须在该继承方法执行后再去声明子类的原型链属性)

④ES6为了弥补之前js设计上的缺陷, 采用了类似java的方式以类的形式声明原型, 可以使用类的extends继承

7. viewport是什么, 它有什么作用 ⭐⭐⭐⭐

点击查看

8. JS垃圾(内存)回收机制 ⭐⭐⭐⭐⭐

点击查看

9. call apply bind的区别 ⭐⭐⭐⭐⭐

首先, 这三个函数都是用于改变this指向的函数
不同:
①call接收n个参数: 第一个参数是对象, 即this指向要改变成的目标对象, 第二个-第n个参数是执行时传入的参数
②apply接收两个参数: 第一个是对象, 第二个是参数列表
③bind接收的参数和apply一样, 但是bind会返回一个函数, 执行它才会执行bind所调用的函数

10. require和import的区别 ⭐⭐⭐

共同点: 都是用于引入模块
区别:
①require属于commonjs的规范, 主要用于node环境, 浏览器原生不支持require, import是ES6的导入模块的方式, 主要用于浏览器, 但是import/export 在浏览器中无法直接使用,我们需要在引入模块的 <script> 元素上添加type=“module” 属性。
②require是运行时加载, 而import则是编译时加载
③import/export 只能在模块顶层使用,不能在函数、判断语句等代码块之中引用;require/exports 可以。

11. 说一下Js模块化 ⭐⭐⭐⭐⭐

①最初的时候, js引入是采用的script标签引入, 在js文件中使用立即执行函数来防止变量不会被其他js文件污染, 但是, 如果js文件之前有相互依赖关系的话, 就必须保证引入的js文件谁先引入谁后引入的顺序, 否则就会报错

②nodejs发布之后, 就有了commonjs的概念, 在nodejs中, 每一个js文件可被看做成一个模块, 可通过module.exports将这个模块的对象暴露在全局中, 同时可以通过require将这个模块导入到另一个模块中, 导入后就可以使用这个模块的一些属性和方法了

③由于commonjs只适用于node,不能在浏览器环境下使用, 后来就有了AMD规范, 就是require.js, 这种模块引入插件的优点是: 依赖前置。通过require方法引入配置项中的js模块(require.config中的path), 所有模块都引入完成后才会执行回调函数, 在回调函数中就可以使用到这些模块的对象和方法了

④基于commonjs的规范, 然后就有了CMD的规范, 与AMD不同的是, CMD采用的是模块需要的时候才会加载(就近依赖), 不需要的时候不会加载
⑤ES6出现后, 可采用新的引入模块机制
import语法声明用于从已导出的模块、脚本中导入函数、对象、指定文件(或模块)的原始值。
import模块导入与export模块导出功能相对应,也存在两种模块导入方式:命名式导入(名称导入)和默认导入(定义式导入)。
import必须放在文件的最开始.import命令是编译阶段执行的,在代码运行之前,表达式和变量只有在运行时才能得到结果的语法结构。import命令会被 JavaScript 引擎静态分析,先于模块内的其他模块执行(叫做”连接“更合适)所以import中不能含有表达式或者变量,因此无法实现动态加载.
因此,import和export命令只能在模块的顶层,不能在代码块之中(比如,在if代码块之中,或在函数之中)。
这样的设计,有利于编译器提高效率,但也导致无法在运行时加载模块。在语法上,条件加载就不可能实现。如果import命令要取代 Node 的require方法,这就形成了一个障碍。因为require是运行时加载模块,import命令无法取代require的动态加载功能。

12. 你是如何做前端优化的 ⭐⭐⭐⭐⭐

点击查看

13. 说一下js的事件循环机制(Event Loop) ⭐⭐⭐⭐⭐

首先, js是一门单线程的语言, 它的异步和多线程的实现是通过事件循环机制实现的。事件循环涉及到宏任务和微任务:
1、微任务(MircoTask)
Promise中的then、catch、finally
MutationObserver(监视 DOM 变动的API,详情参考MDN)
Object.observe(废弃:监听标准对象的变化)
Process.nextTick(Node环境,通常也被认为是微任务)

2、宏任务(MacroTask/Task)
基本上,我们将javascript中非微任务(MircoTask)的所有任务都归为宏任务,比如:
script中全部代码
DOM操作
用户交互操作
所有的网路请求
定时器相关的 setTimeout、setInterval 等

在代码执行时, 代码会放到调用栈中, 并执行, 调用完成后会释放, 当遇到promise等微任务时, 微任务回调中的代码会放到微任务队列中, 遇到定时器等宏任务时, 宏任务回调中的代码会放到宏任务队列中。当代码上下文执行完毕后, 如果宏任务微任务都没有执行时间,则会先执行微任务的代码(顺序执行), 然后在执行宏任务的代码(顺序执行)

14. 从浏览器输入url后都经历了什么 ⭐⭐⭐⭐⭐

①先进行DNS域名解析,先查看本地hosts文件,查看有没有当前域名对应的ip地址,若有直接发起请求,没有的话会在本地域名服务器去查找,如果本地域名服务器没查找到,会从根域名服务器查找,该过程属于迭代查找,根域名会告诉你从哪个与服务器查找,最后查找到对应的ip地址后把对应规则保存到本地的hosts文件中。
注:
如果想加速以上及之后的http请求过程的话可以使用缓存服务器CDN,CDN过程如下:
用户输入url地址后,本地DNS会解析url地址,不过会把最终解析权交给CNAME指向的CDN的DNS服务器
CDN的DNS服务器会返回给浏览器一个全局负载均衡IP
用户会根据全局负载均衡IP去请求全局负载均衡服务器
全局负载均衡服务器会根据用户的IP地址,url地址,会告诉用户一个区域负载均衡设备,让用户去请求它。
区域负载均衡服务器会为用户选择一个离用户较近的最优的缓存服务器,并把ip地址给到用户
用户想缓存服务器发送请求,如果请求不到想要的资源的话,会一层层向上一级查找,知道查找到为止。

②进行http请求,三次握手四次挥手建立断开连接
③服务器处理,可能返回304也可能返回200
返回304说明客户端缓存可用,直接使用客户端缓存即可,该过程属于协商缓存
返回200的话会同时返回对应的数据
④客户端自上而下执行代码
其中遇到CSS加载的时候,CSS不会阻塞DOM树的解析,但是会阻塞DOM树的渲染,并且CSS会阻塞下面的JS的执行
然后是JS加载,JS加载会影响DOM的解析,之所以会影响,是因为JS可能会删除添加节点,如果先解析后加载的话,DOM树还得重新解析,性能比较差。如果不想阻塞DOM树的解析的话,可以给script添加一个defer或者async的标签。
defer:不会阻塞DOM解析,等DOM解析完之后在运行,在DOMContentloaed之前
async: 不会阻塞DOM解析,等该资源下载完成之后立刻运行
进行DOM渲染和Render树渲染
获取html并解析为Dom树
解析css并形成一个cssom(css树)
将css和dom合并成渲染树(render树)
进行布局(layout)
进行绘制(painting)

15. 浏览器常见的攻击方式有哪些 ⭐⭐⭐⭐⭐

①xss脚本注入
不需要你做任何的登录认证,它会通过合法的操作(比如在url中输入、在输入框或者富文本中输入),向你的页面注入脚本(可能是js、hmtl代码块等)。
防御:
编码:对用户输入的数据进行HTML Entity 编码。把字符转换成 转义字符。Encode的作用是将$var等一些字符进行转化,使得浏览器在最终输出结果上是一样的。
过滤:移除用户输入的和事件相关的属性。
②csrf跨域请求伪造
在未退出A网站的前提下访问B,B使用A的cookie去访问服务器
防御
token,每次用户提交表单时需要带上token(伪造者访问不到),如果token不合法,则服务器拒绝请求

16. 请简述一下js中的this指向 ⭐⭐⭐⭐⭐

this取值符合以下规则:
排除使用箭头函数和apply、call或bind方法的情况, this指向可以概括为: 在this所在的函数中, 谁调用了这个函数,this就指向谁。
①在调用函数时使用new关键字,函数内的this是一个全新的对象。
②如果apply、call或bind方法用于调用、创建一个函数,函数内的 this 就是作为参数传入这些方法的对象。
③当函数作为对象里的方法被调用时,函数内的this是调用该函数的对象。比如当obj.method()被调用时,函数内的 this 将绑定到obj对象。
④如果调用函数不符合上述规则,那么this的值指向全局对象(global object)。浏览器环境下this的值指向window对象,但是在严格模式下(‘use strict’),this的值为undefined。
⑤如果符合上述多个规则,则较高的规则(1 号最高,4 号最低)将决定this的值。
⑥如果该函数是 ES2015 中的箭头函数,将忽略上面的所有规则,this被设置为它被创建时的上下文。

17. 跨域的解决方案 ⭐⭐⭐⭐⭐

①后台cors跨域, 设置 Access-Control-Allow-Origin : ‘xxx地址’, 设置后,可以通过Access-Control-Request-Method设置允许请求的方式
②通过nginx代理跨域
③iframe之间的跨域可以使用postMessage来实现
④JSONP跨域, 但是JSONP只支持get请求

二. Vue or React

1. Vue的路由跳转方式 ⭐⭐⭐

//vue:
<router-link :to="{name:'team',params:{userId:123}}">跳转</router-link>
//react:
<Link to={{ pathname: '/team', query: { userId: '123' } }}>跳转</Link>

//vue
this.$router.push({name:'team',params:{userId:789}});
//或
this.$router.push({name:'team',query:{userId:789}});

//react
this.props.history.push({name:'team',query:{userId:789}});

2. vue怎么实现页面的权限控制⭐⭐

可以在即将进去需要权限控制的页面时, 读取用户的权限,实现这么一个操作
如果权限比较多或者较多页面需要权限控制, 可以利用 vue-router 的 beforeEach 事件,可以在跳转页面前判断用户的权限(利用 cookie 或 token),是否能够进入此页面,如果不能则提示错误或重定向到其他页面,在后台管理系统中这种场景经常能遇到。

3. 父子和兄弟组件传参的方式 ⭐⭐⭐⭐⭐

Vue:
父传子:
通过props, 在父组件中使用子组件时, 通过自定义属性来传值, 这些自定义属性的值会被props中的属性接收, 和data中的属性一样, 在created后可获取

子传父:
①子传父是通过事件的方式, 即$emit, 比如在子组件的点击事件中, 要把id等一些参数传到父组件中, 就要通过

this.$emit('事件名',参数1,参数2...)

的方式, 注册一个事件,在父组件中使用@事件名的形式, 通过事件方法得到参数
②通过ref属性也可以获取到子组件中的变量和方法

兄弟组件之间的传值:

  1. 兄弟的父组件做中转传值
  2. 兄弟组件之间的传值也可以通过$emit事件的方式, 需要在A组件中注册B组件的事件, 先通过import引入该组件, 然后在方法或者A组件的生命周期中触发B组件的事件, B组件也是通过@事件名的形式, 通过事件方法, 在A组件中B组件的事件被调用时, 会在B组件中执行相关的事件方法

React:
父传子: 和Vue类似, 在父组件中使用子组件时, 使用属性名={xxx}的形式传递, 子组件可以在props属性中接收
子传父: 子组件通过调用父组件传递到子组件的方法向父组件传递消息的, 父组件在子组件模板上写一个属性为一个父组件方法, 子组件可通过props.这个属性名来调用他, 并传递参数
兄弟组件传值: 兄弟的父组件做中转传值

4. Vuex是什么, 它有什么作用? ⭐⭐⭐⭐⭐

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex可以简化组件之间的调用。
react的redux, flutter的provider和Vuex功能相同, 都是为了实现单页面应用的状态管理。
在多页面应用中, 状态管理只能通过localStorage、sessionStorage或者请求后台来实现。
可能被问到的扩展题:

4.1. Vuex的属性有几种,各发挥了什么作用 ⭐⭐⭐⭐

有五种,分别是State , Getter , Mutation , Action , Module (就是mapAction)

  1. state:vuex的基本数据,用来存储变量

  2. geter:从基本数据(state)派生的数据,相当于state的计算属性

  3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,第二个参数为收到的数据。

  4. action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。

  5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

5. React的生命周期 ⭐⭐⭐⭐⭐

初次渲染时:
componentWillMount: 在渲染前调用。
componentDidMount : 在第一次渲染后调用。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
更新时, 会多次调用:
componentWillReceiveProps: 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate:在组件接收到新的props或者state时被调用, 会返回一个布尔值。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
componentWillUpdate: 在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate: 在组件完成更新后立即调用。在初始化时不会被调用。
销毁时:
componentWillUnmount: 在组件从 DOM 中移除之前立刻被调用。
constructor是组件类的构造函数, 主要用于接收props的参数以及state的定义

6. redux的作用是什么, 为什么不采用全局变量的形式 ⭐⭐⭐⭐⭐

redux虽然和全局变量相比有共同点, 都是可以解决组件之间值来回传递的不方便问题。
但是一个全局变量在被改变之后无法驱动 React 组件重新渲染。
redux的一个比较重要的功能就是: 状态决定渲染结果,因此只有状态改变了才需要重新渲染。如果你用一个非状态的全局变量来保存状态,那任何一个 React 组件都不会因为这个全局变量的人改变而重新渲染。

7. redux的用法 ⭐⭐

3个api:
getState: 返回当前状态(producer的数据)
dispatch: 有条件地、具名地修改store的数据(可以通过传递数据的属性来判断更新那个reducer)
subscribe: 订阅store更新(观察者模式)

8. 你知道虚拟DOM吗? 请简述一下它的工作原理 ⭐⭐⭐⭐⭐

Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。

Virtual DOM 工作过程有三个简单的步骤。

  1. 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。
    在这里插入图片描述
  2. 然后计算之前 DOM 表示与新表示的之间的差异。

在这里插入图片描述

  1. 完成计算后,将只用实际更改的内容更新 real DOM。
    在这里插入图片描述
    优点:
    ①减少了dom操作, 尤其是dom过多时频繁的dom操作会导致页面卡顿, 虚拟dom很好的优化了这一点
    ②跨平台, react native中也使用了虚拟dom算法

Java ⭐⭐⭐⭐

1. Java的8中基本类型 ⭐⭐⭐⭐⭐

byte:
byte 数据类型是8位、有符号的,以二进制补码表示的整数;
最小值是 -128(-2^7);
最大值是 127(2^7-1);
默认值是 0;
byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;

short:
short 数据类型是 16 位、有符号的以二进制补码表示的整数
最小值是 -32768(-2^15);
最大值是 32767(2^15 - 1);
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
默认值是 0;

int:
int 数据类型是32位、有符号的以二进制补码表示的整数;
最小值是 -2,147,483,648(-2^31);
最大值是 2,147,483,647(2^31 - 1);
一般地整型变量默认为 int 类型;
默认值是 0 ;

long:
long 数据类型是 64 位、有符号的以二进制补码表示的整数;
最小值是 -9,223,372,036,854,775,808(-2^63);
最大值是 9,223,372,036,854,775,807(2^63 -1);
这种类型主要使用在需要比较大整数的系统上;
默认值是 0L;
例子: long a = 100000L,Long b = -200000L。
"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。

float:
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
float 在储存大型浮点数组的时候可节省内存空间;
默认值是 0.0f;
浮点数不能用来表示精确的值,如货币;

double:
double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;
浮点数的默认类型为 double 类型;
double类型同样不能表示精确的值,如货币;
默认值是 0.0d;

boolean:
boolean数据类型表示一位的信息;
只有两个取值:true 和 false;
这种类型只作为一种标志来记录 true/false 情况;
默认值是 false;

char:
char 类型是一个单一的 16 位 Unicode 字符;
最小值是 \u0000(十进制等效值为 0);
最大值是 \uffff(即为 65535);
char 数据类型可以储存任何字符;

2. String和StringBuilder、StringBuffer的区别 ⭐⭐⭐⭐⭐

Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它们可以储存和操作字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。

SQL ⭐⭐⭐⭐

1. 你是如何进行SQL优化的 ⭐⭐⭐⭐⭐

点击查看

2. where1=1是干什么用的⭐⭐

where 1 = 1 用于动态SQL拼接,规范语句
where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句。
这个东西的作用仅仅只是为了满足多条件查询页面中不确定的各种因素而采用的一种构造一条正确能运行的动态SQL语句的一种方法。

问项目, 可能被问到的项目中的问题 ⭐⭐⭐⭐⭐

1. 我看到你简历里写到你做过树组件的优化, 请问你是怎么做的 ⭐⭐⭐

做这个优化的原因是因为原先的树组件存在加载大数据量的时候会存在卡顿甚至卡死的情况, 针对这种情况:
首先, 我排查了源码, 了解这个树组件挂载节点是如何渲染的, 经过排查后发现源码中使用了for循环在视图上使用了appendChild方法, 当节点很多时,频繁的dom操作自然就会非常的卡顿
我采用的优化策略是使用了requestAnimationFrame方法来实现, 该方法是页面每一帧都会触发, 当浏览器最小化的时候不会触发, 利用这点, 我设置了每一帧渲染节点的个数, 通过该方法大大优化了加载卡死的情况。

2. 我看到你使用过nodeJs, 请问你为什么要使用它? 它在你项目中发挥了什么作用? ⭐⭐

我做nodejs主要是做公司的一些中间件程序的开发, 用于处理一些复杂, 并且调用接口较多, 涉及到并发, 以及需要消息推送的功能。使用它的主要原因是nodejs的非阻塞I/O特性, 可以较好的处理并发量较高的场景。

问其他-HR面

1. 为什么要从这家公司离职? ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

目前在公司, 我的水平得不到很好的发展, 我想寻求一个更能体现我价值的工作环境, 并且, 我以后会打算在xx城市买房的

2. 自我介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值