前端面试题——2021最新企业面试题

2021最新企业面试题

  • 对MVVM的理解
  • 浏览器的渲染机制
  • 事件循环机制(Event Loop)
  • 宏任务和微任务(先执行微观任务,再执行宏观任务)
  • 你对Promise的理解
  • 数组的常用方法
  • 虚拟DOM的原理
  • 为什么操作对象会比操作DOM快
  • vue组件之间的通讯
  • 说一下vuex的属性
  • 说一下生命周期
  • 你用过keepAlive吗?这个有生命周期吗?
  • compenter和watch的区别
  • 你是怎么做懒加载的
  • 你是怎么进行移动端的设配的(我说rem)你使用rem有遇到过设配问题吗?
  • 说一下弹性盒模型
  • vue和react如何选择
  • vue的混入
  • vue的双向绑定原理
  • vue的key属性的作用
  • vue-router
  • redux
  • react-hook(加强版函数组件)
  • 路由拦截
  • webpack的使用
  • webpack的loader
  • sass的使用
  • CSS3的新特性
  • git销毁某个日志
  • Es6哪些新增的数据结构
  • 有使用哪些自定义指令
  • 自定义指令的生命周期和哪些钩子函数
  • 为什么promise能实现同步的写法?
  • 你对闭包的使用
  • get和post的区别
  • 合并对象时, 使用Object.assign()和展开运算符的不同
  • 你能说说对模块化的理解吗
  • rem布局是怎么实现的
  • ajax原理
  • 讲一下bom 和 怎么拿到屏幕的大小
  • 讲一下http的理解和状态码
  • 报文形式
  • http状态码 TCP状态
  • 三次握手
  • 字符集有哪些
  • 局部刷新(ajax)原理
  • 数字运算精度问题怎么解决
  • websocket 的原理,如果要传入数据怎么传
  • 页面登录的流程
  • 深拷贝
  • 如果有3个ajax请求,有一个成功了就发送请求,怎么判断
  • 以前项目的数据结构
  • Map类型的使用场景
  • cdn:
  • Jwt:
  • $set什么时候用,怎么用

对MVVM的理解

model是数据层, view是视图层, viewmodel是视图模型, MVVM是一种双向数据绑定模式, 核心思想: 通过数据驱动视图, 把需要改变视图的数据初始化到实例中,然后再通过修改实例中的数据,从而实现对视图的更新

浏览器的渲染机制

1、首先当用户输入一个URL的时候,浏览器就会发送一个请求,请求URL对应的资源。
2、然后浏览器的HTML解析器会将这个文件解析,并且构建成一棵DOM树。
3、在构建DOM树的时候,遇到JS和CSS元素,HTML解析器就换将控制权转让给JS解析器或者是CSS解析器。
4、JS解析器或者是CSS解析器解析完这个元素时候,HTML又继续解析下个元素,直到整棵DOM树构建完成。
5、DOM树构建完之后,浏览器把DOM树中的一些不可视元素去掉,然后与CSSOM合成一棵render树。
6、接着浏览器根据这棵render树,计算出各个节点(元素)在屏幕的位置。这个过程叫做layout,输出的是一棵layout树。
7、最后浏览器根据这棵layout树,将页面渲染到屏幕上去。

事件循环机制(Event Loop)

等待主线程中任务全部完成后,再回来把异步队列中任务放到主程序中运行,这样反复的循环,就是事件循环
1. 先执行主任务,把异步任务放入循环队列当中
2. 等待主任务执行完,再执行队列中的异步任务
3. 异步任务先执行微观任务,再执行宏观任务
4. 一直这样循环,反复执行,就是事件循环机制

宏任务和微任务(先执行微观任务,再执行宏观任务)

异步任务分为 宏任务(macrotask) 与 微任务 (microtask),不同的API注册的任务会依次进入自身对应的队列中,然后等待 Event Loop 将它们依次压入执行栈中执行。
宏任务:setTimeout、setInterval、script(整体代码)、I/O、UI 交互事件、setImmediate(Node.js 环境)
微任务:Promise、MutaionObserver、process.nextTick(Node.js 环境)

