前端面试题(实习篇)面试字节跳动深圳-一面二面

面试总结

摘要

这是我学习前端以来的第一次面试,挂在了二面实现一个具体项目需求上面;有遗憾,也有收获,总体感觉还是收获更大,知道了大厂面试的流程是怎么个样子,为今后的面试提供了宝贵的经验 ;同时也意识到一定要多刷面试题,这不仅仅是为了面试,更是能够拓宽知识面;平时也一定要自己亲手写代码,并且保证效率.

笔试

笔试题我并没有做的非常好,尤其是react实现组件封装,本来可以花更多的时间去实现要求的,可是受到了不可抗力因素的影响,实现需求的解决方案是想到了的,知道需要使用哪些api,但是很多代码都并不是自己手写的,而是先百度借鉴了一番;

一面

当一开始收到字节的邀请面试邮件时,我因为怕误操作就没有点开来看,结果在第二天第一轮面试前十分钟才看到邮件说要添加hr的微信,当时瞬间就慌了,以为已经失去了这一次的面试机会,幸好等到了面试官的视频面试邀请;面试官非常的亲切,会用疑问来提示我的错误,此外,他也会对我的一些解答进行追问,问我还有其他的答案,其他的解决方案;总体上对于面试官的问题我都能回答两个点及以上,并且当场写代码也可以基本实现要求,只是有一些属性会忘了怎么拼写(vscode的自动补全给惯的),然后有一些问题给出了自己的答案却并没有给出理由有一些回答也是因为不是非常清楚随便猜,没有跟面试官说这个问题不是非常熟悉理解,之前没有去想过之类的回答;一面是考察的基本上都是基础,我在面试前也刷了面试题,所以总体让面试官还是满意的,在最后一个环节面试官问我还有什么问题要问的时候,我问他公司前端开发的人数以及今后如果入职的晋升,结果他说他只能解答技术上的问题,其他的问题要问hr;面试持续了45分钟左右,面试完就安排了两个小时后的二面

二面

二面以为就是hr面,结果还是技术面,并且没有让我自我介绍,一上来就是让我实现一个九宫格;面试官让我先实现一个每个格子都是正方形的九宫格,接着实现一个全屏幕正方形的九宫格;我先后使用了table,div来基本实现,不过感觉面试官都不是非常满意,当我提出使用栅格布局来实现时,面试官说栅格布局考虑到兼容性不可以使用;接着让我实现从后台请求数据,对应到九宫格的哪一个数字,那么该数字的背景就标红,我先说出了我的思路,然后就开始用代码实现,结果因为忘了js的一个api,导致代码写了很久,网络请求使用axios也被面试官说我写错了;整场面试持续了四十分钟,以写代码为主,总体表现是不及格的,我并没有使用面试时的网站来写代码,而是让面试官允许我用vscode,结果还是因为代码写的慢js基础知识部分不熟悉异步网络请求不熟悉,导致二面直接终结了我实习的机会。

所有笔试和面试都是在网络上进行

笔试

笔试有三道题

  • 第一题

给出了六张图片,要求制作出指定静态页面,使用响应式布局,并且要适配各种分辨率的移动端屏幕

我给出的方案是使用媒体查询,根据的是google浏览器所列出的几种手机类型来进行适配

  • 第二题

分别使用react和vue来封装一个多选框组件,要求要有一个全选框

因为我学的框架是vue,所以用vue封装的还算顺利,然而我由于从来没有接触过react,所以马上看B站视频恶补了一下,然后github了一个类似代码改了一下样式,并没有实现全选框功能

  • 第三题

使用CSS实现dialog

实现思路步骤

  1. 首先把包含弹出按钮和dialog会话框的静态页面绘制出来
  2. 使用position:fixed;bottom:-50px把dialog会话框隐藏在页面之外
  3. 使用dom0的事件监听方法监听弹出按钮事件,并传值true:onclick="toggleDialog(true),同理监听dialog上关闭按钮事件,传值false
  4. 使用三元表达式通过接收true或者false来添加不同的类选择器及其样式,该样式是点击弹出按钮或者关闭按钮之后会话框的终点状态
  5. 会话框弹出使用transition来过渡,会话框关闭使用animation来进行进行过渡
  6. 点击按钮的水波纹效果是直接百度的代码,几乎没有做任何的修改

源码如下:

<!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 undefinedtypeof null的值分别是什么

在这里插入图片描述

12:说一下你了解的盒模型有哪些?有什么区别?
13:box-sizing:content-boxbox-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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值