撸代码之余,偶尔刷刷面试题,回顾下基础的知识点也是极好的。个人通过看大佬文章,也整理了下基础的面试题,同时也夹杂了一些工作中遇到的小问题和方法。打算写成小系列文章做个记录,给自己和有需要的童鞋做个参考。
本篇是系列的第一篇,主要涉及一些基础知识。
1、如何实现三栏布局,中间自适应两边固定宽度?
//方法一:圣杯布局
<div class="box"> <div class="center"> <div class="center-in">center</div> </div> <div class="left">left</div> <div class="right">right</div></div>.box{ padding: 0 200px;}.center{ width: 100%; float: left; background: orange; position: relative;}.left{ width: 200px; float: left; background: green; margin-left: -100%; left: -200px; position: relative; }.right{ width: 200px; float: left; background: green; position: relative; margin-right: -200px;}
//方法二:双飞翼
<div class="center"> <div class="center-in">center</div></div><div class="left">left</div><div class="right">right</div>.center,.left,.right{ float: left;}.center{ width: 100%; background: blue;}.left{ width: 200px; margin-left: -100%; background: orange;}.right{ width: 200px; background: green; margin-left: -200px;}.center-in{ padding: 0 220px;}//方法三:flex
<div class="box"> <div class="left">left</div> <div class="center"> <div class="center-in">center</div> </div> <div class="right">right</div></div>.box{ height: 100%; display: flex; display: -webkit-flex; flex-direction: row; align-items: stretch;}.left, .right{ background: green; width: 200px;}.center{ flex: 1; background: orange;}2、请写出元素水平垂直居中方法
(1)对于单行文字:
text-align:center;
line-height:20px;(2)固定宽高元素: 方法一:
.box{ position: absolute; width: 200px; height: 200px; margin: auto; left: 0; top: 0; bottom: 0; right: 0;} 方法二:
.box{ position: absolute; width: 200px; height: 200px; left: 50%; top: 50%; margin-left: -100px; margin-right: -100px;} 方法三:
.box{ position: absolute; width: 200px; height: 200px; left: 50%; top: 50%; transform: translate(-50%, -50%) }(3)flex方法:
.container{ display:flex; align-items:center; justify-content:center;}3、谈一谈css的重绘和重排
重排一定会引起重绘,重绘不一定引起重排;
引起重排的操作:添加删除元素;显示隐藏元素,主要是display操作;移动元素,修改top、left等值;浏览器窗口大小改变;字体大小改变;元素的大小及padding、margin修改;
引起重绘的操作:修改文字颜色;修改背景色;通过visibility修改显示隐藏;
4、为什么无法定义1px左右高度的容器?(IE6问题)
IE6下这个问题是因为默认的行高造成的,解决办法
参考:overflow:hidded|zoom:0.08|line-height:1px
5、什么是BFC机制?如何触发BFC?
BFC是块级格式化上下文,是一个独立的渲染区域,处于BFC内部的元素与外部的元素相互隔离,元素定位不会相互影响。
触发BFC: float不为none;overflow不为visible;display值为table-cell、table-caption、inline-block之一;position不为static、relative
6、页面导入样式时,使用link和@import的区别
(1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS;
(2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
(3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;
(4)link支持使用js控制DOM去改变样式,而@import不支持
7、display:inline-block 元素之间产生空白间隙的原因是什么?如何避免?
原因:元素被当成行内元素排版时,元素之间的空白符(如空格、回车等)会被浏览器处理。原来html的回车换行被转换成了一个空白符,在字号不为0的时候,会占有一定的宽度。
解决方法:
(1) 将子元素的结束标签和下一个标签的开始符写在一行,或者所有子元素写在一行;
(2) 父元素上字号font-size:0,子元素再单独进行字号设置;
(3) 子元素添加float
8、选择器优先级
!important > 行内样式 > id选择器 > class选择器 > 标签选择器 > * > 继承 > 默认
9、样式的顺序问题
css代码: .red{color: red} .blue{color: blue}
html结构: <div class=’red blue’>文字颜色</div>
<div class=’blue red’>文字颜色</div>
结论:两个文字颜色均为blue,因为样式里.blue类在后面,会覆盖掉red颜色
10、RequireJS(AMD)、SeaJS(CMD)、CommonJS、ES6的区别
Requirejs/AMD:异步模块定义,依赖前置,依赖加载完成后才执行,
导入:require([‘name’], function(‘引用名’){}); 导出:define(function(a){return})
Seajs/CMD:同步模块定义,执行时才加载即按需加载,
导入:define(function(require,exports,module){ var a = require(‘a’)}) 导出:define(function(){return })
Commonjs:模块可以多次加载,但是只在第一次加载的时候运行一次,后面就会读取缓存;模块加载会阻塞接下来的代码执行。输出的是值得拷贝
导入:require(); 导出:exports.a = function(){} module.exports = function(){}
ES6:按需加载,输出的是值的引用。import会优先于模块内其他内容执行;export会有变量提升效果,所以import和export在模块中的位置不影响程序输出。
import a from ‘./a’ export const a = ‘a’ export default a
11、js严格模式和普通模式的区别
(1) 严格模式下,全局变量必须显示声明,否则会报错;普通模式可以不定义直接赋值;
(2) 严格模式下,禁止this指向全局对象,指向全局是返回undefined;普通模式下则返回window
(3) 严格模式禁止使用with语句,因为with语句无法在编译时确定属性归属那个对象;
(4) 严格模式下构造函数必须通过new方法调用,否则会报错;
(5) 严格模式下,给只读对象属性进行赋值会报错,而且有多个重名属性时,也会报错;普通模式下,对只读属性赋值会失败,但不会报错,多个重名属性时后面会覆盖掉前面属性;
(6) 严格模式下,函数声明必须在顶层;
(7) 严格模式,新增加关键字,如let publish static yield等
12、 对js变量提升的理解
js代码在执行时,会生成执行环境,代码会在对应的环境中执行。在生成执行环境时,会有两个阶段,一个是创建阶段,一个是执行阶段。在创建阶段js会把变量和函数进行提升,在内存中开辟空间,同时变量会初始化值为undefined,所以在执行阶段可以提前使用变量和函数,并且函数提升优先于变量提升。
但是再es6里的let和const方法不能在定义前使用,必须先定义后使用。并不是说let不会提升,而是提升了但是没有初始化,会存在一个暂时性死区,导致访问不到。
13、 数组的常见操作?
数组链接:
concat:返回被连接数组的副本;
es6扩展运算符
增加:push:返回新数组长度,影响原数组;
unshift:返回新数组长度,影响原数组
删除:pop:删除最后一个元素,返回被删除元素,改变原数组;
shift:删除第一个元素,返回被删除元素,改变原数组
截取:slice:返回指定元素,不改变原数组;
splice:可以删除/增加/替换数组,对原数组有影响
排序:sort
翻转:reverse:改变原数组
查找:indexOf/lastIndexOf:查找到指定位置的值
遍历:every:对数组每一项执行指定方法,都为true才返回true,否则返回false;
some:对数组每一项执行指定方法,只要有一个为true,则返回true;
map:对数组每一项执行指定方法,返回执行后的新数组;
filter:对数组每一项执行指定方法,返回结果为true的项组成的数组;
forEach:对数组进行遍历
转换:join:将数组转化为字符串
es6新增方法:
find:查找到符合的第一个元素,并返回该元素
fill:填充数组
from:将类数组转化为真正的数组
entries:返回键值对
values:返回数组各项对应的值
keys:返回数组各项下标
includes:数组中是否包含某元素
14、判断是否是微信内置浏览器?
Var iswx = /(micromessenger|webbrowser)/.test(navigator.userAgent.toLowerCase())
Micromessenger:iphone和android系统微信内置浏览器
Webbrowser:winphone系统微信内置浏览器
15、ajax的出现解决了什么问题?
在ajax出现之前,任何与服务器的交互都需要刷新页面进行更新,用户体验差。Ajax是异步的js和xml,Ajax出现之后是网页应用能够快速的将更新呈献给用户,而不需要重新加载整个页面,实现是基于浏览器的xmlhttprequest实现。
16、js小技巧
(1)双位运算符 ~~,对于正数来说相当于Math.floor(),对于负数来说相当于Math.cell()
~~ 4.6 相当于 Math.floor(4.6) //4
~~ -4.6 相当于 Math.ceil(4.6) //-4
(2)取整 | 0:对于一个数字 | 0可以直接取整,对负数同样适用
1.5 | 0 //1
-1.5 | 0 //-1
17、如何实现文件的断点续传?
最核心内容就是把文件进行切片,然后传给服务器,运用html5的file相关api进行操作。大致过程:对文件进行识别,将文件分成若干份,具体如何切片需要和后台一起商议决定;文件上传之后要和服务端进行通信,确定文件是否传输成功,成功之后双方对成功的文件进行标识;如果传输过程中出现失败情况,可以通过获取服务端标识判断是否已经上传一部分,就可以按照上次进度进行续传。
18、简述js中的this
1、在调用函数时使用new关键字,函数内的this是一个全新的对象。
2、如果apply、call或bind方法用于调用、创建一个函数,函数内的 this 就是作为参数传入这些方法的对象。
3、当函数作为对象里的方法被调用时,函数内的this是调用该函数的对象。比如当obj.method()被调用时,函数内的 this 将绑定到obj对象。
4、如果调用函数不符合上述规则,那么this的值指向全局对象(global object)。浏览器环境下this的值指向window对象,但是在严格模式下('use strict'),this的值为undefined。
5、如果符合上述多个规则,则较高的规则(1 号最高,4 号最低)将决定this的值。
6、如果该函数是 ES2015 中的箭头函数,它没有自己的上下文,this被设置为它被创建时的上下文。
19、说下对浏览器内核的理解
思路:主要包括渲染引擎和js引擎
20、cookie、sessionStorage和localStorage的区别?(答案略)
21、get和post的区别
(1)get请求在浏览器回退和刷新的时候是无害的,而post请求会告知用户数据重复提交;
(2)get请求可以被缓存,post请求不可以被缓存,除非在响应头中包含cache-control/expries字段,但是不建议;
(3)get 请求是向url中添加数据,不同浏览器对url长度限制有所区别,因此可能会超过长度限制,post请求无长度限制;
(4)get请求安全性较差,因为数据被暴露在url中,不能用来传递敏感信息,post请求相对安全性较好;
22、svg和canvas的优缺点?
共同点:都是有效的图形工具,对于数据较小的情况下,有很好的性能。
svg优点:矢量图,无限放大后不会失真,以dom形式展示,事件绑定由浏览器直接分发到节点上;缺点:涉及到动画内容时需要更新dom,影响内存。
canvas优点:定制型较强,非dom结构,通过js进行编译,可以做动画,且性能较高;缺点:非矢量图,无法实现高保真,事件分发由canvas’处理。
23、script标签中defer和async的区别?
defer表明脚本在执行时不会影响页面的构建,脚本会在整个页面都解析完毕后在运行。
async同样异步的,但是不会按照书写的先后顺序执行,如果加载完成会立即执行,多个async的js无法保证执行顺序。
24、关于promise(答案略,网上文章很多可参考)
25、设计给予观察者模式的事件绑定机制
基本思路:定义一个观察者类,主要作用包括收集订阅者,并在数据有更新时通过notify方法通知订阅者,订阅者执行update方法;在订阅者类内部,定义各自的update方法和业务逻辑。
26、下面代码输出什么?
//=======index.js
console.log(‘run index.js’)
import {add} from ‘add.js’
console.log(add(1,2))
//=======add.js
console.log(‘run add.js’)
const add = (a,b)=>a+b
//== 依次输出 run add.js==> run index.js ==> 3
import命令,是编译阶段执行的,代码运行之前,被导入的会先运行;
如果用require导入,则是按需加载,会按顺序执行 run index.js ==> run add.js ==> 3
27、页面从输入url到页面加载完成,都发生了什么?
(1)用户输入url
(2)解析url发送到DNS服务器,查询域名对应的ip地址
(3)与服务器建立TCP连接,tcp三次握手
(4)服务器的永久重定向响应
(5)向服务器发送请求,服务器处理请求
(6)服务器返回http响应
(7)客户端解析数据,展示html
(8)客户端请求图片、样式等静态资源,以及异步请求
(9)服务器返回相关数据
(10)数据请求和发送完毕,断开连接,tcp四次挥手
28、前端性能优化的方式
(1)使用内容分发cdn加速
(2)静态资源dns预解析
(3)减少http请求,对静态资源进行缓存
(4)对图片进行压缩、js、css代码压缩打包
(5)优化js代码及逻辑,减少解析、编译时间
(6)图片懒加载技术
(7)减少对dom的操作
(8)打包优化,抽离公共组件及引用,减少不必要引入
29、以下代码输出什么?
[‘1’, ‘3’, ‘10’].map(parseInt)
//==== 1, Nan, 2
Array.map(function(item, index){})方法中两个参数分别对应parseInt(num, jishu)中的两个参数,即相当于:parseInt(‘1’, 0) = 1, parseInt(‘3’, 1) = NaN, parseInt(‘10’, 2) = 2
30、safari浏览器中z-index层级问题
在safari浏览器中(包括ios的safari、iphone的微信以及mac的safari),当设置3d变换时,会出现自身及其他元素设置z-index不生效问题,设置了3d的元素会覆盖掉z-index元素。
解决办法:在任意非body的父级设置overflow:hidden即可;也可以给受影响的浮层添加数值较大的translateZ值。
31、小按钮(小文字)文组居中问题
在android系统中,当字体大小小于14px/0.7rem时,会出现居中失效情况。
解决办法:(1)将rem转换为px
(2)将宽高、文字大小都放大2倍,在用transform进行缩放。
.fonts{width: 2rem; height: 2rem; font-size: 1.2rem; transform: scale(0.5; )}
32、移动端输入框与键盘兼容问题:
(1)input标签在IOS上唤起软键盘,键盘回收后页面不回落。
解决办法:监听input的focus事件,触发后将scrolltop设置为0.
document.addEventListener(‘focusout’, function(){ document.body.scrollTop = 0})
(2)唤起软键盘后遮挡输入框
解决办法:获取聚焦的元素并检验是否是input或者textarea,是的话则调用scrollIntoView方法。
document.addEventListener(‘resize’, ()=>{ if(document.activeElement.tagName == ‘INPUT’ || document.activeElement.tagName == ‘TEXTAREA){ setTimeout(()=>{ document.activeElement.scrollIntoView() }, 0) }})
(3)唤起键盘后,原来position:fixed; bottom:0; 元素被键盘顶起。
解决办法:监听window的resize事件,事件触发后,将fixed元素隐藏,键盘收回时再进行显示。(可以根据触发事件前后clientHeight高度进行判断)
let clientHeight = document.documentElement.clientHeight;document.addEventListener(‘resize’, ()=>{ let bodyHeight = document.document.clientHeight; let ele = document.getElementById(‘fixedEle’); if(!ele) return; if(clientHeight > bodyHeight){ ele.style.display = ‘none’ }else{ ele.style.display = ‘block’ }})33、减少webpack打包时间,分离基础组件(如:vue、vuex、vue-router、axios等)方法
基本思路:使用dllPlugin进行抽包,将公共组件进行抽离打包或者使用cdn方式进行引用,同时在webpack里配置不需要打包的组件
34、web安全问题,常见的攻击方式及预防措施
(1)、SQL注入
如果后台人员在使用用户输入的数据或者get请求发送的数据时,没有做相应的防范措施,当遇到恶意修改请求内容时,会造成SQL问题。
解决办法:后端增加过滤和验证机制,有效预防SQL注入问题
(2)、XSS
全称是跨站脚本攻击,主要是通过代码注入方式达到攻击的目的。
解决办法:
字符转义:对于输入输出的内容进行转义,特殊符号转义;跳转链接添加白名单控制,只允许类似http/https/mailto等安全协议;
(3)、CSRF
全称是跨站请求伪造,本质上是借助用户的身份或者权限完成某些操作,即使借助cookie进行。
解决办法:对各个层级添加权限校验,尤其是涉及到交易的内容,输入密码验证码之类方式。
(4)、点击劫持
也被称为UI覆盖攻击,即在某些点击区域或者按钮上覆盖一层透明iframe,用户点击即会触发。
解决办法:
① 使用http头防御:配置nginx发送x-frame-options响应头,可以防御用iframe嵌套的点击劫持攻击,浏览器可以阻止嵌入网页的渲染。
② 使用js防御:判断顶层窗口的域名是不是和本页面的域名一致,不一致则可以跳转到正常页面。
if (top.location.hostname !== self.location.hostname) {
alert("您正在访问不安全的页面,即将跳转到安全页面!") top.location.href = self.location.href;
}
(5)、中间人攻击
俗称MITM攻击,是通过拦截正常的网络通信数据,并进行数据的篡改和嗅探来达到攻击的目的。
解决办法:
① 确保当前你所访问的网站使用了HTTPS
② 不要在公共网络上发送敏感信息
③ 如果网站使用了SSL,确保禁用了不安全的SSL/TLS协议
④ 不要点击恶意链接和电子邮件
(6)、window.opener
带有target=“_blank”跳转的网页拥有了浏览器window.opener的跳转权限,可能会被恶意利用,如跳转出本页面时,用高仿页替换掉原有页面。
解决办法:现在通用办法是所有的外链都替换为内部的跳转链接服务,点击链接时,先跳转内部地址,再有服务器redirect到外部地址。
35、跨域问题解决办法?
(1)、jsonp跨域:由于js的src不受跨域的限制,可以通过动态创建script方式进行跨域通信,只支持get请求。。
(2)、document.domain + iframe跨域:要求主域名相同。
(3)、window.name + iframe跨域
(4)、location.hash + ifrane跨域
(5)、postMessage跨域:包含发送消息的postMessage方法和接受信息的message事件。
(6)、跨域资源共享cors:允许浏览器向跨源服务器发送XHR请求,克服了ajax只能同源的限制,实现的关键是服务器。区分简单请求和非简单请求:
简单请求:浏览器自动在请求头中添加origin字段,用来说明此次请求来自哪个源,服务端需要添加access-control-allwo-origin字段,对应请求的origin字段值,或者设置为 * 表示接受任意域名请求。
非简单请求:请求方式为put、delete方法或者content-type是application/json。
(7)、websocket协议跨域:实现了浏览器与服务器全双工通信,并允许跨域通信(可以使用 socket.io)
(8)、node代理跨域
(9)、nginx代理跨域:通过nginx转发请求,把跨域的接口代理成本域的接口,然后转发到真正的请求上。
36、说说对SPA的理解,并说说优缺点
单页面应用一单页面加载完成,就不会因为用户的操作而重新加载页面或者跳转,对于切换操作主要是通过路由方式,对页面内容进行局部的刷新,避免了页面的重新加载。
优点:用户体验好,内容改变不需要加载整个页面,避免重复渲染;不重复加载,减小了服务器的压力;前后端分离,前端负责交互,后端负责数据
缺点:初次加载耗时较长,会一次性加载各种资源,虽然部分页面/组件按需加载;不利于SEO;不能使用浏览器的前进后退功能,需要自己进行管理。
以上是整理的一些比较基础的东西和平时工作中遇到的问题及解决办法,个别题目没有写答案或者只写了基本思路,也是给大家做个参考。
如果发现答案或者题目有问题,欢迎各位大佬指出并给予解答~码字不易,大家多多支持~