你对Promise的理解

promise是为了解决回调地狱而产生的, Promise构造函数接受一个函数作为参数,分别是resolve和reject, then接收成功的回调, catch接收失败的回调。
ES6新增了async和await可以让我们用同步的写法实现异步的效果,配合try...catch使用可以捕获异常, 当await等待不到结果时, 会被catch捕获并提示异常
三个状态:
    1)pending 初始状态
    2)fulfilled 成功状态
    3)rejected 失败状态
三个缺点:
    1)无法取消Promise,一旦新建它就会立即执行,无法中途取消
    2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
    3)当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
all/race

数组的常用方法

push
pop
shift
unshift
contact
splice
slice
sort
reserve
forEach/map/filter/some/every

虚拟DOM的原理

1. 用JavaScript模拟DOM树,并渲染这个DOM树
2. 比较新老DOM树,得到比较的差异对象
3. 把差异对象应用到渲染的DOM树。

为什么操作对象会比操作DOM快

因为浏览器内核有两个引擎: js引擎和渲染引擎, 对象是在js引擎中的, 而dom是在渲染引擎中的, 跨引擎操作是有性能开销的, 所以操作对象会比操作DOM快

vue组件之间的通讯

父子通信: 
    父向子传递数据是通过props, 子向父是通过自定义事件 ($emit)
    通过父链/子链也可以通信($parent/$children)
    ref也可以访问组件实例
    provide / inject APl
    $attrs / $listeners
兄弟通信: 
    Bus; Vuex
跨级通信: 
    Bus; Vuex; provide/ inject APl, $attrs/$listeners

说一下vuex的属性

state、getter、mutation、action、module
state: 就是数据源存放地, 当mutation修改了state的数据的时候,会动态的去修改所有的调用这个变量的所有组件里面的值
getter: 可以对 state 进行计算操作,它就是 store 的计算属性
mutation: 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
action: 异步代码

说一下生命周期

cmud
WillMount(dom/ajax/定时器/本地储存)
DidMount
WillUpdate
DidUpdate(新的DOM节点操作/发起新的网络请求)
WillUnmount(清除定时器/终止请求)

你用过keepAlive吗?这个有生命周期吗?

keep-alive缓存不活动的实例组件, keep-alive有两个属性include:名称匹配的组件会被缓存, exclude:名称匹配的组件不会被缓存
在被keep-alive包含的组件/路由中,会多出两个生命周期的钩子: activated与deactivated
activated: 在组件第一次渲染时会被调用, 之后在每次缓存组件被激活时调用(不会触发beforeCreate created beforeMount mounted)
deactivated: 组件被停用(离开路由)时调用(不会触发beforeDestroy和destroyed)

compenter和watch的区别

计算属性computed:
    1. 支持缓存,依赖的数据变,才重新计算
    2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
    3. 多对一或者一对一,一般用computed
    4. get和set方法
监听属性watch:
    1. 不支持缓存,数据变,就会触发
    2. watch支持异步
    3. 一对多,一般使用watch
    4. immediate和deep

你是怎么做懒加载的

自己封装了一个可以适配所有屏幕的滚动条到达底部的方法,原理是使用scrollTop + clientHeight >= scrollHeight 那么就是滚动条滚到底部了, 然后在里面发送请求, 请求到下一页的数据进行加载

你是怎么进行移动端的设配的(我说rem)你使用rem有遇到过设配问题吗?

px2rem插件
媒体查询
设置根元素font-size + rem
    document.documentElement.style.fontSize = document.documentElement.clientWidth / 375 * 16 + 'px'

说一下弹性盒模型

css3新增的特性, 是一种响应式布局方式, 把父元素设置为display: flex, 子级通过flex参数来设置缩放比例,缩放条件,排序方式等

vue和react如何选择

vue:简洁和轻量、单页面应用程序
vue的优势:
    模板和渲染函数的弹性选择
    简单的语法和项目配置
    更快的渲染速度和更小的体积
