前端开发实习生面试总结

个人感觉面试官对实习生还是很友好的,大部分时候你答不上来都会引导你,最后还会点评你的不足,评价出来的那些问题确实是我自己的短板!所以在整个过程中还是学到了很多!!
本人坐标南京,南京投的相对较多,不过其他地方也投了。我投的基本都是没太有名气的小公司,常听的那些BAT等大厂有机试而我算法很差,所以想找个小公司体验一下。一般都会先让介绍自己介绍项目,然后开始技术提问。现在总结一下我投的几家公司被问到的技术


公司一

base南京,100人左右的小公司,现场笔试,实习薪资150-180/天


笔试题目

  • HTTP

1. 请简述HTTP中get、post、put和delete的内容以及之间的区别。

方法功能
get在服务器上查询数据并返回
post增加新的资源或者修改已有资源
put修改已有资源
delete请求服务器删除指定内容

get和post的区别
安全性:get的安全性低于post。因为get参数通过 url 传递,而post的参数放在 Request body 中。以url传递参数的方式:以?分割url和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。可见传递的数据是直接暴露在url中。
数据大小:由于get的参数是放在url中进行传递,而大多数浏览器对于url的处理长度有所限制,基本是2K个字节。而post是将参数放在Request body中,可以传输的数据达到上百K。
tcp数据包:get发送一次数据包,post发送2次数据包。对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
get和post的区别还有很多,我这里放几个最主要的,其它的读者可以自行查阅。

2. 请简述HTTP常见的状态码及其含义(至少写出5个)

类别含义
1XX信息类
2XX成功
3XX重定向
4XX客户端错误
5XX服务器错误

常见状态码:

状态码状态码英文名称含义
100Continue继续。客户端应继续其请求
101Switching Protocols切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200OK请求成功。一般用于GET与POST请求
204No Content请求处理成功,但没有任何资源可以返回给客户端,一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。
206Partial Content部分内容。服务器成功处理了部分GET请求
301Moved Permanently永久性重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302Found临时性重定向。与301类似,但资源只是临时被移动。客户端应继续使用原有URI
303See Other查看其它地址。与301类似。使用GET和POST请求查看,303状态码和302状态码有着相同的功能,但303状态码明确表示客户端应当采用GET方法获取资源,这点与302状态码有区别。
304Not Modified该状态码表示客户端发送附带条件的请求时, 服务器端允许请求访问资源, 但未满足条件的情况。
400Bad Request客户端请求的语法错误,服务器无法理解
401Unauthorized该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证) 的认证信息。
403Forbidden对请求资源的访问被服务器拒绝。
404Not Found服务器上无法找到请求的资源
500Internal Server Error服务器内部错误,无法完成请求
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。

  • HTML

1. 块级元素有哪些?行内元素有哪些?(每种至少写出5个)
块级元素:div p table ul lo li h1-h6 dl dt
行内元素:a img span b strong input select section
空元素:br hr img input link meta

块级元素和行内元素的区别:

序号块级元素行内元素
1总是从新的一行开始,即各个块级元素独占一行,默认垂直向下排列;和其他元素都在一行,即行内元素和其他行内元素都会在一条水平线上排列;
2高度、宽度、margin及padding都是可控的,设置有效,有边距效果;高度、宽度是不可控的,设置无效,由内容决定。
3块级元素中可以包含块级元素和行内元素。根据标签语义化的理念,行内元素最好只包含行内元素,不包含块级元素。

块级元素和行内元素如何相互转化?
使用display属性能够将块级元素、行内元素和行内块元素任意转换:

  • display:inline;转换为行内元素;
  • display:block;转换为块状元素;
  • display:inline-block;转换为行内块状元素。

2. img标签的alt和title有什么区别?
alt属性和title属性相同点:它们都会出现浮层,显示自己设置的图片相关的内容。
alt属性和title属性不同点

  • alt属性:①当图片加载不出来的时候,就会在图片未显示的地方出现一段alt设置的属性内容。这个属性的作用是为了给未加载的图片显示提示信息,即使在网络比较差的时候,用户也可以知道图片的内容,方便用户浏览网页。同时在程序员对网站维护的时候也能更快的查找到问题。②浏览器的搜索引擎可以通过alt属性的文字描述来获取图片。
  • title属性:title属性可以用在任何的元素上,当用户把鼠标移动到元素上时,就会显示预先设置的title的内容,起到对图片说明的作用,实质上就是对图片的解释和备注。

  • CSS

