前端面试题(实习篇)面试字节跳动深圳-一面二面
面试总结
摘要
这是我学习前端以来的第一次面试,挂在了二面实现一个具体项目需求上面;有遗憾,也有收获,总体感觉还是收获更大,知道了大厂面试的流程是怎么个样子,为今后的面试提供了宝贵的经验 ;同时也意识到一定要多刷面试题,这不仅仅是为了面试,更是能够拓宽知识面;平时也一定要自己亲手写代码,并且保证效率.
笔试
笔试题我并没有做的非常好,尤其是react实现组件封装,本来可以花更多的时间去实现要求的,可是受到了不可抗力因素的影响,实现需求的解决方案是想到了的,知道需要使用哪些api,但是很多代码都并不是自己手写的,而是先百度借鉴了一番;
一面
当一开始收到字节的邀请面试邮件时,我因为怕误操作就没有点开来看,结果在第二天第一轮面试前十分钟才看到邮件说要添加hr的微信,当时瞬间就慌了,以为已经失去了这一次的面试机会,幸好等到了面试官的视频面试邀请;面试官非常的亲切,会用疑问来提示我的错误,此外,他也会对我的一些解答进行追问,问我还有其他的答案,其他的解决方案;总体上对于面试官的问题我都能回答两个点及以上,并且当场写代码也可以基本实现要求,只是有一些
属性会忘了怎么拼写(vscode的自动补全给惯的),然后有一些问题给出了自己的答案却并没有给出理由,有一些回答也是因为不是非常清楚随便猜,没有跟面试官说这个问题不是非常熟悉理解,之前没有去想过之类的回答;一面是考察的基本上都是基础,我在面试前也刷了面试题,所以总体让面试官还是满意的,在最后一个环节面试官问我还有什么问题要问的时候,我问他公司前端开发的人数以及今后如果入职的晋升,结果他说他只能解答技术上的问题,其他的问题要问hr;面试持续了45分钟左右,面试完就安排了两个小时后的二面
二面
二面以为就是hr面,结果还是技术面,并且没有让我自我介绍,一上来就是让我实现一个九宫格;面试官让我先实现一个每个格子都是正方形的九宫格,接着实现一个全屏幕正方形的九宫格;我先后使用了table,div来基本实现,不过感觉面试官都不是非常满意,当我提出使用栅格布局来实现时,面试官说栅格布局考虑到兼容性不可以使用;接着让我实现从后台请求数据,对应到九宫格的哪一个数字,那么该数字的背景就标红,我先说出了我的思路,然后就开始用代码实现,结果因为忘了js的一个api,导致代码写了很久,网络请求使用axios也被面试官说我写错了;整场面试持续了四十分钟,以写代码为主,总体表现是不及格的,我并没有使用面试时的网站来写代码,而是让面试官允许我用vscode,结果还是因为
代码写的慢,js基础知识部分不熟悉,异步网络请求不熟悉,导致二面直接终结了我实习的机会。
所有笔试和面试都是在网络上进行
笔试
笔试有三道题
- 第一题
给出了六张图片,要求制作出指定静态页面,使用响应式布局,并且要适配各种分辨率的移动端屏幕
我给出的方案是使用媒体查询,根据的是google浏览器所列出的几种手机类型来进行适配
- 第二题
分别使用react和vue来封装一个多选框组件,要求要有一个全选框
因为我学的框架是vue,所以用vue封装的还算顺利,然而我由于从来没有接触过react,所以马上看B站视频恶补了一下,然后github了一个类似代码改了一下样式,并没有实现全选框功能
- 第三题
使用CSS实现dialog
实现思路步骤
- 首先把包含弹出按钮和dialog会话框的静态页面绘制出来
- 使用
position:fixed;bottom:-50px
把dialog会话框隐藏在页面之外 - 使用dom0的事件监听方法监听弹出按钮事件,并传值true:
onclick="toggleDialog(true)
,同理监听dialog上关闭按钮事件,传值false - 使用三元表达式通过接收true或者false来添加不同的类选择器及其样式,该样式是点击弹出按钮或者关闭按钮之后会话框的终点状态
- 会话框弹出使用
transition
来过渡,会话框关闭使用animation来进行进行过渡 - 点击按钮的水波纹效果是直接百度的代码,几乎没有做任何的修改
源码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>弹框动画</title> <style> button { padding: 7px 10px; border: none; outline: none; } .open-btn { background-color: #00bfff; color: #fff; border-radius: 3px; box-shadow: 0px 1px 5px #808080; } .open-btn:hover{ box-shadow: 0px 2px 5px #808080; } .ripple-btn .waves-animation { position: absolute; border-radius: 50%; width: 25px; height: 25px; opacity: 0; background: rgba(255, 255, 255, 0.3); transition: all 0.7s ease-out; transition-property: transform, opacity, -webkit-transform; -webkit-transform: scale(0); transform: scale(0); pointer-events: none; } .dialog { width: 350px; border-radius: 3px; position: fixed; bottom: -50px; right: 30px; box-shadow: 0px 0px 15px #dcdcdc; opacity: 0; visibility: hidden; } .content { padding: 16px 12px; font-size: 12px; } .dialog-footer { display: flex; justify-content: flex-end; margin-right: 10px; padding: 5px 0 7px 0; } .dialog-footer > button:nth-child(1) { margin-right: 10px; background: none; color: #00bfff; } .dialogslipUp { transition: 1s; width: 350px; border-radius: 3px; position: fixed; bottom: 250px; right: 30px; box-shadow: 0px 0px 15px #dcdcdc; opacity: 0.8; z-index: 2000; } .dialogslipBottom { /* transition: 0.5s; */ width: 350px; border-radius: 3px; position: fixed; bottom: -50px; right: 30px; box-shadow: 0px 0px 15px #dcdcdc; opacity: 0; animation-name:dialogFaceSlipToBottom; animation-duration: 1s; } /* 会话框消失动画 */ @keyframes dialogFaceSlipToBottom{ 0%{ bottom: 250px; opacity: 1; } 25%{ bottom: 300px; opacity: 0; } 50%{ bottom: 450px; } 75%{ bottom: 100px; } 100%{ bottom: -50px; } } </style> </head> <body> <!-- 打开会话框按钮 --> <button class="open-btn ripple-btn" onclick="toggleDialog(true)">SHOW AGAIN</button> <div class="dialog" id="dialog"> <div class="content"> This could be a great way to display an ad using Materialize! </div> <hr /> <div class="dialog-footer"> <!-- 会话框关闭 --> <button onclick="toggleDialog(false)" id="closed" class="ripple-btn">No THANKS</button> <button class="open-btn">YES PLEASE</button> </div> </div> </body> <script type="text/javascript"> function toggleDialog(show) { var animationClass = show ? "slipUp" : "slipBottom"; var closed =document.getElementById('closed') var animation = function () { dialog.className = "dialog" + animationClass; }; if(animationClass === "slipBottom"){ closed.setAttribute('style','background-color:#dcdde1;') } else if(animationClass==="slipUp"){ closed.style.background='#fff'; } setTimeout(animation, 100); } // 点击出现水波纹 document.addEventListener( "DOMContentLoaded", function () { var duration = 750; // 样式string拼凑 var forStyle = function (position) { var cssStr = ""; for (var key in position) { if (position.hasOwnProperty(key)) cssStr += key + ":" + position[key] + ";"; } return cssStr; }; // 获取鼠标点击位置 var forRect = function (target) { var position = { top: 0, left: 0, }, ele = document.documentElement; "undefined" != typeof target.getBoundingClientRect && (position = target.getBoundingClientRect()); return { top: position.top + window.pageYOffset - ele.clientTop, left: position.left + window.pageXOffset - ele.clientLeft, }; }; var show = function (event) { var pDiv = event.target, cDiv = document.createElement("div"); pDiv.appendChild(cDiv); var rectObj = forRect(pDiv), _height = event.pageY - rectObj.top, _left = event.pageX - rectObj.left, _scale = "scale(" + (pDiv.clientWidth / 100) * 10 + ")"; var position = { top: _height + "px", left: _left + "px", }; (cDiv.className = cDiv.className + " waves-animation"), cDiv.setAttribute("style", forStyle(position)), (position.transform = _scale), (position.opacity = "1"), (position["transition-duration"] = duration + "ms"), (position["transition-timing-function"] = "cubic-bezier(0.250, 0.460, 0.450, 0.940)"), cDiv.setAttribute("style", forStyle(position)); var finishStyle = { opacity: 0, "transition-duration": duration + "ms", "-webkit-transform": _scale, "-moz-transform": _scale, "-ms-transform": _scale, "-o-transform": _scale, top: _height + "px", left: _left + "px", }; setTimeout(function () { cDiv.setAttribute("style", forStyle(finishStyle)); setTimeout(function () { pDiv.removeChild(cDiv); }, duration); }, 100); }; document.querySelector(".ripple-btn").addEventListener( "click", function (e) { show(e); }, !1 ); }, !1 ); </script> </html>
一面
1. 自我介绍
因为应聘的岗位对react框架更加的侧重,而我之前做的项目使用的框架都是vue,所以在介绍的时候我是这样说的:我开发过XXX和XX这两个项目,虽然用到的框架都是vue,但是我认为这里所要求的个人能力特质都是相同的,都需要对HTML,CSS以及JS有一定程度的了解,并且熟悉前后端分离开发;接着我还讲了平时对于HTML,CSS以及JS的笔记以及示例代码积累非常多
2. 了解垂直居中吗?说一下你知道的实现垂直居中的方法
回答:
垂直居中我了解几种,首先我在平时项目当中最经常用到的就是
display:flex了,如果要对某一个元素进行垂直居中,那么就在父元素上使用
display:flex; justify-content:center; align-items:center;
当然也会用到
position:absolute,它是直接在要垂直居中的元素上使用即可
position:absolute; left:50%; top:50%; transform:translate(-50%,-50%)
也可以
position:absolute; top:0; bottom:0; left:0; right:0; margin:aut
如果是知道元素宽高的情况下,可以
width:200px; height:200px; position:absolute; top:50%; left:50%; margin-left:-100px; margin-top:-100px;
JS实现也可以作为一个了解
let HTML=document.documentElement winW=HTML.clientWidth; winH=HTML.clientHeight; boxW=box.offsetWidth;//box是要居中元素的id boxH=box.offsetHeight; box.style.position='absolute'; box.style.left=(WinW-boxW)/2+'px' box.style.top=(WinH-boxH)/2+'px';
3:说一下块级元素和行内元素的区别
1:块级元素独占一行,而行内元素不行
2:块级元素可以设置宽高并且会自动填充满父元素,而行内元素不行
3:块级元素可以设置margin和padding,而行内元素不行
4:display有哪些属性值,说说他们的特点
display:block;-----可以把行内元素转化为块级元素
display:inline-block------把行内元素转换为行内块元素,虽然不能独占一行,但可以设置宽高
display:none--------让元素消失,不占用页面位置
5:var,let和const的区别
1:let和const是ES6才有的api
2:let和const声明的是块级作用域,比如{},if以及for,而var的作用域是全局,举一个例子:
for(let i=0;i<3;i++){ console.log(i) } console.log(i)
因为i是用let声明在for块级作用域里面,所以在for循环外面打印i就会提示错误,表示i没有被定义
如果使用var声明的话,在for块级作用域外面依旧可以访问到i,虽然输出的范围是0~2之间,但是循环还会再运算一次i=i+1
3:var存在声明提升
首先我们来看一下使用三种变量声明方式去声明一个变量,并不赋值,结果会是怎样
浏览器输出:
实际代码输出:
浏览器调试台只有let会打印出undefined,剩下两个都是直接报错;而使用实际代码,let和var输出结果都是undefined,const直接报错,因为
const在一开始声明的时候就要马上初始化赋值,否者就会报错
接着我们来了解一下作用域:作用域在ES5是只有全局作用域和函数作用域两种,而且如果在函数内部声明的变量,名字与全局变量相同,那么函数就会根据就近原则接收函数内部的变量
那么什么是声明提升呢?
Javascript引擎的工作机制是先预解析一遍代码,获取所有被声明的变量和函数声明,然后再一行一行的执行,这就使得所有用var声明变量的语句,都会提升到代码的头部,这就是声明提升
正常情况下,我们直接打印一个没有声明和定义的变量,那么就会报错
而由于var的声明提升,结果却发生了变化,第一次输出打印出来了undefined,说明变量d在这个时候已经被声明了但是没有赋值;
而如果使用let的话,就会直接报错
共同点:都不可以重复声明,但是除了const,都可以再次赋值
4:var具有全局作用域和函数作用域,并没有块级作用域
参考:ES6中let,var和const的区别,var声明与变量提升
6:说一下下面代码的输出结果
for(var i=0;i<3;i++){ setTimeout(function(){ console.log(i) },1000) }
结果是输出三次3
7:用css实现一个三角形
<style> div{ width:0; height:0; border-top:10px solid red; border-bottom:10px solid transparent; border-left:10px solid transparent; border-lright:10px solid transparent } </style> <body> <div></div> </body>
原理:
- . transparent表示颜色透明,类似于raba(0,0,0,0);
- . 当我们设置一个div的宽高,以及border为100px时,显示的结果如下:
- :如果设置height为0会是这样的:
- :自然可以知道再设置width为0的话,就会出现四个三角形:
- :那么如果我们需要一个三角形此时就非常简单了,只需要隐藏其它边框就行了,这是就要用到
transparent
属性了
总结来说就是利用了border边框的特性来实现三角形
8:实现一个正方形的无限旋转
<style> div{ width: 50px; height: 50px; background-color: teal; animation-name: cicle1;//设置关键帧的名字 animation-duration: 1s;//设置完成一次动画的时间 animation-iteration-count: infinite;//设置动画无限执行 animation-timing-function: linear;//设置过渡速度保持稳定 } @keyframes cicle1 { from{ transform: rotate(0deg); } to{ transform: rotate(360deg); } } </style> </head> <body> <div></div> </body>
9:说一下各种选择器及其权重如何
!important>
内联选择器(行内样式)>
id选择器>
类选择器|属性选择器|伪类选择器>
元素选择器(标签)>
*(通配符)
规则 | 权重 |
---|---|
行内样式 | 1000 |
id选择器 | 100 |
类选择器 | 10 |
标签 | 1 |
* | 0 |
10:说一下下面代码div的背景颜色
<style> div{ width: 100px; height: 100px; background-color: lawngreen; } .red{ background-color: red; } .blue{ background-color: blue; } </style> </head> <body> <div class="red blue"></div> </body>
当两个选择器的权重相同时,按照选择器的先后顺序来进行规则,后面的选择器样式会覆盖前面选择器的样式,所以div的背景颜色是蓝色
如果此时再加一个id选择器的话,结果又会不同
11:typeof undefined
和typeof null
的值分别是什么
12:说一下你了解的盒模型有哪些?有什么区别?
13:box-sizing:content-box
和box-sizing:border-box
的区别
14:position
都有哪些值,有哪些是脱离了文档流,他们的定位原点在哪?
15:画一个可以自适应屏幕大小的正方形
- 方法一
使用padding
来撑
<style> .box{ width:25%; padding-top:25%;//高度继承宽度 height:0;//避免div里面内容把正方形撑开 } </style> <body> <div class="box"></div> </body>
- 方法二
<style> .box{ width:25%; height:25vw;//vw是相对于视口的宽度,1vw=1% viewport width background:#ccc; } </style> <body> <div class="box"></div> <body>
更多方法参考:正方形自适应的几种方法
16:怎么实现表格的单数行和双数行?
方法一使用nth-child(odd)和nth-child(even)
table{ border: 1px solid #999; border-collapse: collapse;//去除td之间的间隔 } tr:nth-child(odd){//管理偶数行 backgroundcolor:red; } tr:nth-child(even){//管理奇数行 backgroundcolor:green; }方法二
使用nth-child(2n+1)和nth-child(2n)
table{ border:1px solid #999; border-collapse:collapse; } tr:nth-child(2n+1){//管理偶数行 background-color:green; } tr:nth-child(2n){//管理奇数行 background-color:red; }
第一种方法的奇数偶数计数是从th开始的,第二种方法的奇数偶数行计数是从tr开始的
17:js有哪些数据类型
基本类型:String Number Boolean Undefined Null Symbol 引用类型:Object Function Array
18:slice和splice的区别
19:说一下怎么解决跨域问题
20:说一下使用git的基本命令,把创建本地仓库到把一个分支上传到服务器的所有命令都说一说
二面
实现一个可以自适应手机屏幕的正方形九宫格,并且实现从后台请求数据,如果数据对应上了九宫格的某一个数字,该数字的背景就变红的随机抽奖demo
- 亲历腾讯WEB前端开发三轮面试经历及面试题
- 前端面试:精选经典面试题(二)
- 前端面试:精选经典面试题(七)
- 最新Web前端,Java web经典面试试题及答案-史上最全前端面试题(含答案) java web , web .html .bootstrap,jQuery
- 前端面试--四月二十家前端面试题分享
- 前端面试:精选经典面试题(二十五)
- 前端面试:精选经典面试题(二十八)
- 前端面试:精选经典面试题(十一)
- 前端面试:精选经典面试题(四十九)
- 2018最新Web前端经典面试试题及答案 JavaScript面试题
- 2019年底前的web前端面试题初级-web标准应付HR大多面试问题
- 前端面试整理<特别多,耐心看基础面试题部分基本没有问题了!!!>
- 阿里巴巴前端面试parseInt()函数的面试题
- 前端面试:精选经典面试题(四十二)
- 前端面试:精选经典面试题(二十二)
- 前端面试:精选经典面试题(三十五)
- (史上最全)Web前端面试试题大全及答案汇总(之篇二JavaScript基础笔试面试题)
- 2019年底前的web前端面试题初级-web标准应付HR大多面试问题
- 面试稳了!集齐几千名程序员精选的 100 道前端面试题!
- 如何准备一次技术面试(附一套前端面试题)