react:构建大型应用程序、同时适用于Web端和原生App、最大的生态圈
react的优势:
    更适合大型应用和更好的可测试性
    Web端和移动端原生APP通吃
    更大的生态系统,更多的支持和好用的工具

vue的混入

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
    钩子函数合并
    数据对象合并
    普通方法合并
    局部混入
        1. 创建一个mixins.js文件, 定义一个混入对象
        2. 在页面调用时, import引入mixins文件, 通过mixins:[‘文件名’]来使用

vue的双向绑定原理

Vue采用数据劫持结合发布者-订阅者模式的方法,通过Object.defineProperty()来劫持各个属性的setter,getter属性,在数据变动话,通知订阅者,触发更新回调函数,重新渲染视图
    observer 实现对vue各个属性进行监听
    compiler 实现对vue各个指令模板的解析器,编译成Virtual Dom,渲染视图
    Watcher 连接observer和compiler,接受每个属性变动的通知,绑定更新函数,更新视图

vue的key属性的作用

官方文档:
    当 Vue.js 用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
key属性的作用:
    在有了key属性之后,Vue会记住元素们的顺序,并根据这个顺序在适当的位置插入/删除元素来完成更新,这种方法比没有key属性时的就地复用策略效率更高。这样可以提高列表渲染的效率,提高了页面的性能。

vue-router

router-link: 路由入口
router-view: 路由出口
vue-router参数传递:
    1)动态路由传参
    2) 通过路由属性中的name来确定匹配的路由,通过params来传递参数
    3) 使用path来匹配路由,然后通过query来传递参数
vue-router导航钩子:
    vue-router 的导航钩子,主要用来作用是拦截导航,让他完成跳转或取消
    第一种:全局导航钩子(beforeEach/afterEach)
    第二种:单独路由独享钩子(beforeEnter)
    第三种:组件内的钩子(beforeRouteEnter/beforeRouteUpdate/beforeRouteLeave)
编程式导航:
    1).router.push()
    2).router.replace()
    3).router.go(n)
mode的两个模式:
    History 模式
        充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求
    hash 模式
        hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页,也就是说hash 出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash 模式的原理是 onhashchange 事件(监测hash值变化),可以在 window 对象上监听这个事件

redux

Redux 的基本思想是整个应用的 state 保持在一个单一的 store 中。store 就是一个简单的 javascript 对象,而改变应用 state 的唯一方式是在应用中触发 actions,然后为这些 actions 编写 reducers 来修改 state。整个 state 转化是在 reducers 中完成,并且不应该有任何副作用。
createStore
    创建 store 对象,包含 getState, dispatch, subscribe, replaceReducer
reducer
    reducer 是一个计划函数,接收旧的 state 和 action,生成新的 state
action
    action 是一个对象,必须包含 type 字段
dispatch
    dispatch( action ) 触发 action,生成新的 state
subscribe
    实现订阅功能,每次触发 dispatch 的时候,会执行订阅函数
combineReducers
    多 reducer 合并成一个 reducer
replaceReducer
    替换 reducer 函数
middleware
    扩展 dispatch 函数!

react-hook(加强版函数组件)

React Hooks 要解决的问题是状态共享,不会产生 JSX 嵌套地狱问题。设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数
    State Hook(状态的钩子)
        useState:参数表示state变量的初始值
        setCount:用于改变state变量的函数
    Effect Hook(执行副作用操作的钩子)
        useEffect: 看做 componentDidMount,componentDidUpdate 的结合

路由拦截

当我们登陆的时候, 服务器返回一个token标记符给我们, 客户端拿到token后保存到本地localStorage或vuex中. 在main.js入口文件注册全局守卫, 使用beforeEach钩子函数设置路由拦截, 当我们访问需要登陆才能进入的页面(购物车/个人中心/订单页)时, 把token传到后端并进行校验, 如果校验成功, 则允许进入, 反之则禁止进入

webpack的使用