1. CSS选择器优先级是怎样的?important和内联优先级哪个高?
最高到最低顺序为:
① id选择器(#myid)
② 类选择器(.myclassname)
③ 标签选择器(div,h1,p)
④ 子选择器(ul < li)
⑤ 后代选择器(li a)
⑥ 伪类选择(a:hover,li:nth-child)
!important的优先级最高

2. display:none 与 visibility:hidden 的区别是什么?

区别display:nonevisibility:hidden
是否占据空间不占据任何空间空间依旧存在
是否具有继承属性display不是继承属性,元素及其子元素都会消失visibility是继承属性,给父元素设置visibility:hidden;子元素也会继承这个属性。但是如果重新给子元素设置visibility: visible,则子元素又会显示出来
读屏器是否读取读屏器不会读取display:none的元素内容会读取visibility:hidden的元素内容
  1. 如何水平居中div?如何垂直居中div? 这个问题好常见,几乎每场面试都会被问

①水平居中
法一:需要为其设置width、height、position、left、margin-left属性,其中left为50%,position的值除了static之外的都可以,margin-left的值为负数,数值大小为width的一半。

			width:400px;
			height:400px;
			position:relative;
			left:50%;
			margin-left:-200px;
		    display: block;
		    background-color:red;

法二:当前div的display为block,需要为其设置width、height、display、margin属性

		    width:200px;
		    height:200px;
		    display: block;
		    margin:0 auto;
		    background-color:red;

②垂直居中
法一:需要为其设置width、height、position、top、margin-top属性,其中top为50%,position的值为absolute或者fixed,margin-top的值为负数,数值大小为height的一半。

			width: 400px;
   		    height: 500px;
   		    position: absolute;
   		    top: 50%;
   		    margin-top: -250px;
   		    display: block; 
   		    background-color: red;

③水平垂直居中
法一:是上边两种法一的综合,即需要为其设置width、height、position、top、margin-top、left、margin-left属性

			    width: 400px;
			    height: 500px;
				position: absolute;
			    top: 50%;
			    left: 50%;
			    margin-top: -250px;
			    margin-left: -200px;
			    display: block; 
			    background-color: red;

法二:绝对定位法
不确定当前div宽度和高度,采用当前div的父级添加相对定位position: relative;,当前div设置 transform: translate(-50%,-50%);
法三:flex布局+margin: auto:
在父元素中设置display: flex;,当前元素设置margin: auto;
法四:flex布局+justify-content和align-items:
在父元素中设置

display: flex;
justify-content: center;
align-items: center;

  • JS
  1. 关于Promise
const promise = new Promise((resolve, reject) => {
	console.log(1);
	resolve();
	console.log(2);
})

promise.then(() => {
	console.log(3);
})

console.log(4);

写出以上代码的输出结果。
new Promise 里的参数函数,是同步被执行的,故而先输出 1,2。
resolve 后还需要等待进入下一个事件循环。then 把参数函数推入微任务队列,并不直接执行。
输出 4,接着事件循环进入下一轮,输出 3。
所以输出顺序为1,2,4,3
拓展:

  • 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
  • promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
  • then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。
    关于Promise的题目网上还有很多,上边这个是最简单的了,读者可以自己搜搜其它题目做做
  1. 关于map
    [‘1’, ‘2’, ‘3’].map(parseInt)
    写出以上代码的输出结果。
    结果为[1, NaN, NaN],具体解释这位博主讲的很详细https://blog.csdn.net/weixin_44135121/article/details/88050214

  2. 写一个函数,实现数组去重。 不同公司笔试的时候碰见了2次

var arr=[2,8,5,0,5,2,6,7,2];
function unique1(arr){
  var new_arr=[];
  for (var i = 0; i < arr.length; i++) {
     if(new_arr.indexOf(arr[i])==-1){		//indexOf为-1时表示当前值不在新数组
      new_arr.push(arr[i]);
     }
  }
  return new_arr;
}

  • 优化和安全
    1. 如何进行网站性能优化?至少写出5条
    ①减少HTTP请求次数(尽量合并js和css文件、减少独立文件个数)
    ②减少外部脚本的使用,减少DNS查询时间
    ③将CSS放在页面顶端,JS文件放在页面底端( 浏览器会在下载完成全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。如果将 CSS放在其他地方比如 BODY中,则浏览器有可能还未下载和解析到 CSS就已经开始渲染页面了,这就导致页面由无 CSS状态跳转到 CSS状态,用户体验比较糟糕,所以可以考虑将CSS放在HEAD中。
    Javascript则相反,浏览器在加载javascript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此javascript最好放在页面最下面。但如果页面解析时就需要用到javascript,这时放到底部就不合适了。)
    ④减少DOM元素数量(一个复杂的页面意味着需要下载更多数据,同时也意味着JavaScript遍历DOM的效率越慢。)
    ⑤使用gzip压缩网页内容(能够显著减少用户访问网页时的等待时间)

2. CSRF跨站点请求伪造是什么,如何进行防御
CSRF跨站点请求伪造(Cross—Site Request Forgery),攻击者盗用了用户的身份,以用户的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以用户的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
防御:
①验证 HTTP Referer 字段(根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。通常情况下,访问一个安全受限页面的请求来自于同一个网站)
②在请求地址中添加 CSRF Token 并验证(可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。)
③在 HTTP 头中自定义属性并验证(这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便)

面试提问

  1. 有很多人都保持登录状态,如何确保当前的用户是谁,也可以理解对于不同的用户需要展示不同的页面功能,那么如何确定该用户的身份?
    答:服务端要为特定的用户创建了特定的Session,用于标识这个用户,并且跟踪用户,这个Session是保存在服务端的,有一个唯一标识。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。
  2. 听你说部署的时候有下载nginx,能具体说说这个nginx的作用吗?
    ①静态HTTP服务器:Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端。
    ②反向代理服务器:客户端本来可以直接通过HTTP协议访问某网站应用服务器,网站管理员可以在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器。下面的负载均衡、虚拟主机等,都基于反向代理实现。
    ③负载均衡:以上配置会将请求轮询分配到应用服务器,也就是一个客户端的多次请求,有可能会由多台不同的服务器处理。
    ④虚拟主机:例如将http://www.aaa.com和http://www.bbb.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。

剩下的就是看我笔试写的内容,有的地方让我进行解释。

公司二

base南京,1000-9999人的公司,一对一腾讯会议视频面试,实习薪资200-220/天


  1. 自己怎么学习前端技术的?
    我说刚开始是看b站入门,后边熟悉了比较喜欢看文档。老师问有没有看过系统的书籍,我是没有。不过他们还是挺建议去看系统的书籍,最后也建议我可以边看边做笔记。

  2. 自己平时会关注哪些前端技术的博客和网站进行学习?

  3. 说一个最近学到的新的知识

  4. 自己为什么会选择前端开发

  5. html的head里有meta标签,meta标签的用法?里边都有什么属性?
    标签提供关于 HTML 文档的元数据。它不会显示在页面上,但是对于机器是可读的。可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务。
    meta标签常见的有四个属性,分别是name属性、http-equiv属性、content 属性、scheme 属性。
    具体解释如下:
    https://www.php.cn/div-tutorial-417816.html

  6. css选择器的权重关系(这个上边的笔试也有问到)
    !important > 内联样式 > id选择器 > class选择器 > 元素选择器 > 通配符选择器

  7. 怎样通过css实现一个0.5像素的边框线?
    我说直接设置border为0.5,面试官问border可以直接设置小数吗?好问题!我之后查了一下实现方法:通过缩小50%的1px的边框来实现
    ①设定目标元素的参考位置
    ②给目标元素添加一个伪元素before或者after,并设置绝对定位
    ③给伪元素添加1px边框
    ④用box-sizing:border-box属性把边框都包进宽和高里面
    ⑤宽和高设置为200%
    ⑥整个盒子模型缩小为0.5
    ⑦调整盒子模型的位置,以左上角为基准:transform-orgin:0 0;

		.border{
            position: relative;
        }
        .border:before{
            content:'';
            position:absolute;
            border:1px solid red;
            /* webkit-transform-origin: 0 0; */
            -moz-transform-origin: 0 0;		/*兼容火狐浏览器*/
            -ms-transform-origin: 0 0;		/*兼容ie浏览器*/
            -o-transform-origin: 0 0;		/*兼容Opera浏览器*/
            transform-origin: 0 0; 
            /* -webkit-transform: scale(0.5, 0.5); */
            -ms-transform: scale(0.5, 0.5);
            -o-transform: scale(0.5, 0.5);
            transform: scale(0.5, 0.5);
            -webkit-box-sizing: border-box;		/*兼容chrome浏览器*/
            -moz-box-sizing: border-box;
            box-sizing: border-box;
        }
  1. 浏览器从url输入开始到页面加载的过程中都有哪些事情?
    输入url地址
    应用层进行DNS解析
    应用层生成HTTP请求报文
    传输层建立TCP连接
    网络层使用IP协议来选择路线
    数据链路层实现网络相邻节点间可靠的数据通信
    物理层传输数据
    服务器处理反向传输
    服务器返回一个 HTTP 响应
    浏览器渲染

具体过程可查看这位博主的分享https://blog.csdn.net/qinian8/article/details/99081105

  1. 前端路由用过吗?前端路由一种是hash路由,一种是history路由,这两种路由的原理是什么?
    hash路由:www.test.com/#/ 就是 Hash URL,当 # 后面的哈希值发生变化时,可以通过hashchange事件监听到url的变化,从而进行页面跳转,并且无论哈希值如何变化,服务端接收到的url请求永远是www.test.com
    history路由:History 模式是 HTML5 新推出的功能,主要使用history.pushState和history.replaceState改变 URL。
    通过 History 模式改变 URL 同样不会引起页面的刷新,只会更新浏览器的历史记录

两种模式的对比

  • hash模式只可以更改#后面的内容,History模式可以通过API设置任意的同源URL
  • History模式可以通过API添加任意类型的数据到历史记录中,hash模式只能更改哈希值,也就是字符串
  • Hash模式无需后端配置,并且兼容性好,History模式在用户手动输入地址或者刷新页面的时候会发起url请求,后端需要配置index,html页面用于匹配不到静态资源的时候
  1. 在网络的请求中一般情况下有一些交互,什么样的一些做法可能会造成前端开发的安全性问题?
  • XSS
  • iframe带来的风险
  • 点击劫持
  • 错误的内容推断
  • 不安全的第三方依赖包
  • 用了HTTPS也有安全隐患
  • 本地存储数据泄露
  • 缺失静态资源完整性校验

具体解释可查看这位博主:https://zhuanlan.zhihu.com/p/30649102

  1. 前后台发生交互行为的时候会发送http请求,http请求会返回状态码,你知道状态码都有些什么,有什么含义?
    这个状态码我在上边第一家公司总结过,我就说了一到五开头的状态码分别表示什么状态,然后他又问我能说具体的吗?比如302和303有什么区别?呜呜呜还是得好好记每个状态码,只记开头很容易被问倒!

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

  3. 技术问题结束,最后一个问题,为什么会选择来我们公司?
    这个可以在面试前去了解一下这家公司的背景,以及有什么项目。

公司三

base南京,10000人以上,一对一腾讯会议语音面试,实习薪资150-200/天


呜呜呜,这家面试官一直在问,不停地问,问了好多好多问题,我感觉我答得很差,最后直接开摆,问用过什么没,都说没用过hhhh。现在总结一下问题和答案,自己也多看一看!!!真的是发现了自己理论基础上的好多好多不足!还是挺感谢面试官的。
  1. 什么是BFC?
    BFC(Block formatting context)直译为“块级格式化上下文”。BFC它是一个独立的渲染区域,只有Block-level box(块元素)参与,它规定了内部的Block-level box如何布局,并且与这个区域外部毫不相关。
    可以理解成:创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素(里面怎么布局都不会影响外部),BFC仍属于文档中的普通流。
  2. BFC的原理是什么?
    1)内部的Box会在垂直方向,一个接一个地放置。
    2)Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
    3)每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
    4)BFC的区域不会与float box重叠。
    5)BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
    6)计算BFC的高度时,浮动元素也参与计算
  3. 如何创建BFC?
    1)根元素,html标签就是一个BFC
    2)float属性不为none
    3)position不为static和relative
    4)overflow不为visible
    5)display为inline-block, table-cell, table-caption, flex, inline-flex
  4. BFC作用?
    1)防止外边距重叠。
    bfc导致的属于同一个bfc中的子元素的margin重叠(Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠)
    我们可以在div外面包裹一层容器,并触发该容器生成一个BFC。那么两个div便不属于同一个BFC,就不会发生margin重叠了。
    2)清除浮动的影响
    块级子元素浮动,如果块级父元素没有设置高度,其会有高度塌陷的情况发生。
    原因:子元素浮动后,均开启了BFC,父元素不会被子元素撑开。
    解决方法:由第六条原理得,计算BFC的高度时,浮动元素也参与计算。所以只要将父容器设置为bfc,就可以把子元素包含进去:这个容器将包含浮动的子元素,它的高度将扩展到可以包含它的子元素,在这个BFC,这些元素将会回到页面的常规文档流。
    3)防止文字环绕
  5. css垂直居中的方法? 上边有总结
  6. 高度坍塌的产生原因及解决办法?
    当父元素未设置高度时,所有子元素浮动后,造成子元素脱离文档流进而无法把父元素撑开,父元素高度为0产生高度塌陷,称为高度塌陷问题。
    解决办法:
    法一:最直接的办法就是给父元素添加高度
    优点:简单。缺点:只适合固定页面的布局,无法进行自适应,不推荐使用。
    法二:触发BFC
    BFC有一个特性是计算BFC的高度时,浮动元素也参与计算,所以将box触发为BFC后可以解决高度塌陷。可以通过给box添加overflow: hidden;等声明触发BFC。
    法三:给所有的浮动元素后面加一个空的标签。给添加的这个空标签添加声明
				clear: both;     
				height: 0;
				overflow: hidden;

