荔枝FM前端面试题
最近接到了荔枝FM的面试通知,遗憾的是没有拿到offer,但是这次面试呢,还是收获很大的,下面就来给大家说说我遇到的面试题
一面
一面是直接发了一套面试题到邮箱,开启了防作弊的,限时20分钟做完,下面是我一面是的题目
1. 变量提升和函数提升
function outter () { return inner; function inner () {} var inner; inner = 9; } //问题是下面代码执行输出值是什么: typeof outter();
这题涉及到的知识点是变量提升,在js中是存在变量提升和函数提升的,但是如果变量名重复的情况下函数提升>变量提升
答案:function
2. 用html和css实现一个宽度为屏幕45%的正方形,可以使用最近标准
这题只要考察的是自适应的问题
第一种方法:利用宽度百分比
<div style="width:50%;padding-bottom:50%;height:0px;> </div>
第二种方法:利用css的新单位vw
<div style="width: 50vw; height: 50vw;> </div>
第三题:写出6个div元素的堆叠顺序,最上面的在第一个位置,例如: .one .two .three .four .five .six(z-index)
html:
<div class="one"> <div class="two"></div> <div class="three"></div> </div> <div class="four"> <div class="five"></div> <div class="six"></div> </div>
css:
.one { position: relative; z-index: 2; .two { z-index: 6; } .three { position: absolute; z-index: 5; } } .four { position: absolute; z-index: 1; .five {} .six { position: absolute; top: 0; left: 0; z-index: -1; } }
这题考察的是css部分的层叠上下文的知识点说这个之前呢,我们得了解下面几个知识点
解析:从w3c的文档可以知道,z-index属性设置一个定位元素沿 z 轴的位置,z 轴定义为垂直延伸到显示区的轴。如果为正数,则离用户更近,为负数则表示离用户更远
- 没有定位的元素z-index是不会生效的
- 定位元素拥有更高堆叠顺序的元素总是处于堆叠顺序较低的定位元素的前面
- 子元素必然在父元素的前面,不管是否是定位元素
- 同级定位元素的z-index相同时遵循”后来居上”,后面的定位元素堆叠顺序更前
- z-index小于0的定位元素位于所有元素的后面,但是比其父元素的堆叠顺序要前
通过上面的结论分析,得出的答案如下
答案:.three>.two>.one>.five>.six>.four
二面的时候,面试官会根据这题扩展问题一下这个问题:
z-index的触发条件是:
- 根层叠上下文(
html
) - position
- css3属性
- flex
- transform
- opacity
- filter
- will-change
- -webkit-overlow-scrolling
4.写一个正则表达式,满足一下特点:
-
有8-12位
-
只包含数字和字母
这题呢考察的是正则的使用,答案肯定是不止一种的
[A-Za-z0-9]{8,12}$
/(\d|[A-z]{8,12})/
解析:正则呢,我们需要了解以下几个元字符,基本写出来就不难了:
- \d : 匹配一个数字字符,等价于:[0-9]
- {n}: n是非负整数,匹配确定的n次
- {n,} : n是非负整数,至少匹配n次
- {n,m} :n,m均为非负整数,其中n<m,表示最少匹配n次做多匹配m次
- $ : 行尾,匹配输入的字符串结束位置
- [] : (这个是非元字符)表示的是一个范围
- \ : 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符
5. IE不支持Function.prototype.bind,自定义函数使IE支持该方法
6. 写一个sleep函数,sleep(3)等待3秒
该题目的意思就是写一个sleep函数,设置个时间,等到设置的时间之后再执行
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function demo() { await sleep(3000); //间隔多少毫秒 console.log(new Date()); //修改成要执行的代码 } demo();
二面:
二面是技术面,直接会有个技术人员来面试你,主要是问一些原理性和基础性的东西
1.怎么实现变量私有化
在ES6之前是没有块级作用域之说的,但是可以自己实现,下面给大家写几个实现的方法,当然包括ES6的
- ES6的变量申明 let
- 自执行函数
(function Random(){ // 块级作用域 })()
- 闭包里面定义的局部变量
function add() { var num = 10; return function jian() { console.log(num) } } add()(); // 10 console.log(num); // Uncaught ReferenceError: num is not defined
- ES6的Symbol
Symbol是ES6新引入的数据类型,表示独一无二的值,可以保证不会与其他属性名产生冲突
Symbol('2')==Symbol("2"); // false var x = y = Symbol('a'); x === y //打印 true 说明该数据类型以引用的方式传值
下面就用Symbol实现变量私有化
var Person = (function(){ const a = Symbol('a'); const m = Symbol('m'); class Person { constructor(){ this[a] = 'a这是私有变量'; this.b = '变量B-外部可访问'; this[m] = function(){ console.log('私有方法'); } } getA(){ console.log(this[a]); } getM(){ console.log(this[m]); } } return Person }()) let pc = new Person() console.log(pc)
2. 实现 add(1)(2)(3)=6
这题考察的是柯里化,
3. 实现自适应的方案有哪些?怎么实现
- 媒体查询 :根据不同屏幕尺寸写出不同的适配方案
- flex布局:设置父元素的display为flex,子元素可以根据需要的占比来设置flex的值,从而实现自适应布局
- grid布局:这是CSS3新提出的,实现方式类似flex,具体看我另外一篇笔记有详细讲解(https://www.cnblogs.com/cythia/p/10894598.html)
- rem:rem是指相对于根元素的字体大小的单位,下面有个公式可以供大家理解
元素的rem值=元素的px/根节点字体大小
var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth //获取屏幕宽度 var htmlDom = document.getElementsByTagName('html')[0] //获取html htmlDom.style.fontSize = htmlWidth / 10 + 'px'; //设置html字体大小为屏幕的十分之一 //监听窗口大小改变 window.addEventListener('resize', () => { var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth var htmlDom = document.getElementsByTagName('html')[0] htmlDom.style.fontSize = htmlWidth / 10 + 'px'; })
当然我们需要考虑一下兼容性的问题,大家可以看一下这篇https://github.com/imochen/hotcss文章,上面的这个解决方案是算比较完美了的
- 利用px2rem-loader: 现在我们很多项目都是使用webpack做构建工具,那么我们可以使用webpack配置px2rem-loader来实现px转rem
安装(前提是你已经配置安装好了css-loader,style-loader或vue-style-loader):
npm install px2rem-loader --save-dev
配置webpack:
{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", }, { loader: 'px2rem-loader?remUnit=37.5&remPrecision=6' }], }) }
4. vue的怎么实现性能优化
- vue-router路由懒加载
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/', component: resolve => require(['@/components/Patient'],resolve), children: [ { path: '', component: resolve => require(['@/components/Hospital'],resolve) }, { path: '*', redirect: '/Hospital' } ] })
- 为item设置唯一的key值:方便vuex的内部机制在循环时能够快速准确的找到该条列表数据
- 减少watch的数据 : 因为当watch的数据比较大的时候,会大量消耗性能,所以 我们可以使用事件中央总线或者vuex进行数据的变更操作
- 使用骨架屏加载 : 骨架屏就是在页面内容未加载完成的时候,先使用一些图形进行占位,待内容加载完成后在把它替换掉
- SSR(服务端渲染) : 如果项目比较大的话,首屏无论怎么优化,都还是会出现闪屏的情况,可以考虑使用SSR
- 按需加载 : 使用第三方的UI框架的时候,如果我们只是使用里面部分的UI组件的话,只需要导入需要使用的部分即可
5. webpack怎么实现性能优化
- 缩小文件的搜索范围 : webpack里面有个resolve字段,可以告诉webpack怎么去搜索文件
- 压缩图片:
安装
npm i image-webpack-loader -D
rules: [{ test: /\.(gif|png|jpe?g|svg)$/i, use: [ 'file-loader', { loader: 'image-webpack-loader', options: { bypassOnDebug: true, disable: true, }, }, ], }]
- 压缩js: 使用webpack内置UglifyJS插件、ParallelUglifyPlugin
安装:
npm i -D uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = { plugins: [ new UglifyJsPlugin() ] }
- 压缩css:
weboack中4+的版本和以前的版本的压缩方式是不一样的,webpack4+版本的方式使用optimize-css-assets-webpack-plugin
安装
npm install --save-dev optimize-css-assets-webpack-plugin
在webpackconfig中配置:
// 引入模块 const OptimizeCssAssetsPlugin=require('optimize-css-assets-webpack-plugin') plugins: [ new HtmlPlugin({ title:'webpack test', template:path.join(__dirname, './public/index.html') }), // 压缩css new OptimizeCssAssetsPlugin(), new MiniCssExtractPlugin({ filename:'[name].css', chunkFilename:'[id].css' }) ]
- 去掉不必要的插件:
- gzip压缩:
(webpack性能优化请等待我的下一篇笔记)
6. less/sass为什么嵌套最好不要超过三层
嵌套多层的话,会有以下几种缺点
- 嵌套多层的话,会降低易读性,不利于后期的维护
- 嵌套多层的话,权重规则会变得复杂,还要多输入一些字符,于机器于人都不利
- 性能方面,因为css渲染是由子元素开始父元素上渲染的,如果嵌套多层的,就会一直往上找父元素,这是非常消耗性能的