1. webpack.config.js(根目录)
2. module.exports配置项
3. 常用配置项
    entry: 页面入口文件配置(字符串或者一个对象)
	output: 配置打包的结果(一个对象)
	fileName:定义输出文件名(字符串)
	path: 定义输出文件路径(字符串)
	publicPath:公共资源路径(字符串)
	module: 定义对模块的处理逻辑(对象)
	loaders:定义一系列的加载器(数组)
	plugins: 定义插件(数组)

webpack的loader

loader: 用于对模块源码的转换,loader描述了webpack如何处理非javascript模块,并且在buld中引入这些依赖。
loader可以将文件从不同的语言(如TypeScript)转换为JavaScript,ES5 解析成 ES6,LESS 文件解析成 CSS 文件。比如说:CSS-Loader,Style-Loader等。

sass的使用

$var 变量用于存储一些信息,它可以重复使用
@mixin 指令允许我们定义一个可以在整个样式表中重复使用的样式。
@include 指令可以将混入(mixin)引入到文档中
@import 指令可以让我们导入其他文件等内容

CSS3的新特性

选择器/弹性盒/圆角/阴影/过渡/动画/倾斜/缩放/平移/旋转

git销毁某个日志

git reset --soft commit~3
git reset --hard

Es6哪些新增的数据结构

new Set: add()、delete()、has()、clear()、keys()、values()、entries()、forEach()
new WeakSet: add()、delete()、has()
new Map: get()、set()、has()、delete()、key()、values()、entries()
new WeakMap: get()、set()、has()、delete()

有使用哪些自定义指令

自动聚焦v-focus

自定义指令的生命周期和哪些钩子函数

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。

为什么promise能实现同步的写法?

+ 因为每次then后都会重新返回一个新的promise实例, 所以才能一直then下去, 从而实现同步的写法
+ 链式写法能一直then下去的原因:链式调用靠的是返回新的promise,来保证可以一直走成功或失败

你对闭包的使用

1. 实现公有变量
    eg: 函数累加器
2. 可以做缓存(存储结构)
    eg: eater
3. 可以实现封装,属性私有化
    eg: Person();
4. 模块化开发,防止污染全局变量

get和post的区别

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求在URL中传送的参数是有长度限制的,而POST没有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中

合并对象时, 使用Object.assign()和展开运算符的不同

关键的区别: 扩展运算符总是给你一个拷贝后的普通对象。而Object.assign()函数却修改其第一个传入对象obj, 就是把第一个以后的参数合并到第一个参数上

你能说说对模块化的理解吗

模块化开发是指项目中每一个功能和组件都是一个独立的模块, 彼此互不影响, 方便分别管理
(1) 解决命名冲突
(2) 依赖管理
(3) 解决高耦合低内聚无复用
(4) 提高代码可读性

rem布局是怎么实现的

如果设计师给的图是750px;那么1rem就是750/16=46.875px;也就是1rem代表46.875px;

ajax原理

1. 创建请求对象
let xhr = new XMLHTTPRequest;
2. 设置请求对象
xhr.open('', '', true);
3. 发送网络请求
xhr.send();
4. 监听网络请求
xhr.onreadystatechange = function () {
5. 接收服务器返回的数据
    if(xhr.state === 4){
        if(xhr.readystate === 200){
            console.log(xhr.responseText);
        }else{
            console.log(xhr.statusText);
        }
    }
}

讲一下bom 和 怎么拿到屏幕的大小

Window(窗口)
Navigator(浏览器)
Screen (客户端屏幕)
History(访问历史)
Location(浏览器地址)
setInterval
setTimeout
alert	警告框	
confirm	确认框	
prompt	输入框
获取文档显示区域的高度和宽度: window.innerWidth/window.innerHeight
获取屏幕大小: window.screen

讲一下http的理解和状态码

HTTP: 简单、快速、灵活、明文传输(HTTPS)、无状态-cookie
200         服务器成功处理了请求
301/302     url重定向
403         请求资源被拒绝
404         Not Found(页面丢失)未找到资源
500         服务器故障或Web应用故障

报文形式