法四:万能清除法:给高度塌陷的元素添加如下after伪类

			父元素:after{
			    content: "";
			    height: 0;
			    clear: both;	/*清除两侧浮动*/
			    overflow: hidden;
			    display: block;	/*转化成一个块元素*/
			    visibility: hidden;
			}
  1. JS中的原型链是什么?有什么作用?
    原型链中就是实例对象和原型对象之间的链接。每个函数都有一个prototype属性,这个prototype属性就是我们的原型对象,我们拿这个函数通过new构造函数创建出来的实例对象,这个实例对象自己会有一个指针(proto)指向他的构造函数的原型对象!这样构造函数和实例对象之间就通过( proto )连接在一起形成了一条链子。
    作用:
    ①继承
    ②prototype用来实现基于原型的继承与属性的共享
    ③避免了代码冗余,公用的属性和方法,可以放到原型对象中,这样,通过该构造函数实例化的所有对象都可以使用该对象的构造函数中的属性和方法
    ④减少了内存占用

  2. 定义一个类,在js中new一个对象的过程中发生了什么?
    ①创建一个新对象;
    ②将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
    ③执行构造函数中的代码(为这个新对象添加属性);
    ④返回新对象;
    具体过程可查看这位博主:
    https://blog.csdn.net/ZYS10000/article/details/113447144

  3. JS里的闭包是什么?闭包有什么作用?
    闭包(closure)就是能够读取其他函数内部变量的函数。在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成 “定义在一个函数内部的函”。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
    优点:    
    ①保护函数内的变量安全
    ②在内存中维持一个变量(用的太多就变成了缺点,占内存) ;
    ③逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
    ④方便调用上下文的局部变量。
    ⑤ 加强封装性,可以达到对变量的保护作用。
    缺点:常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
    解决办法:在退出函数之前,将不使用的局部变量全部删除(垃圾回收机制)。

  4. 垃圾回收机制常用方法?
    ①标记清除。
    在一个函数中声明一个变量,就将这个变量标记为"进入环境",从逻辑上讲,永远不能释放进入环境变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为"离开环境"。
    垃圾回收机制在运行的时候会给存储在内存中的所有变量都加上标记(可以是任何标记方式),然后,它会去掉处在环境中的变量及被环境中的变量引用的变量标记(闭包)。而在此之后剩下的带有标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾回收机制到下一个周期运行时,将释放这些变量的内存,回收它们所占用的空间。
    ②引用计数。
    语言引擎有一张"引用表",保存了内存里面所有资源(通常是各种值)的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。

  5. 什么情况会引起内存泄漏?
    ①意外的全局变量引起的内存泄漏。
    原因:全局变量不会被回收。解决:使用严格模式避免。
    ②闭包引起的内存泄漏。
    原因:闭包可以维持函数内局部变量,使其得不到释放。解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
    ③没有清理的DOM元素引用
    原因:虽然别的地方删除了,但是对象中还存在对dom的引用。 解决:手动删除。

  6. 什么是节流,什么是防抖?使用场景是什么?
    防抖是一段时间内不断的触发只执行最后一次,节流是一段时间内不断触发,会均匀的间隔执行。

