这次春招投递了8个公司,两个公司缩招没投进去,有效参加了6家公司的招聘。mihoyo笔试阶段被拒;字节、美团杳无音讯;目前拿到了微软苏州STCA、腾讯WXG、阿里盒马三家Offer。本次经历学到很多,也记录了很多。把记录的内容发出来更多的是为了鞭策自己。
DOM
-
获取父亲节点:
document.documentElement.parentNode; // W3C标准(一个节点可能不是Element Node,此时获取不到parentElement) document.documentElement.parentElement; // IE支持
-
meta标签:
- name
- keywords: 网页关键字,针对搜索引擎
- description: 网页描述,针对搜索引擎
- viewport: 移动端窗口
- robots: 定义搜索引擎爬虫的搜索方式
- author: 标注网页作者
- copyright: 标注版权信息
- revisit-after: 搜索引擎爬虫重访时间
- renderer: 双核浏览器渲染方式(webkit/ ie-comp/ ie-stand)
- http-equiv(定义http头)
<meta http-equiv="Content-Security-Policy" content="策略">
- name
CSP指令 | 描述 | 指令值 | 描述 |
---|---|---|---|
default-src | 默认加载策略 | * | 允许任何 |
script-src | 对于JavaScript脚本的加载策略 | 'none' | 不允许任何 |
style-src | 对于样式的加载策略 | 'self' | |
img-src | 图片的加载策略 | data: | 允许data:协议 |
object-src | 显示插件来源,如flash | URL | 允许加载指定域名资源 |
frame-src | unsafe-inline | 允许inline资源 | |
media-src | unsafe-eval | 允许动态js代码 | |
report-uri | 请求资源不被允许时,向该地址提交日志 |
- script和link标签
<script src="" type="application/javascript" defer async></script>
<link href="" rel="stylesheet">
rel是当前文档与被链接文档之间的关系
script最好放在底部,link最好放在头部,为什么? - css加载不会阻塞DOM树的解析,但会阻塞DOM树渲染并且阻塞后面的js语句的执行。 - JS 阻塞 DOM 解析 - 移动端白屏问题和解决方法【问题原因(解决方法)】:
- css加载需要时间,加载过程中是白屏(css代码前置或内联)
- 首屏无实际内容,等待异步请求数据(首评同步渲染html,后续滚屏再采用异步请求数据)
- 首屏内联js的执行会阻塞页面渲染(尽量不要在首屏html中放置内联脚本)
- SSR(服务端渲染)的优缺点:
- 优点:首屏渲染快,SEO好
- SEO好是因为服务端返回的HTML就是已经将数据都渲染好了,而客户端渲染没有数据
- 首屏渲染快是因为客户端需要下载css js解析,渲染,而下载和解析的时候都是白屏
- 缺点:
- 例如Vue生命周期只有到挂载的阶段
- 优点:首屏渲染快,SEO好
DOM事件模型
-
基本事件模型
- 只能注册一个handle事件处理函数
- 在
docmuent.querySelector('button').<event> = handler
-
Level2事件模型
- W3C标准
- 用addEventListener绑定handler函数
- 事件捕获 事件处理 事件冒泡
-
IE事件模型
- attachEvent detachEvent
-
Level3事件模型
- 在Level2上增加了更多的事件类型
- UI事件,焦点事件,鼠标事件,滚轮事件,文本事件,键盘事件,合成事件,变动事件
-
自定义事件模型
class Event { constructor() {} on(key, fn) {} one(key, fn) {} // 绑定一次性事件 off(key, fn) {} emit(key, ...args) {} }
JavaScript
-
js的6种数据类型:undefined、null、Boolean、String、Number、Object
- es6多一个symbol
- 基本数据类型包括undefined、null、Boolean、String、Number、Symbol
- 基本数据类型保存在栈内存中,因为基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。
- 闭包中的基本数据类型变量不保存在栈内存中,而是保存在堆内存中
-
展开与解构:数组解构/对象结构 剩余符... ; 解构符...
-
原型链:
__proto__.__proto__.___proto___...
object instanceof constructor (检查object的原型链里有没有constructor) -
箭头函数能保存函数创建时的 this 值,而不是调用时的值
-
Symbol类型
let sym = Symbol(); let obj = { [sym]: "value" }; console.log(obj[sym]); // "value"
-
for...of遍历值 for...in遍历健
-
Polyfill一个Promise:
class Promise { callbacks = []; constructor(fn) { fn(this._resolve.bind(this)); } then(onFulfilledFunction) { this.callbacks.push(onFulfilledFunction); return this; } _resolve(value) { // 宏任务 setTimeout(() => { this.callbacks.forEach(fn => fn(value)); },0); } }
-
点击穿透:移动端执行顺序 touchstart > touchend > click, click有300ms延迟,如果touchstart绑定callback函数让顶层元素消失,底层元素就会被点到。用tap.js/fastClick.js可以解决。
-
事件捕获/事件冒泡: addEventListener(event, func, bool)
bool是useCaptrue
bool: true 事件捕获
bool: false 事件冒泡
先捕获后冒泡,冒泡兼容性高一点
阻止: event.stopPropagation() / return false; / preventDefault- 三种阻止方式的区别:
- stopPropagation不会触发传播链
- preventDefault阻止元素的默认特性
- return false两者均有(jQuery中)
- 三种阻止方式的区别:
-
Object.defineProperty(obj,'name',{}) 为对象obj定义/修改属性
-
this 永远指向最后调用它的那个对象; 箭头函数它没有自己的this值,它继承外围作用域的this call: 指定函数运行时的this:call(thisArg, args1, args2... ) apply: 和call一样,但是两个参数(thisArg, [args]) bind: 创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,所以说要去手动调用这个函数
-
块级变量作用域: 网页 使用var时会有变量提升:变量可以在声明之前使用,值为undefined(let下报错)
-
Event Loop: 网页 同步 -> 微任务(Promise await后面的代码 process.nextTick[这个直接插入到队列首,而不是尾]) -> 宏任务(setTimeout/setInterval script标签)
-
浅拷贝深拷贝:
- 浅拷贝:
- obj2 = Object.assign({},obj1)
- arr2 = arr1.concat()
- arr2 = arr1.slice()
- 深拷贝:
- JSON.parse(JSON.stringify())
- 递归
- 浅拷贝:
-
Promise:resolve/reject之后不直接执行then/catch,先执行剩下的。
-
闭包:
1.函数嵌套函数; 2.内部函数使用外部函数的参数和变量; 3.参数和变量不会被垃圾回收机制回收。
好处: 1.希望一个变量长期保存内存中; 2.避免全局变量污染; 3.私有成员的存在。
坏处: 1.常驻内存,增加内存使用量; 2.使用不当造成内存泄漏。
(funtion() { let data = { // some data } function funcName(args) { // do something } return { setName: () => {}, func: funcName, something: data.something } })()
-
Generator:
function* func() {let i; while(true){yeild i++;}}
-
跨域:设置CORS(跨域资源共享)
在服务端设置header:- Access-Control-Allow-Origin: url,不能写'*'
- Access-Control-Allow-Methods: GET,PUT,POST,DELETE
- Access-Control-Allow-Headers: Content-Type 或者jsonp:
- 利用script标签的src属性实现跨域(只支持get)
- 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信
- 请求一个服务端API,API需要param callback,return的是callback(content)
-
事件委托:例如有一个
<ul>
列表,里面很多<li>
,如果每一条li都绑定一个函数则会有很大的内存消耗,可以将事件监听设置在<ul>
上,判定点击位置来确定点击的是哪一个<li>
。或者事件冒泡,event.target就是最里面的元素。 -
polyfill es6的class, 包括继承
function class(props1) { this.props1 = props1; } const _extend = function(sub, sup) { Object.setPrototypeOf(sub, sup); // 设定指定对象的原型 sub.prototype = Object.create(sup.prototype); // 拷贝prototype sub.prototype.constructor = sub; // 修改上一步拷贝原型的constructor sub.super = sup.prototype; // super指向父级 if(sup.prototype.constructor === Obejct.prototype.constructor) { // 如果原型是Object(继承自Object) sup的constructor就是自己 sup.prototype.constructor = sup; } }
-
防抖、节流:
- 防抖: 指定时间后触发,在时间内就重新计时。例如双击按钮,监听input去请求ajax
function debounce(fn, delay) { clearTimeout(fn.id); fn.id = setTimeout( () => { fn(); },delay); }
- 节流: 指定时间内触发,只有一次生效
function throttle(fn, delay) { let last = 0; function work() { let now = +new Date(); // = valueOf(Date()); if(last+delay<now) { fn(); } } work() }
-
currentTarget和target区别:
currentTarger指向被绑定的元素,target指向触发事件的元素。
Vue
-
computed缓存答案,依赖不改变就返回缓存
-
双向数据绑定:网页
重写object访问器属性里面的get set方法。 -
生命周期:
# new Vue() 1. beforeCreate # create 2. created 3. beforeMount # Mount 4. mounted ( beforeUpdate updated ) 5. beforeDestory 6. destroyed
-
自定义事件: $emit('name',{props}) 事件名不存在任何自动化的大小写转换
-
VNode: 用虚拟DOM实现
createEmptyVNode(); createTextVNode(); createComponent(); cloneVNode(vnode); createElement(context: Component, tag: any, data: any, children: any, normalizationType: any, alwaysNormalize: boolean);
-
MVC和MVVM的区别
MVC是单向数据流,只有从数据到视图,视图回到数据要靠控制器中转。
MVVM则是靠一个双向的VM层进行UI和数据的双向同步。将后端传输的数据转化为所看到的页面是通过数据绑定。 -
看过源码吗?介绍一下Vue底层。 使用了装饰器模式、观察者模式、策略模式的设计模式。新建一个Vue实例的时候会用装饰器模式,把Mixins挂载到Vue原型上。在initState时对props,methods,data,computed,watch进行初始化。在此之前之后分别调用beforeCreate和created生命周期钩子。然后每个组件都会对应一个observer,如果数据变动了就会通知observer,使用vdom-diff、patch算法更新渲染dom节点。Vue其中还有双向数据绑定,是通过Object.definePropety改写obj访问器属性的get set方法实现的。
Vue-router
<keep-alive>
<router-view :key="$route.fullPath+localUserId"/>
<!-- key 可以让keep-alive更新的时候根据“key不同就更新”来更新或避免更新-->
</keep-alive>
<routre-link :to="" />
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [{
path: '',
redirect: '/main'
},{
path: '/status',
component: submitdetail,
props: (route) => ({
pid: route.query.p,
sid: route.query.s
}),
meta: {
isLogin: true
}
},{
path: '/problem'
children: [
{
path: '/123',
component: ''
}
]
},{
path: '*',
component: page404,
meta: {
isLogin: false
}
}];
var router = new VueRouter({
mode: 'history',
routes: routes
});
export default router;
$router.path // 路径
$router.fullPath // 全写路径
$router.push('home')
$router.push({ path: 'home' })
$router.push({ name: 'user', params: { userId: '123' }})
$router.push({ path: 'register', query: { plan: 'private' }})
$router.replace() // 不会向history添加记录
$router.go(<number>) // 倒退,前进
router.beforeEach( (to, from, naxt) => {
// do something
to.mate.??? // 检测标签
next() // 继续
})
router.afterEach( route => {
// do something
});
-
hash路由和history路由的区别:
- hash模式用window.onhashchange去监听改变页面,参考的是url #后面的字段
- history是在HTML5 history API出现以后
- history模式下要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
-
abstract路由是使用一个不依赖于浏览器的浏览历史虚拟管理后端
Vuex
使用单一状态树
-
State:
- 储存数据
- mapState: 可以帮助生成计算属性
computed: mapState({func: () => {}})
-
Getter:
- 从State里面组织数据返回,类似于MySQL的视图、还有Computed
- getter的返回值会根据它的依赖被缓存起来,只有当它的依赖值发生了改变才会被重新计算
...mapGetters('<module>',{})
将getters映射出来使用
-
Mutation:
- 更改Vuex中state的唯一方法是commit mutation,mutation就是变更状态的方法:
mutations: { func(state,args...) {} }
- 提交载荷(Payload),即提交Mutation所传入的参数:
store.commit('func',payload)
- 更改Vuex中state的唯一方法是commit mutation,mutation就是变更状态的方法:
-
Action:
- 类似于mutation
- Action提交的是mutation,而不是直接改变状态
- Action可以包含异步操作
- 通过dispatch触发
- 在组件中分发actions: ...mapActions([])可以映射为store.dispatch使用
actions: { func(context) { context.commit('<mutation>') } } store.dispatch('func', args...)
plugin
- install方法:
install(Vue, options) {
// 使用基础 Vue.extend 构造器,创建一个“子类”
const plugin = Vue.extend(pluginComponent)
// 创建一个 plugin 的实例 profile 挂载到一个HTMLElement实例上
const profile = new plugin({el: document.createElement('div')})
appendchild(profile.$el) // mount
// 处理options...
// 定义plugin方法
Vue.prototype.$plugin = plugin方法 // 挂在vue原型上面
}
React
- 生命周期
- componentWillMount
- componentDidMount
- componentWillUnmount
- componentWillUpdate(可以用来解决props改变而带来的副作用)
- 为什么用setState而不直接更改state?在Vue里面监听值来实现双向绑定,但是对引用类型支持的不好,为了解决这个问题而使用setState。setState是异步的,用队列机制更新state,来创建/修改虚拟DOM。
Webpack
- 入口entry、loader、plugin、出口output
- webpack由node编写,只识别js。通过loader可以加载识别别的文件。text指定文件后缀regex,还可以指定用的加载器。
- 常用plujin:
- UglifyJsPlugin: sourceMap要关上, compress参数指定是否忽略console和//
- CompressPlugin: 静态资源压缩,还可以指定是否删除原文件
CSS
-
translate3d?
-
虽然margin可以应用到所有元素,但display属性不同时,表现也不同
- block元素可以使用四个方向的margin值
- inline元素使用上下方向的margin值无效
- inline-block使用上下方向的margin负值看上去无效
inline-block使用上下方向的margin负值只是看上去无效,这与其默认的vertical-align:baseline有关系,当垂直对齐的属性值为其他值时,则会显示不同的视觉效果 参考链接
-
filter:drop-shadow()
-
盒子模型:从外到内是:margin->border->padding->content
-
竖着排列文字:write-mode: vertical-lr (IE下tb-lr)
- 字体横行竖列呢? transform: rotate(90deg)
-
~运算符,从哪到哪 第二个参数只能是同级或者子级,不能回到父级
-
direction: rtl(right to left) ltr
-
css兼容:-ms- -moz- -webkit- -o-
-
px, em(font-size), rem(相当于根元素的em), %(相对于父元素), vw(视窗宽度%), vh(视窗高度%), vm(视窗min(width,height)%)。除此之外还有in,cm,mm,t:point,pc:pcia
-
为什么给body设置font-size是62.5%:16px*62.5%=10px,这样1em是10px,2em是20px方便计算。
-
优先级:ID选择器(100) > 类选择器,属性选择器,伪类(:hover)(10) > 类型选择器,伪元素(::before)(1); 通配选择符,关系选择符,否定伪类对优先级没有影响。内联样式有最高优先级(1000)。!import比内联还高。 网址 css权重计算
Flex
-
flex可选择1~3个参数
flex: flex-grow<number> | flex-shrink<number> | flex-basis<width>; flex: 2 2 30px; flex: auto; /* flex: 1 1 auto; */ flex: initial; /* flex: 0 1 auto; 根据自身宽高设置尺寸,缩小但不伸长 */ flex: none; /* flex: 0 0 auto; */
Ps. 是无单位数,是带单位宽度 双值语法:
- 无单位number:
- 有效宽度值width:
-
默认情况下,元素不会缩短至小于内容框尺寸,若想改变这一状况,要设置元素的 min-width 与 min-height属性
-
flex-flow: <flex-direction> | <flex-wrap>
-
flex-direction: row | row-reverse | column | column-reverse
-
flex-wrap: nowrap | wrap | wrap-reverse
-
order: <integer> /*表示此可伸缩项目所在的次序组*/
Grid
- grid语法:
grid: <'grid-template'> |
<'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? |
[ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
- grid-template: 其包含 grid-template-columns,grid-template-rows 和 grid-template-areas
- grid-template-column:
- grid-template-row:
BFC
-
元素内形成BFC环境的条件(关系:或):
- 根元素
- float不是none
- overflow不是visible
- display是inline-block/table-cell/table-caption
- position是absolute/fixed
-
在块格式化上下文中,从包含块的顶部开始,垂直地一个接一个地排列block
-
垂直方向上的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠
- 上下相邻的两个元素;父元素与子元素的margin发生重叠
- 上下相邻的情况下用加float属性来消除重叠
- 如果父元素的margin-top为0,padding-top为0,没有border,而子元素的margin-top不为0,那么父元素距离上方的距离就会是子元素margin-top的值,margin-bottom同理
- 消除父子margin重叠:给父元素加border,设置父元素的padding或者margin,给父元素添加overflow:hidden
-
overflow: hidden下bfc的区域不会与float的元素区域重叠
-
计算bfc的高度时,浮动元素也参与计算
<div class="main"> <div></div> <div></div> </div> <style> .main { background: deepskyblue; /*position: absolute; 加上这句才会形成BFC才会撑开父级元素*/ } .main div { height: 100px; width: 100px; float: left; } </style>
-
BFC的可利用点:清除浮动的影响;清除margin重叠
算法
- 手写快排(为什么要把第一个作为基准值):网页 应该用random的位置作为基准值,防止被特殊数据卡。选择第一个或者最后一个会被已经排好序的数据卡掉。随机选取三个元素,并用它们的中值作为整个数据中值的估计值。或者选择最左端,最右端和中间位置的三个元素的中值作为基准。
- 红黑树:自平衡二叉查找树
- 根节点黑色
- 叶子节点都是黑的
- 如果一个节点是红的,那么他的两个子节点都是黑的
- 对任意节点来说,到叶子节点的每个路径黑节点数量相同 这五个性质使一棵n个结点的红黑树始终保持了logn的高度
SaSS
- @mixins @include
TypeScript
-
指示类型符:
-
接口interface(可选属性?;readonly只读属性)(Array<>,ReadonlyArray<>,any)
-
function:never必须有不可达终点 or Error
-
enum color {black=1,yellow,green=4}
-
当作属使用则用readonly,当作变量使用则用const
-
断言<>/as
-
interface额外属性:
interface SquareConfig { color?: string; width?: number; [propName: string]: any; }
-
枚举的反向映射
enum Enum { A } let a = Enum.A; let nameOfA = Enum[a]; // "A"
-
为了支持CommonJS和AMD的exports, TypeScript提供了
export =
语法。export =
语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。若使用export =
导出一个模块,则必须使用TypeScript的特定语法import module = require("module")
来导入此模块。 -
三斜线指令。
/// <reference path="..." />
指令是三斜线指令中最常见的一种。它用于声明文件间的依赖。三斜线引用告诉编译器在编译过程中要引入的额外的文件。
网络/安全
- XSS(跨站脚本攻击),避免:敏感字符替换,包括javascript:标签
- http缓存:cache-control:
-
private(default)客户端缓存
-
public 缓存服务器缓存
-
max-age=xxx xxx秒后过期
-
no-cache 对比缓存
-
no-stroe 不缓存,强制缓存和对比缓存都无效。
-
脚本缓存在memory cache,静态资源在diskcache
-
首次请求没有缓存,会根据参数设置,向服务器请求缓存,与服务器协商缓存。
-
再次请求如下图:
- 强缓存
- max-age=xxx
- public(客户端和代理服务器均缓存)
- immutable(刷新的时候不要去请求服务器)
- 协商缓存
- etag 文件hash 用来对比文件师是否改变
- last-modified 文件修改时间,精确到s
-
- http2和http1的区别:
- 二进制传输:将请求和相应数据分割为更小的帧,用二进制编码。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装
- header压缩:HPACK压缩。首部表,每次更新差异数据。
- 服务端推送:在浏览器刚请求html时就把JS、CSS推送到客户端,减少延迟。
- 多路复用:同域名下所有通信可以在单个连接上完成,单个链接可以承载任意数量的双向数据流。
- 安全性加强:跑在TLS上面
- TCP拥塞控制:
拥塞控制是防止过多的数据注入网络,使得网络中的路由器或者链路过载。流量控制是点对点的通信量控制,拥塞控制是全局网络流量的整体控制。发送双方都有一个拥塞窗口cwnd- 慢开始:最开始发送方cwnd=1,由小到大逐渐增大发送窗口和拥塞窗口。每经过一个传输轮次,拥塞窗口cwnd加倍。当cwnd超过慢开始门限,则使用拥塞避免算法,避免cwnd增长过大。
- 拥塞避免:每经过一个往返时间RTT,cwnd就增长1。 在慢开始和拥塞避免的过程,一旦发现网络拥塞,就把慢开始门限设为当前值一半,重新设置cwnd为1,重新慢启动。(这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕)
- 快重传:接收方每次收到一个失序的报文段后就立即发出重复确认,发送方只要连续收到三个重复确认就立即重传。
- 快恢复:当发送方连续收到了三个重复确认,就乘法减半(慢开始⻔限减半),将当前的cwnd设置为慢开始⻔限,并且采用拥塞避免算法(连续收到了三个重复请求,说明当前网络可能没有拥塞)。
- RESTful
- 协议。经常使用https。
- 域名。部署在专用域名之下
api.example.com
或者example.com/api/
- 版本。
api.example.com/v1/
- 路径(终点)。表示API的具体网址
- HTTP动词。GET POST DELETE PUT PATCH
- 过滤信息。
- 状态码。
- 错误处理。如果状态码是4xx就返回错误信息。
- 返回结果。
- Hypermedia API
- API身份认证应该使用OAuth 2.0框架
- 数据格式尽量使用json
- CSRF(Cross-site request forgery, 跨站请求伪造)
- XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任
- 防御
- 关键操作(例如非幂等操作)使用POST方法
- 关键操作上加验证码增加和用户的交互
- 验证referer
- token验证(服务端渲染),如果是前后端分离式,那么就在每一次请求的时候发放下一次的token,第一次请求来鉴权
通常提问
- 项目中遇到的困难,如何解决的
- 介绍一下项目核心内容
“你还有什么问题问我们吗?”
- 通过这次面试,在您看我还有什么可以提高的地方,不足是什么?(面试情况有没有达到您的期望)(少问,有的面试官不喜欢听到这个问题)
- 平常公司前端岗位的技术栈/常用框架是什么呢?
面经
阿里盒马
内推提前批,投递简历第二天就收到了一面面试电话。
一面电话面
问的问题比较多,涉及到的知识面也比较宽泛。可能和我的简历有关吧,阿里教我做人。面试官很和善,面试了30min。
-
自我介绍一下吧
-
先说一下你在大学里做过哪些项目
-
HTTP2和HTTP1的区别是什么?
-
设计一个登陆页,应该用HTTP的什么Method去提交请求?除了用Post,在传输的过程中还要注意什么?
-
如果用户没有登录就去访问一个有登录限制的网页,应该返回什么状态码?(应该是401,403是登录但没有权限拒绝服务)
-
了解restful吗?介绍一下
-
HTTPS为什么比HTTP安全?
-
在写html时script和link标签的位置会刻意放在开头或结尾,这是为什么?
-
设计一个三栏式页面,左边栏和右边栏固定200px,中间可以缩放,你怎么实现?
-
实现一个旋转的loading动画
-
在使用promise时如何处理错误?(.catch)除了.catch呢?
-
如何串行的调用a(),b(),c()三个function,用Promise怎么写?并行呢?
-
介绍一下后端开发中常用的框架
-
解释一下MVC?MVC和MVVM的区别?
-
Vue中更改了一个数据,到更改渲染到页面上,经历了哪些步骤(回答的双向绑定和虚拟DOM-diff的相关内容)
-
假设有一个树形Object,存储着好几层、不同的数据内容。设计一个搜索Object的算法,在尽可能快的情况下找出所有和关键字有关的内容(吐血,好难,这啥,不会)
-
Polyfill一个class(用es5的内容实现es6的class,包括继承之类的)(回答的闭包+原型链,但是忘了如何用原型链实现继承了)
-
看如下代码,输出
new Promise( resolve => { resolve(); }).then( message => { console.log("hello"); setTimeout(() => { console.log("world"); }, 0) })
笔试
笔试是一面完当天做的,一共两道题,2hours,到最后第二道题差一点调试完。
-
(基础版)给你一段xml,xml标签中没有attribute,结构单一,不存在标签不匹配。把它解析成json(json格式已经给定),用js实现。
<list> <item>content1</item> <item>content2</item> <item>content3</item> <item> <name>hema</name> <value>frontend</value> </item> </list>
{ tag: 'list', children: [ { tag: 'item', children: 'hello world' }, { tag: 'item', children: 'content2' }, { tag: 'item', children: 'content3' }, { tag: 'item', children: [ { tag: 'name', children: 'hema' }, { tag: 'value', children: 'frontend' } ] } ] }
-
(增强版)xml中携带attr,时间复杂度要求O(n),异常处理:针对标签未闭合情况, 能报出异常信息
二面电话面
一面完成后的第三天晚上收到面试通知,第四天下午两点面试。
- 为什么选择了前端这个岗位
- 你刚才提到了前端的新技术的产生是比较快的,从你开始学到现在,你接触了哪些新的东西
- 讲一下你笔试的时候的思路吧,你的代码为什么这样写
- 介绍一下你印象最深的项目吧,为什么对这个项目印象深刻
- 你提到了Vue的一些原理性的东西,你能具体介绍一下吗?
- 能详细说明一下computed计算属性缓存是怎么设计的吗?为什么要这样设计? 然后就开始从这个项目出发问了一系列的问题:你现在写到的xx系统,前端后端数据库都是怎么设计的?如果让你设计某一个系统,在前端、后端、数据库方面,你怎么来设计?
- 你还有什么问题问我们吗?(部门的常用技术栈有哪些?)
答:阿里是React的天下,Vue用的比较少,平常会用weex之类的写pc、app给中后端使用,前端消费者使用的是另一个部门开发的。
三面电话面
二面完成之后的第三天下午,24min
就是大致讲一下OnlineJudge项目的核心部分,不一定是前端,后端之类的都可以。然后让我好好准备后面的四面、交叉面和hr面
四面电话面
短信预约的,在提前批面了三面之后终于入了系统,做了素质测试后一星期收到四面面试短信
还是聊项目,每个功能可能问的比较深,会问到一些关于上线之后生产环境的隐患问题有没有考虑。再就是问了感兴趣的方向,对于团队的技术栈有没有什么期望。一共45min左右。
五面交叉面 电话面
音质有点不好,听起来比较费劲
感觉从三面开始,或者说从二面开始的内容就差不多一样了,没有什么特别问题,就是一直在聊项目,询问技术栈之类的。时常30min左右。
美团点评
内推提前批,投递简历两天后面试官联系,一周后开始一面。
一面电话面
面试官很好,没有问的很紧,每个问题之间会有一定的缓和时间,一共持续了20min。上来表明希望招到的都是能留下来工作的,问了大四能不能在那里实习。这次面试就是提前了解一下情况,因为是提前批,后面招聘正式开始后会按照正常的流程再走一遍。
- 基础的了解情况,介绍自己项目,实习时间,Vue、ts、node、webpack以及后端语言的掌握情况
- css布局去实现一个九宫格布局(每行最多三列,wrap的向下排)
- 介绍一下DOM事件模型
- 考察事件委托,为什么使用事件委托
- es6的map类型使用过吗?那你平常用es6的哪些语法?
- 你还有什么问我们的问题吗?(部门用到的技术栈是什么?Node是必需的吗?)
答:vue和react都用到,自己的部门用react比较多,平常我们还会用js的相关内容去开发移动端app之类的。自己的部门全员node,但是对于实习来说不是必须的。
笔试
笔试开始前五天收到通知,说要五天后晚上7:00笔试,笔试是统一的在赛码(好像是叫这个网站)上,要开摄像头什么的。
不允许泄题,那就不说题目是什么了,总之算法题型,然后做得也不好最后估计只有36分左右(满分100)。 整体难度的话:ACM铜及以上吧。
二面视频面
笔试之后大概一个星期
就是一些开放性问题,聊项目啊之类的,个人性格之类的。比较特别的问题有以下几个:
- js的垃圾回收机制了解过吗?没了解过的话你类比c++的垃圾回收机制,你猜测以下他是什么样一个机制,或者说让你去设计一个js的垃圾回收机制的话你怎么去设计
- 前端一直使用js,但是为什么最近开始ts了呢?你认为公司为什么会去倾向使用js
- 你在项目里用sass的场景是什么,用到了哪些内容
- 关于oj ranklist页面的开发聊了比较多,比如vue生命周期,轮询,在beforeMount处理数据的时候用户会看到一个白屏,你怎么去提升用户的体验。
- 值得一提的是我最后问部门是一个什么样的技术栈,除了常用的前端技术栈外,居然还有java、mysql、redis的技术栈
腾讯微信公众号
内推,投递简历第二天联系了笔试。我投的腾讯音乐,结果是WXG的人来找我
笔试
腾讯文档上面一个word上面写,4个题,一个小时
- leetcode原题第二题
- 给一棵不完全二叉树,每个节点都有一个值。不能拿相邻节点的值,问在这棵树上最大能拿多少
- 树的diff,html解析能否用上述算法,优化方案是什么
- leetcode原题,两个有序序列二分找中位数
一面电话面
笔试完了接着打电话过来一面了,1hour,面试官感觉还可以,会引导你去想一些问题,每个问题刨根问底也问的比较深
- 回顾一下刚才笔试的四个题,为什么这样做,你写的算法缺点在哪里,怎么改进
- 自我介绍一下
- 什么时候接触前端的?你前端是怎么学的,有没有系统的听过课或者看过书来学?
- 你简历上写了很多东西,你最常用的是什么?(Vue)
- Vue的双向绑定,如果for i in range(0,100)改变a,那么
{{a}}
里面是怎么渲染的。
答:可能只看到99
如果让你来写你怎么让他只看到99
答:防抖
那么如果你是框架设计者,我是框架使用者,我就是想让用户看到0-99变化的这个过程,你该怎么改变你的框架?你这里掌握的不太好,你回去再看一下
(后面看了一下,这是“异步更新队列”。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。用宏任务可以让页面出现变化的过程。因为宏任务不会接着执行下一个宏任务,中间穿插了对页面的渲染。) - Vue-router是怎么实现的?
- 假设两个组件a和b,我从a->b,这个时候我又点了一下回退,返回到了a,这里需要注意什么?
- 针对上个问题,给个业务场景,这个页面很长,用户滚动条拖的很下面,你怎么保证返回的时候能重新定位在这里?(把scrollTop存下来,返回的时候卡看有没有相关的存储,有的时候设置一下scrollTop为存储值)那你存储用什么样的数据结构去存储?Vue-router你还需要再了解学习一下
- 你有没有看过Vue源码,讲一下你看过的部分
- SaSS和TypeScript,React掌握的怎么样?
- 问一个CSS,用一个div和css画一个等腰直角三角形
- 再问一下浏览器相关,从在浏览器里面输入一个URL到看到界面,发生了什么?(网址)
- 针对上个问题,详细说一下DNS?DNS服务器在哪里?
- 一个html页面,head里面有10个css,页面底部10个js,每个下载都需要10s。下载完css多长时间?下载完js多长时间?
- 从服务器返回到浏览器解析这一部分,详细说一下。服务器怎么保证返回的是浏览器想要的?(nginx)那么假设nginx出了bug,返回了一个视频/图片,浏览器是否能解析它?浏览器怎么检测这个文件是什么类型的?
- 上面说的20个文件,在http1.1下简历了多少个tcp链接?你http这一块不太好回去好好学
- 安全问题接触过吗?XSS和CSRF?(了解过XSS)
- 详细说一下XSS,为什么会出现XSS问题,怎么防范?
- 你的项目里是如何请求内容的?XHR用过吗?Ajax用过吗?jQuery用过吗?你怎么避免你用的fetch的兼容性问题?
- es6里面的module用过吗,如果让你生成一个依赖关系,你怎么写?
- 学校里都学了什么课程?英语怎么样?数学怎么样?说一下操作系统的段存储和页存储?
- 编译原理说一下什么是词法解析什么是语法解析?说一下你写过的XML解析器是怎么写的
- 你linux和类linux的操作系统的命令掌握的怎么样?
- 我看你博客大多都是算法竞赛内容,为什么?说一下常用的排序有哪些?介绍一下希尔排序?
- 我看你博客里面写了想考研?(不不不,现在不想)
- 说一下你觉得你的优势在哪里
- 说一下你的兴趣爱好?
第二次笔试
好神奇,也没有换部门,一面笔试完了二面又带个笔试。一面完之后两天给通知,约第三天下午笔试+面试。
- 将字符串解析一个成一个整数(32位,保证输入合法),如果溢出返回0
- 快速排序,讲一下复杂度
- 两个二叉树合并为新的二叉树
- 给一个数组,将数组向右移动k个位置,用尽可能多的解法
- leetcode原题,一段字符串,求最长不重复子序列,只要长度。
二面电话面
面试之前还进行了第二次笔试
- 看了一下笔试内容,讲一下笔试。针对第2题讲一下怎么去避免最差时间复杂度(没答上来),针对第4题引导了一个新的解法
- 介绍一下自己
- 你有过acm经历是吧,你说一下你acm获奖情况,在队伍里都承担什么任务?
- 那你说一下图论的相关内容吧
- 讲一下Vue的特性
- Vue的双向绑定以及观察者模式
- Vue的异步更新队列(我说上个面试官问了,没答上来,下去看了一下,把下来看的内容给他讲了一下
- 那你说一下上个面试官还问了什么问题你没答上来下去又看了的
(答:一个页面十个css十个js那个 - 上个问题涉及到了计算机网络的http,深究了一些http的东西。
- 介绍http2和http1的区别
- tcp的拥塞控制
- http1下,有多个小图片,你怎么去优化(雪碧图
- 说一下你在学校里学了什么课程,什么最有把握,我说操作系统和编译原理
- 问了一些操作系统的问题(一个都没答上来
- 那这样吧你自己讲一个操作系统的点(讲了个页面储存替换算法
- 你还有什么问题问我吗?
(部门技术栈是什么?
答:你通过了的话让后面的面试官给你讲吧,我不是前端组的,不是很了解
HR视频面
二面当天十几分钟后系统就显示通过了,三天后接到HR面试邀请,第四天下午进行视频面试,平台是腾讯会议。
就聊了一下性格、爱好、学校内做的一些事情,现在的状况,实习的安排,没有什么特别值得说的。然后说下周会有offer的沟通,保持电话畅通。
字节跳动
投的前端开发实习-教育业务,从暑期实习被调到日常实习,但是不知道区别是什么,影响不大
一面视频面
投递简历一星期后收到电话,约第三天下午视频面试,平台是牛客网。
总体来说,一共接近一个小时,体验很好,但是觉得自己回答的不太行,猜测是一面挂。期间牛客网评测出现了一次问题,调了半天代码没动静,还以为是我写的问题。
- 介绍自己,为什么选择前端,写过什么项目?
- 说一下tcp,udp的区别和分别的使用场景
- 从输入url到展示页面有哪些过程用了udp
- https有了解吗?介绍一下如何交换密钥
- 说一下get和post的区别
- 介绍一下tcp的三次握手四次挥手,为什么要三次握手、四次挥手?
- http的keep-alive见到过吗?(见到过,但不会)那http状态码有哪几种?
- 301,302的区别?304是什么?
- 说一下协商缓存
- 说一下es6的数据类型(一紧张忘记了一个Boolean)
- 实现一个判断是不是Array的function
- 实现一个判断是不是空Object的function
- 实现一个数组拍平(这里牛客网评测机坏掉了)
- 实现一个regex风格替换function(<%= 123 %>替换为{{ 123 }},不太会regex没写出来)
- 实现一个debounce(突然就忘记怎么写了,干)
- 闭包接触过吗?介绍一下闭包的特点和缺点?有什么使用场景?介绍一下你自己写过的闭包
- 你平常http请求用什么?(fetch)
- 能自己实现一个fetch吗?(???完全不会)
- 那你能给fetch加一个abort函数吗,终止请求(???)
- 那你了解Promise的all和race嘛?你能自己实现一个Promise.race嘛?
- 介绍一下css盒模型
- 说一下box-sizing各个参数和含义
- 说一下html有哪些语义化标签(nav,footer之类的,没用过)
- 实现一个add(leetcode第二题原题)
- 序列化一个json,序列化为数组,每个数组元素要携带层级
- 你实习能实习多长时间?从什么时候开始?
- 你还有什么问题问我吗?(技术栈:react,有的业务部门用node)
米哈游
笔试
第一批笔试,依旧不允许外传题目。做的不理想有点崩溃。
微软苏州STCA
内推,没有笔试 面试流程据说是IC1、IC2任何一轮通过都会进入到Lead面,然后Offer
IC1面视频面
视频面,平台是Ms Teams,但是面试官不开视频。然后就聊了几个问题,就开始写题,题目是在线平台上写的,只能用plain text,没有高亮不能编译,但是要尽可能的去保证能编译通过并运行。面试官说话中英混杂,据说因为很多同事不说中文。
- 自我介绍
- 你在大学里做了什么项目,项目的难点是什么,怎么克服
- 洛谷P1434滑雪 dfs+记忆化,要求一次性实现最优解
- 滑雪·改,改成一维,要求时间O(n),但不允许用额外空间
- 你有什么问题吗?
问:实习的内容,技术栈
答:(含义查不多,具体怎么说的记不清了)Intern期间大概率给一个额外的Project,这个Project也会很有challenge。不会去触碰业务线上的项目,因为出一个错误就损失几个亿...技术栈的话很多,做什么的都有。
Lead面视频面
收到面试邀请邮件,邮件上写的Philippines, Manila,不是China就很恐怖,很怕是英文面. 结果是English的introduce yourself,其他都是中文
- introduce yourself
- 随机向BST中插入N个random数,返回根节点
- checkBalance函数
- 写个函数让他平衡,可以使用额外空间
- 如果不使用额外空间怎么做?有几种情况?
- 有什么要问我的吗?