HTTP响应报文的结构
请求报文:  请求首部(请求头 + 请求行)  +  请求主体(请求体)
响应报文:  响应首部(响应头 + 状态行)  +  响应主体(响应体)

请求头:对客户端以及对请求本身的描述信息
请求行: 协议 和 方法
请求体:提交给服务器端的参数(POST请求)

响应头:对服务器端以及对响应本身的描述信息
状态行:网络请求的状态(成功?失败)
响应体:服务器返回给客户端的具体的数据

http状态码 TCP状态

TCP状态
    CLOSED(closed):初始状态,表示TCP连接是“关闭着的”或“未打开的”
    LISTEN(listen):表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。
    ESTABLISHED(established):表示TCP连接已经成功建立。

三次握手

第一次握手: 客户端向服务器发送一个连接请求
第二次握手: 服务器收到连接请求后返回一条收到消息给客户端
第三次握手: 客户端把确认消息发给服务端

字符集有哪些

常见字符集名称:ASCII字符集、GB2312字符集、Unicode字符集(UTF-8、UTF-16、UTF-32和UTF-7)

局部刷新(ajax)原理

AJAX引擎会在不刷新浏览器地址栏的情况下,发送请求
使用JavaScript在指定的位置,显示响应数据,从而局部修改页面的数据,达到局部刷新目的

数字运算精度问题怎么解决

toFixed() 方法进行四舍五入保留指定位数
Math.round() 方法进行四舍五入为整数

websocket 的原理,如果要传入数据怎么传

ws.onmessage()

页面登录的流程

在登录的时候, 把用户输入的账号密码通过get请求传给服务端, 服务端收到后对账号密码进行验证, 如果验证通过, 则给客户端返回一个token, 把token存到cookie或localStorage中, 当需要进入一些设置了拦截器的页面时, 会把这个token传到服务端验证, 如果验证通过, 则允许进入该页面

深拷贝

JSON.stringify
JSON.parse

如果有3个ajax请求,有一个成功了就发送请求,怎么判断

Promise.all(): 三个请求同时发送,当三个请求全部resolve以后才会执行then
Promise.race(): 三个请求有任意一个resolve了,就会走then,别的promise就不管了

以前项目的数据结构

数组 (Array)
栈 (Stack)
堆 (Heap)
队列 (Queue)
树 (Tree)
链表 (Linked List)
散列表 (Hash)

Map类型的使用场景

map是一个二维数组,一组键值对的结构,具有极快的查找速度

cdn:

用户在自己的浏览器中输入要访问的网站的域名,浏览器向本地DNS请求对该域名的解析,通过DNS确定当时最适当的CDN节点,并将解析的结果(IP地址)发给用户,用户向给定的CDN节点请求相应网站的内容

Jwt:

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份, 为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名
三个部分:Header(头部)、Payload(负载)、Signature(签名)

$set什么时候用,怎么用

当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。此时需要用到$set。
Vue.set()和this.$set()区别在于: Vue.set()是将set函数绑定在Vue构造函数上,this.$set()是将set函数绑定在Vue原型上。
# 附上某家企业面试题(地点:广州)

1.说说都常用到什么es6中的什么方法
2.熟悉vue/react/angular吗,最熟悉的是哪一个?有看过源码吗?(看过源码加分)
3.请解释一下 JavaScript 的同源策略。
4.如何解决跨域问题?
5.闭包有什么优缺点
优化方面:
1.请说出三种减少页面加载时间的方法。
2.你如何对网站的文件和资源进行优化?
其他问题:
1.有没有写过单元测试?
2.有没有写过自动化测试?
3.有没有用nodejs的框架,例如express,koa,eggjs,如果有的话是用于解决什么场景。
工作经验问题:
1.你在(之前/现在)的团队处于什么样的角色,起到了什么明显的作用?
2.项目中遇到什么问题?如何解决?说一个印象最深的
3.最近在学什么?能谈谈你未来3,5年给自己的规划吗?
4.之前有接触过敏捷开发吗?

你可能感兴趣的:(面试题,vue,面试,javascript,html,css)