应用场景
防抖在连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求手机号、邮箱验证输入检测
  • 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能

具体的实现代码,可以参看这位博主的分享https://vue3js.cn/interview/JavaScript/debounce_throttle.html#%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0

  1. DOM的事件模型
    主要包含4个方面的内容,分别是:
    ①事件流
    ②主流浏览器的事件模型
    ③事件对象
    ④注册与移除事件监听器
    具体解释可以参看这位博主的分享:https://blog.csdn.net/lzgs_4/article/details/46224561

  2. 在DOM结点上设置了一个事件监听器,那么触发事件的时候是怎么触发的?浏览器是怎么判断事件触发的?
    ①鼠标事件
    mouseenter:鼠标移动到元素上时出发(不支持冒泡),不能使用事件委托;进入子元素依然属于在该元素内,没有任何反应。
    mouseover:鼠标移到某元素之上(支持冒泡),先调用父元素的mouseout,再调用子元素的mouseover,因为支持冒泡,所以会将mouseover传递到父元素中;
    ②常见的键盘事件
    onkeydown:某个案件被被按下,事件先发生
    onkeypress:发生在文本被输入
    onkeyup:某个按键被松开,发生在文本输入完成
    ③常见的表单事件
    1)获取焦点和失去焦点
    onfocus:元素在获取焦点时触发
    onblur:元素在失去焦点时触发
    2)内容发生改变/输入内容
    3)监听重置和提交

  3. 在DOM结点上设置了一个事件监听器,要经历哪几个阶段
    ①捕获阶段 (从根节点开始顺着目标节点构建一条事件路径,即事件由页面元素接收,逐级向下,到具体的元素)
    ②目标阶段 (到达目标节点,即元素本身)
    ③冒泡阶段 (从目标节点顺着捕获阶段构建的路径回去, 即跟捕获相反具体元素本身,逐级向上,到页面元素)
    看下边这张图比较好理解。
    在这里插入图片描述

  4. get和post的区别? (又被问到了,上边已经总结

  5. 知道restful吗?
    emmm,不知道,面试官给我说是接口的一个规范,刚刚问get和post的区别,面试官说他俩最大的区别其实是语义上的区别。那他就是想让我回答的就是:get用来获取数据,post用来提交数据。面试完查了一下restful,放上链接https://blog.csdn.net/zzvar/article/details/118164133

  6. 什么是同源策略?
    一个域名地址由 协议、域名、端口、请求资源地址 等部分组成。如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源。
    浏览器默认两个相同的源之间是可以相互访问资源和操作 DOM 的。两个不同的源之间若想要相互访问资源或者操作DOM,那么会有⼀套基础的安全策略的制约,我们把这称为 同源策略。它的存在可以保护用户隐私信息,防止身份伪造等(读取Cookie)。
    同源策略主要表现在 DOM、web 数据 和 网络 这三个层面。

    但是有三个标签是允许跨域加载资源:

    <img src=''>
    <link href=''>
    <script src=''>
  1. 接上个问题,如果有一个ip地址对应的域名,用域名访问这个网站,然后后边接口都用ip去访问,这个算同源吗?
    我回答是同源的,面试官给我说是不同源的,我问为什么,他说没有为什么,这是浏览器的规定。
    大无语,不想面试了,直接开摆!
  2. 接上个问题,如果想突破浏览器的同源策略应该怎么做?(也就是如何解决跨域问题)
    ①document.domain属性
    Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。
    法一:通过JS设置document.domain属性:
<script type="text/javascript">
	document.domain = 'example.com';
</script>

法二:服务器也可以在设置Cookie的时候,指定Cookie的所属域名为一级域名,比如.example.com。
Set-Cookie: key=value; domain=.example.com; path=/
这样的话,二级域名和三级域名不用做任何设置,都可以读取这个Cookie。

②片段识别符(fragment identifier)

片段标识符(fragment identifier)指的是,URL的#号后面的部分,比如http://example.com/x.html#fragment的#fragment
当fragment变化的时候,会触发window.onhashchange事件,可以通过修改片段标识符的值,来在两个页面之间传递数据,父窗口可以把信息,写入子窗口的片段标识符。

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;

子窗口通过监听hashchange事件得到通知。

window.onhashchange = checkMessage;

function checkMessage() {
  var message = window.location.hash;
  // ...
}

同样的,子窗口也可以改变父窗口的片段标识符:

parent.location.href= target + "#" + hash;

③window.name
④跨文档通信API(Cross-document messaging)
⑤JSONP
⑥CORS(Cross-Origin Resource Sharing)
⑦WebSockets
扩:JSONP和CORS两种跨域方式的对比:
  JSONP是利用浏览器对script的资源引用没有同源限制,通过动态插入一个script标签,当资源加载到页面后会立即执行的原理实现跨域的。JSONP是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback或者开始就定义一个回调方法,参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
  JSONP只支持GET请求而不支持POST等其它类型的HTTP请求,它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题,JSONP的优势在于支持老式浏览器,弊端也比较明显:需要客户端和服务端定制进行开发,服务端返回的数据不能是标准的Json数据,而是callback包裹的数据。
  CORS是现代浏览器支持跨域资源请求的一种方式,当使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
  CORS支持所有的浏览器请求类型,承载的请求数据量更大,开放更简洁,服务端只需要将处理后的数据直接返回,不需要再特殊处理。

  1. 有学过ts吗?学过react吗?知道JSX是什么?

  2. vue中的生命周期钩子有哪些?
    这位博主写的很详细!:https://blog.csdn.net/Sheng_zhenzhen/article/details/104623260

  3. Vue组件之间的通信方式都有哪些?
    https://vue3js.cn/interview/vue/communication.html#%E4%B8%89%E3%80%81%E7%BB%84%E4%BB%B6%E9%97%B4%E9%80%9A%E4%BF%A1%E7%9A%84%E6%96%B9%E6%A1%88

  4. 有用过vuex吗?vuex里更改状态的方法有两种,一个是action一个是mutation,这两种有什么区别?
    ①流程顺序
    “相应视图—>修改State”拆分成两部分,视图触发Action,Action再触发Mutation。
    ②角色定位
    基于流程顺序,二者扮演不同的角色。
    Mutation:专注于修改State,理论上是修改State的唯一途径。
    Action:业务代码、异步请求。
    ③限制
    角色不同,二者有不同的限制。
    Mutation:必须同步执行。
    Action:可以异步,但不能直接操作State。

  5. 你知道vue中的双向绑定怎么用?vue中双向绑定的指令是什么?
    指令是v-model,
    https://zhuanlan.zhihu.com/p/352064419

  6. v-model实现了父子组件相互传值,那是怎么传的?
    https://blog.csdn.net/daisy0328/article/details/109844630

  7. 你有对vue原理进行了解吗?
    https://zhuanlan.zhihu.com/p/138114429

  8. 在vue中,computed和watch的区别是什么?
    https://blog.csdn.net/weixin_38779534/article/details/113116779#:~:text=%E6%A0%B9%E6%8D%AEvue%E5%AE%98%E6%96%B9%E6%96%87,ch%E5%8F%AB%E5%81%9A%E4%BE%A6%E5%90%AC%E5%99%A8%E3%80%82

  9. 深拷贝和浅拷贝有了解吗?写一下深拷贝的实现函数
    https://blog.csdn.net/qq_37430247/article/details/110423921

公司四

base北京,2000+人,同时有2位面试官,一位提问,另一位一直在观看。提前下载其他软件,面试的时候介绍项目有被要求共享屏幕展示项目,我放了一下我们项目里做的介绍视频。是个初创公司,薪资比同等高,加班是常态,不过面试官的态度是真的好! 实习薪资300-400/天。


因为面试时长30min左右,前边面试官对我的项目很感兴趣,所以很长时间都在介绍项目,对于前端技术最后问的比较少。

  1. 为什么会出现跨域问题,都有什么解决方法?

  2. 说一下前端部署流程,内部原理?
    我回答了我之前部署都是用的npm run build

  3. npm run build的原理?

  4. 页面缓存cookie和localStorage以及sessionStorage的区别

  • cookie:主要用来保存登录信息,比如登录某个网站市场可以看到“记住密码”这就是通过cookie中存入一段辨别用户身份的数据来实现的
  • sessionStorage:会话,是可以将一部分数据在当前的会话中保存下来,刷新页面数据依旧存在。但是页面关闭时,sessionStorage中的数据就会被清空。
  • localStorage:是HTML5标准找那个新加入的技术,localStorage中的键值对总是以字符串的形式存储。localStorage类似sessionStorage,但其区别在于:存储在localStorage 的数据可以长期保留。
    具体解释可参看这位博主:
    https://zhuanlan.zhihu.com/p/207106785
  1. 让我共享屏幕,打开编译器用js写代码
    题目是,传入两个字符串,里边存储的是版本号,比如v1.2.2和v1.2.3然后返回较小的版本号
  2. 提高难度
    因为我写的不是普适性的,里边有一些边界问题,然后问如果两个版本号长度不一样,比如v1.2.2和v1.2.3.1,怎么比较返回?
    对于上述的写代码,我临场发挥是对字符串中的每个字符进行比大小判断,只要当前的数字不等,就直接返回小的那个字符串,对于后边的就不用继续再判断了。不过晚上睡觉前,突然想到,这里可能想考我的是split的用法,先用str.split('.')将字符串分割成只有那些数字字符的数组,然后按照从前到后组装成数字进行比大小。
    第二天我自己敲代码试了一下,代码如下:
				var str1 = "v1.2.2.2";
				var str2 = "v1.2.3";
				var arr_str1 = str1.split('.');		// arr_str1 = ['v1', '2', '2', '2']
				var arr_str2 = str2.split('.');		// arr_str2 = ['v1', '2', '3']
				var length = Math.max(arr_str1.length, arr_str2.length);
				var num_str1 = 0;
				var num_str2 = 0;
				for(let i=0;i<length;i++){
					if(i==0){		//对于数组的第一项,由于是"v1",所以只需要获取到其中的"1"就好了
						num_str1 += arr_str1[i][1] - '0';
						num_str2 += arr_str2[i][1] - '0';
					}
					else{
						if(i<arr_str1.length)
							num_str1 = (num_str1 * 10) + (arr_str1[i] - '0');
						else
							num_str1 = num_str1 * 10;			//是较短的版本号,后边直接补0进行填充
						if(i<arr_str2.length)
							num_str2 = (num_str2 * 10) + (arr_str2[i] - '0');
						else
							num_str2 = num_str2 * 10;			//是较短的版本号,后边直接补0进行填充)
					}
				}
				if(num_str1 < num_str2)
					console.log("min = " + str1);
				else
					console.log("min = " + str2);

控制台输出了一下,好像没什么问题。如果还有没考虑到的地方或者逻辑上有错误的地方,请友友指正!
在这里插入图片描述

上边是这家公司的一面,二面的时候还是先介绍项目,面试官直接就是我入职后的mentor,他对我的项目很感兴趣,共享屏幕演示了2个项目基本都用了快半个小时,最后时间不够了就只考查了一个代码题。这题很简单,我觉得面试官已经决定要我了,所以就没有为难我。
题目是:将字符串"I Love NanJing"变为"NanJing love I"
这个用了splitjoin函数,先将"I Love NanJing"用split函数以空格分开存入数组,然后将数组转置,再用join函数以空格连接起来。

    var str1 = "I Love NanJing";
    var arr1 = str1.split(' ');
    var arr2 = [];
    for (let i = arr1.length - 1; i >= 0; i--) {
        arr2.push(arr1[i]);
    }
    var str2 = arr2.join(' ');
    console.log(str2); 

看控制台输出:
在这里插入图片描述

我写对了,最后又跟面试官聊了二十多分钟,主要交流了以后的规划发展以及公司的情况,各方面都很合适,最后我也是选择了在这家公司实习。

其实我觉得前端面试的提问深度不深,但是广度很广,有html\css\js\网络\优化\安全等方面。但是大部分的提问网络上的面经里都有总结了,我被提问的上述那些问题基本之前都看到过,但就是背了忘,忘了又背,得多下功夫多看看,有的常见问题不同家公司都会问到,大家加油呀,祝大家顺利拿到心仪的offer!

  • 15
    点赞
  • 133
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值