面试造火箭,工作拧螺丝!
在技术圈毕竟只有百分之一的人能进入BAT,百分之九九的小伙伴只能在普通公司做这普通的事情,此文没有BAT啥经验,都是基础。帮助小伙伴们快速梳理知识,不会涉及到具体的很细节的知识点,关注面试本身。公司一般会从以下5个方面(HTML5+CSS3/JS/框架/项目/工具)考察一个人的能力,此文总结了最近2-3年(成渝地区)常问的面试题,适合初中级(就是只要10K左右的小伙伴啦)前端工程师。
1、HTML(5)和CSS3方面
前端与后端数据交互的格式有哪些,为什么大部分现在都用json而不用xml。
答:XML:
知了哥 3岁
复制代码
JSON:{ name:”知了哥”,age:3} JSON书写方便节省字节,更轻量,前后台都有直接解析JSON的方法(JSON.stringfity/parse)使用方便。
Flex布局熟悉吗,说几个常用的属性。
答:这个几乎每天都在用,还是挺熟悉的。
display:flex
align-items 多个
align-content:单个
justify-content
justify-items
flex-direction
flex-wrap:
flex-basic:初始盒子宽度 flex
flex-grow:增长因子 200 4 40=160 1,1,1,2 1/5 40 flex
flex-shrink :缩减因子 200 60*4=240
说一下CSS盒模型
答:CSS的盒模型包含了一下几个内容margin,padding,border,content。 在计算盒子宽高的时候,IE和Chrome会有一些区别,IE算到border,Chrome的宽度只包含content区域,因此CSS3提供了box-sizing这个属性来修改。
答:*(has,not,target,root。。。。)通配符, ID,class,attr属性,element,子代( > + ~ ), UI状态伪类选择器(hover,active,link,seceted…,checked), 结构性伪类选择器(nth-child,fist-child,last,nth-of-type…before,after…)
!important > style > id > class > elemnet > 伪类和属性
请用5种方式实现元素垂直居中。
答:1、flex
2、Tranform
3、定位+margin负值(知道子节点宽高)
什么是BFC?垂直margin重叠是为什么?怎么解决这个问题?
答:概念:BFC全称Block Formatting Context ,中文意思为块级格式上下文。 通俗的来说:BFC是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子内部的元素无论如何翻江倒海,都不会影响到外部。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。比如清除浮动)并且在一个BFC中,块元素与行元素都会垂直的沿着其父元素的边框排列。
如何触发 BFC
1.浮动元素,float 除 none 以外的值
2.position的值不为static或者relative
3.display不为none
4.overflow 除了 visible 以外的值
BFC的应用
1.解决浮动塌陷问题 2.自适应两栏布局(我们还可以运用BFC可以阻止元素被浮动元素覆盖的特性来实现自适应两栏布局。方法:给没有浮动的元素加overflow:hidden。) 3.解决设置margin值重叠问题。
总结:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。它规定了元素与其他元素的关系和相互作用。
什么是浮动,有什么作用,有何副作用,以及如何清除浮动?
答:浮动是使用给节点添加float属性,最初的设计是用来实现文字环绕的。 添加了float的节点脱离文档流,同时触发节点的BFC,让节点往一个方向靠,并排成一行。 当一个父节点的子节点全部浮动,就会造成父节点高度塌陷, 解决的办法首先是可以给父节点主动添加高度值,再者利用只要有一个子节点不浮动原理来添加一个不浮动的节点(通常使用伪元素before,after),再者还可以触发父节点的bfc,常用的定位,或者overflow:hidden。
CSS里面有哪些相对单位?都是相对什么的?
答:REM,EM,VW,VH等 REM:相对于根节点html的font-size EM:父节点的font-size VW:视口的宽度为 100VW,相对于把视口分为100份。 VH:视口高度为100VH,同理
以上单位都可以在移动端做页面适配,但通常使用REM和VW
复制代码
fixed是相对于谁定位的?如果加上transform会出现问题吗?
答:fixed定位相对于浏览器视口来定位的 添加上transform以后,fixed定位会失效(现在这个bug已经不存在啦! )。如果fixed元素的祖先有transform属性,则fixed元素会相对与这个祖先计算,而不是视口(问题还在)。
为什么不推荐用style内联元素?内联元素有什么缺点?(css文件可以缓存)
答:首先是style是节点的属性,不能被缓存;代码的可读性和可维护性相对弱一些,特别是多人协作开发的时候。但是如果一个页面的style样式足够少的时候,可以使用style元素,因为一次请求最多携带14K的数据,如果足够小,还可以节约一次请求。
简单描述http或https协议,以及为什么要三次握手?什么是长链接
答:http(https)是超文本传输协议,基于TCP请求与相应的模式,无状态的,是目前主流的web传输协议。一般包含请求头,请求体,响应头等 目前http协议已经发展到2.0阶段,支持长链接Connection: keep-alive,断点续传,cache 缓存策略,多路复用,服务器推送等。 https相对于http更安全,增加了证书SSL加密,端口是433。
三次握手其实就是三次网络连接,客户端携带SYN=1,Seq = x信息给服务端,服务端接受到后,服务端就知道了,有一个客户端要链接我,然后服务器就会开启一个TCP socket的端口,然后返回数据给前端也是SYN=1,SEQ=Y,ACK = x+1,客户端接受到后,在发一个seq,和ACK+1.主要是为了防止开启无用的链接,或者网络延迟丢包,服务器无法确定到底客户端有没有收到消息
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。 Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。 为何需要长链接?长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
http常见状态码有哪些?301和302的区别是什么?304是指什么?
答: 404:找不到资源; 500:服务器内部错误; 200:请求成功,并返回数据; 301:永久重定向; 302: 临时移动,可使用原有URI; 304:资源未修改,可使用缓存; 400:请求语法错误(一般为参数错误); 403:没有权限访问。。。等
浏览器页面渲染的流程是什么(输入url后页面发生什么)?
答: 首先dns解析IP,建立tcp链接下载资源,构建dom树,当遇到link标签,会下载并执行解析css(不会阻止dom树的构建)当遇到script标签的是,dom树构建会暂停,下载并执行完js才会继续(defer(下载延迟执行),async(异步下载并执行)) 然后再布局和绘制(layout,paint)最后在 render
什么是reflow与repain?哪些操作会触发reflow,如何避免
答:reflow:回流,当元素的尺寸、DOM结构发生改变时,浏览器会重新渲染页面,称为回流。 repain:重绘,当元素的样式(布局不发生,color,opacity,visibility)发生改变的时候。
以下常见操作都会触发:
复制代码
浏览器窗口大小改变 元素尺寸、位置、内容发生改变 元素字体大小变化 添加或者删除可见的 dom 元素 激活 CSS 伪类(例如::hover)等
通过class的方式集中改样式,documentFragment缓存节点,避免使用table、calc,做动画的节点脱离文档流(新创建图层)。总结:减少DOM操作!
HTML5常用的特性(API)有哪些?你用过哪些?
答:语义化标签(header,nav等),video、audio,获取dom的方式(queryselector),websocket Canvas,svg,requestAnimationFrame,Geolocation,stroage ,notification,file API,Orientation API用于检测手机的摆放方向等
请列举出几个常见的浏览器兼容性问题?
答:现在市面上IE678基本已经停止使用了,所以尽量不要说这方面的兼容性。 有些浏览器支持的,有些呢 不支持;或者是支持的方式不一致。
1、不同浏览器的默认margin和padding不一致
2、图片的默认间距不一致
3、获取视口的宽高window.innerheight/width
4、CSS3的动画,过渡,渐变,flex也有,grid
5、Canvas,SVG
6、IE9以下不能的opacity,使用filter: alpha(opacity = 50);
7、event.offsetX/Y
8、绑定事件IE9才支持(addEventListener)
什么是浏览器缓存(知道什么是 强缓存 和 协商缓存)?
答:当浏览器访问过后的资源,会被浏览器缓存的本地,当下次在访问页面的时候,如果没有过期,直接读取缓存,加快浏览器的加载效率。
http缓存机制:1、Expires:通过设置最大缓存时间,当时间超过了就去服务器下载, 2、http1.1,cache-control:max-age = time ,当time过期后,检测etag 带上etag往服务器发请求,如果etag没变,直接告诉浏览器读本地缓存,如果没有etag 就会 检测 Last-Modified,判断 如果 上一次更改的时候,距离本次访问时间比较久,说明文件没有发生改变,返回304。
强缓存就是当前访问时间还在设置的最大时间范围内。 协商缓存就是时间过了,通过检查etag或者last-modifed来使用缓存的机制。
说一下浏览器垃圾回收机制
答: 老:标记清除算法,GC会检测当前对象有没有被变量所引用,如果没有就回收。 新: Scavenge ,把内存空间分为两部分,分别为 From 空间和 To 空间。当一个空间满了以后,会把空间中活动对象转移到另外一个空间,这样互换。
什么是事件委托
答:事件委托本质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理。使用事件代理我们可以不必要为每一个子元素都绑定一个监听事件,这样减少了内存上的消耗,也是常见的JS性能优化的一个点。
什么是响应式布局?如何实现
答:书写一套CSS样式适配PC和移动端,让PC和移动端都能正常的浏览器页面。 使用mate 控制viewport,再配合media query 的 screen 来设置断点样式。 注意:做相应式 不能使用固定单位,要使用max-width、min-width等能自动缩放的单位。
2、JS方面(ES6/ES7)
在JS中什么是面向对象程序设计,面向对象设计优点?
答:在JS中面向对象更多说的是通过构造函数或者class封装一个独立的功能,以达到代码的复用。 面向对象的三个特点: 封装:通过对象把属性和方法封装起来,相似对象的话采用构造函数或者类new得到。 继承:通过混合继承(构造函数和原型)的方式,可以达到属性和方法的复用。 多态:通过对象属性覆盖,可以让继承的对象拥有更多行为。
面向对象的程序设计是组织代码的方式,能提升开发效率和代码的可维护性。
什么是原型、原型链,有什么作用?
答: 原型:每一个对象都与另一个对象相关联,那个关联的对象就称为原型。
意义:函数Person有一个属性prototype,指向一个对象,对于普通函数来说没多意义,对于构造函数就有作用了,当使用new操作符时,会把Person.prototype(原型对象)赋值给实例的__proto__(原型实例)属性,再通过原型查找机制所有的Person产生的实例都可以访问到挂载到原型上的方法,这样就达到了函数的复用,减少内存开销。
原型查找机制,通过实例调用一个属性的时候,先在实例自身对象上查找,如果实例本身上没有,就去自动去实例的__proto__上去查找。
原型链:每一个对象,都有一个原型对象与之关联,这个原型对象它也是一个普通对象,这个普通对象也有自己的原型对象,这样层层递进,就形成了一个链条,这个链条就是原型链。通过原型链可以实现JS的继承,把父类的原型对象赋值给子类的原型,通过原型查找机制,这样子类实例就可以访问到父类原型上的方法了。
Person.prototype.constructor == Person
Person.prototype.proto.constructor == Object
Person.prototype.proto == Object.prototype
Object.prototype.proto == null
复制代码
如何实现继承(ES5/ES6)?
答:
10 function Anima(name){ //父类
11 this.name = name;
12 }
13
14 Anima.prototype.sayName = function(){
15 console.log(this.name)
16 }
17
18 function Person(name,age){ //子类
19 Anima.call(this,name);
20 this.age = age;
21 }
22
23 Person.prototype = Object.create(Anima.prototype, {
24 constructor: {
25 value: Person,
26 enumerable: false
27 }
28 })
29
30
31 var p = new Persion(“haha”,12);
32
33 Extends //ES6
复制代码
什么是作用域以及作用域链?
答:作用域是指程序源代码中定义变量的区域,限定一个变量可访问范围的,作用域的本质是对象。JS采用的词法作用域,在书写代码的时候(定义函数的时候),作用域就已经确定好了。 在ES6环境下,包含3个作用域,全局globel,函数作用域,快级作用域( {} ) (eval) 作用域链:当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。 用途是保证对执行环境有权访问的所有变量和函数的有序访问。本质为执行上下文的scope属性,存储所有的变量,包括局部与全局,控制变量的使用顺序。 参考文献:https://github.com/mqyqingfeng/Blog/issues/6
var b = 10; //1:输出?2:改造代码输出10或20
(function b(){
b = 20;
console.log(b);
})();
var b = 10; (function b(b) { 在这个函数b是一个常量,在函数b内部是可以使用的,但是不能修改,如果加上use strict 严格模式就会报错。 window.b = 20; console.log(b) //输出10 })(b)
var a = 10; (function () { console.log(a) a = 5 console.log(window.a) var a = 20; console.log(a) })()
复制代码
复制代码
什么是闭包,闭包的好处和坏处分别是?
答:当函数可以记住并访问外部作用域时,就产生了闭包,那个外部作用域就称为闭包。
形成的原因:外层函数的作用域对象无法释放。 作用:为了封装对象的私有属性和私有方法,避免全局变量的污染(保护一个变量,重用一个变量)。坏处:使用不当,会造成内存泄漏。
大白话来解释:函数A和函数B,当内部函数B引用了A 的局部变量时,函数A 称为闭包 原因是:JS是词法作用域,B的作用域链上有对A执行环境的引用(这个执行环境用函数来表示),A的执行环境AO就不会回收。
for (var i = 0; i< 5; i++){ //改造代码,每间隔一秒 输出 0-4
setTimeout(() => {
console.log(i);
}, 1000)
}
复制代码
什么是this,this的常用方式有哪些?如何改变this的指向?
答:简单的理解:this指向就是当前的执行上下文对象的一个引用。 JS在运行过程中会产生执行上下文环境(context),context记录了包含函数在哪里被调用,作用域链,OA,this等信息,this是context的其中一个属性,会在函数的执行过程中使用,它指代的上下文对象取决于函数调用的各种条件。通常this在函数中使用。 设计的目的:this提供了一种优雅的方式来隐式的传递一个对象的引用,所以在函数中使用this可以更加方便的复用函数。
This的使用场景:
1、全局使用 this === window 很少使用,函数体包含严格模式时为undefined
2、函数当中 在全局调用这个fn() this === window
3、在方法当中使用 this === 调用当前这个函数的所在的对象啊
4、构造函数this执向的是 new 创建出来的实例对象啊
5、DOM事件处理函数中的this,指向当前的DOM节点 6、通过 bind,call,apply 操作符来显示的设置 this的指向 bind:绑定函数里面的this,返回新函数, call,apply:绑定并执行这个函数,前者传参是“,”隔开,后者是数组
7、ES6的箭头函数 箭头函数没有自己的this,父作用域(父函数)的this
var x = 3;
var foo = {
x: 2,
baz: {
x: 1,
bar: function() {
return this.x;
}
}
}
var go = foo.baz.bar;
go()?
foo.baz.bar()?
//综合面试题
function Foo() {
Foo.a = function() {
console.log(1)
}
this.a = function() {
console.log(2)
}
}
Foo.prototype.a = function() {
console.log(3)
}
Foo.a = function() {
console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
复制代码
手写bind,call,apply函数
答案:以上都是Function原型上的方法。
Function.prototype.myCall = function(context,…args){//绑定并执行 //执行函数 var fn = this; context.fn = fn; context.fn(…args); delete context.fn }
Function.prototype.myBind = function(context){//绑定返回新的执行函数
//判断调用者是不是函数
if(typeof this != ‘function’){
throw new Error(“Error”)
}
//截取传递的参数
let args = […arguments].slice(1);
var _this = this;//保存一下当前的调用者
return function F() {
return _this.apply(context,args.concat([…arguments]))
}
}
function polyfillBind (fn, ctx) { //尤大
function boundFn (a) {
var l = arguments.length;
return l ? l > 1? fn.apply(ctx, arguments): fn.call(ctx, a): fn.call(ctx)
}
boundFn._length = fn.length;
return boundFn
}
复制代码
复制代码
复制代码
什么是深、浅拷贝,请写出代码
答:浅拷贝,就是复制一个对象,当对象的属性值没有引用类型的时候。 Object.assign 迭代(for…in for…of object.enteries) 扩展运算符…,JSON.parse 等 let skuObj = {…this.goodsSku,…{color,size,mate,from}} //浅拷贝一个对象 let skuObj = Object.assign({},this.goodsSku,{color,size,mate,from}) 反之如果对象中还有引用类型,连着引用类型一并拷贝称为深拷贝。 JSON对象的方法(会忽略到值为函数和undefined的属性),递归
function deepCopy(obj){ //判断对象的类型 var newObj = Array.isArray(obj)?[]:{}; if(obj && typeof obj == “object”){ //迭代 for(var key in obj){ if(typeof obj[key] == ‘obj’){ newObj[key] = deepCopy(obj[key]) }else{ newObj[key] = obj[key] }
} } return newObj }
什么是Ajax,如何封装一个Ajax?Get请求与 Post请求的区别?
答:Ajax的全称是异步的js与xml技术,通过它与后台服务器进行数据交换,可以使网页实现异步更新,言外之意是在不重新加载整个页面的情况下,对网页进行局部更新。
1.nex xmlhttprequset对象
2.open(method,url,true)
3.绑定redaystatechange事件
4.调用send方法,如果是post请求,可以传递参数
复制代码
前端的请求方式除了常用Get和Post,还有update,delete,put等(restful api设计) 三分方面来说:能不能缓存,传参数方式,传参大小
GET 请求可被缓存,保留在浏览器历史记录中 ,请求的参数是直接跟在URL上,因此不应传递敏感数据。 GET 请求有长度限制(2048字符),IE和Safari浏览器限制2k;Opera限制4k;Firefox,Chrome限制8k 。 GET 请求通常只应当用于从后台获取数据。
POST 请求不会被缓存,不会保留在浏览器历史记录中 POST 请求对数据长度没有要求。 POST 请求通常用于往后台提交数据。
说一些ES6、ES7新特性。
答: let /const定义变量(块级作用域);解构,从对象和数组中提取值;箭头函数;字符串模版;扩展运算符…;对象的简写;module;promise(async);class;对原生对象的扩展(新增加了很多方法) ;for-of (Object.keys,values,entries等);Symbal(); 不常用的proxy,reflect,generate函数,map和set
什么是Promise,如何使用?
答:Promise对象是ES6异步编程一种解决方案,通常用来解决异步嵌套和多异步同时完成回调等问题。我的理解就是:在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了。 Promise是一个构造函数,相当于一个容器,把异步代码包裹在里面,promise有三个状态(pending(进行中)、fulfilled(已成功)和rejected(已失败))初始化为pending,当异步请求成功后调用resolve函数,状态从pending—>fulfilled,失败的时候调用reject,状态从pending—>rejected。状态不可逆。 缺点:书写麻烦,不能实现异步代码,同步执行的需求(配合async函数使用即可)
什么是跨域,解决跨域常用的方式有哪些?
答:跨域是浏览器端行为,根据同源策略,当请求的协议、域名、端口只有一个不同,就会跨域,跨域是浏览器为了安全存在的机制,浏览器会把跨域请求的数据去掉,同时报错。 在实际开发难免会出现跨域的情况,解决方案通常有
1.JSONP技术,利用了script的src属性没有跨域限制,img的src也没有跨域限制
2.CORS,当在相应头信息中添加access-control-allow-origain属性,浏览器读取到就会允许返回数据。后台配置,或者下一个浏览器插件即可。
3.后台代理(Node)
4.Iframe域的提升(很少)
什么是函数的防抖、节流,并手写基本代码
答:防抖和节流都是为了提升运行效率,减少函数的执行次数。 防抖:把多次函数执行,合并成一次执行。给定一个间隔时间,当两次函数执行的间隔时间大于了给定的间隔时间,就执行一次函数。
function debounce(fn,delay){ //fn真正执行的函数,delay间隔时间
var timer = null;
return function(){
var args = arguments;
var that = this;
if(timer) clearTimeout(timer)
timer = setTimeout(function(){
fn.apply(that,[…arguments])
},delay)
}
}
复制代码
节流 :减少函数执行的频率。规定一个单位时间,在单位时间内触发一个事件回调,触发时超过间隔时间则执行,否则不执行。
function throttle(fn,gapTime){
let _lastTime = null;
return function(){
var that = this;
var args = arguments;
let _nowTime = + new Date();
if(_nowTime-_lastTime > gapTime || !_lastTime){
fn.apply(that,args);
_lastTime = _nowTime;
}
}
}
复制代码
什么事件循环(Event Loop)?
答:js是非阻塞单线程语言,js在执行过程中会产生执行环境,执行环境会被顺序的加入到执行栈,当遇到异步任务,会添加到task队列当中,执行同步栈,当同步栈执行完以后,event loop 就会从异步task队列当中提取要执行的代码放到执行栈中。这个一个过程称为事件循环。所以JS的异步还是同步过程。
console.log(‘script start’)
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
}).then(function() {
console.log('promise1')
}).then(function() {
console.log('promise2')
})
console.log('script end')
//输出结果?
复制代码
前端安全你有了解吗?什么是XSS攻击和CSRF 跨站请求伪造?怎么预防?
答:前端的安全问题,在工作过程中会注意这些问题。 1、XSS 跨站脚本漏洞攻击,通常不信任用户的输入,转义输入输出内容(encodeURIComponent),括号 尖括号等。利用用户对站点的信任
2、CSRF 跨站请求伪造
是一种挟制用户在当前已登录的web应用中执行非本意的攻击
大白话:利用用户登录态发起恶意请求
网站对用户的信任
复制代码
添加验证码(体验稍微差一些),不让第三方访问cookie 对cookie设置 samesite, 请求验证 加 token ,
3、密码问题:对密码进行加密(MD5等)
如何处理精度丢失问题?
答:产生的原因:JS使用64位表示Number类型一个数字。
计算机先把10进制转位2进制,0.1和0.2转成二进制的时候还会无限循环,由于有52位位数的限制,多余的会被裁掉,所以在进制之间转换就会丢掉精度。 通常可以把小数乘以倍数转成正整数,计算完后再转回去。 parseFloat((0.1 + 0.2).toFixed(10))
前端常用请求数据的方式有哪些,并说出各自的区别。
答:前端进行网络请求常用的form,Ajax,fetch 常用的库文件Jquery或者axios等。
Form提交数据页面会刷新,使用体验不佳。
Ajax是一个综合技术,可以实现异步更新页面内容。使用起来方便,通常使用JQ的封装,会额外的JS加载代价。
Fetch是新的API,比较底层。目前浏览器兼容性问题多一些,比如老版本不会携带cookie,不能直接传递JS对象作为参数,不支持JSONP等 “fetch” in window
Websocket
复制代码
如何检测一个对象一定是数组?
答: 1、Object.prototype.toString.call(),前提是toString方式没有被重写。 2、instanceof 内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。 [] instanceof Object; // true Array.prototype === arr. 「 proto 」 3、Array.isArray() ES5新增的方法,兼容性稍微差一些。
JS加载会阻塞页面渲染吗?会的话该怎么解决呢?
答:会 defer:并行下载,在页面解析完后执行,会按照script的顺序执行。(常用) async:异步下载代码,下载完毕后立即执行代码,不会按照页面的script顺序。
常见前端性能优化有哪些?
答: 1:加载优化
CDN,文件压缩混淆合并,按需加载(异步组件),
前端缓存(url,dom,localstore,cookie),浏览器缓存(cache-control,exprices),
图片懒加载DNS预先解析dns-prefetch,服务器渲染 nuxt,next(SEO)
2:脚本优化
减少合并DOM操作(createDocumentFragment),CSS3代替js动画,缓存变量,
用requestAnimationFrame代替setTimeout,减少reflow与repain,事件代理,
开启GPU渲染tranfrom:translateX(0);防抖和节流
3:图片优化
雪碧图(减少请求),使用SVG和iconfont(字体图片)代替图片,图片压缩
复制代码
复制代码
复制代码
正则表达式
答:正则表达式在面试中出现的概率很高
参考文献: http://jquery.cuishifeng.cn/regexp.html
String.prototype.trim = function(){
return this.replace(/(^\s*)|(\s*$)/g,’’)
}
复制代码
reg = /[^\s]+/g; //匹配非空格正则
let resultarr = [];
str.split(/\n/).forEach((item,index)=>{
return resultarr.push(item.match(reg));
})
复制代码
var money = 141412301.11
function current(money){
var mon = money+’’;
let [yuan] = mon.split(’.’)
if (yuan.length<=3) {return mon}
var reg = /(\d)(?=(\d{3})+(?!\d))/g; //找到某一个字符,这个字符后面要有多个3个连续的数字
//并且不以数字结尾
return mon.replace(reg,’$1,’)
}
复制代码
常用的前端缓存数据(不是浏览器缓存)方式有哪些?说出他们的优缺点。
答: URL:存储有限,数据直接放到url上面,不能放敏感信息 Cookie:存储有限,每次请求都会带上cookie,会造成请求资源浪费 DOM节点:H5标准通过data-xx为节点添加自定义属性,存储有限,DOM操作的时候非常方便。 本地存储(storage):存储5M左右,可以永久存储和会话存储,api方便,只能存字符串。 indexDB:前端数据库,键值对的方式存储,可以做离线应用,学习成本高,使用场景少。
谈谈你对前端模块化理解?简单描述一下AMD,CMD,ES6(module)之间的区别
答: 前端的模块化是把一个js文件看成一个模块,然后对外暴露方法和属性。 在早些年浏览器不支持模块化,社区有AMD,CMD两个标准,把代码封装在一个函数内部,通过请求的方式去动态的加载js文件。 AMD与CMD两者的区别为,前者为异步预先加载代码并执行;后者为异步加载,当使用到模块提供的函数的时候,在执行(延迟执行)。 ES6以后开始JS开始支持模块化,之前的模块化使用就很少了。
==判断的转化规则?
答: 当左右两边数据类型不相同的情况下,对象和字符串比较,是对象转字符串;undefined==null;其他情况都是把值转成数字,而对象转成数字要先经过toString转成字符串,再转成数字。
1.if(a1 && a2 && a==3){
2. console.log(ok)
3.}
复制代码
//思路一,为把a定义为对象{},当对象与数字比较的时候,会先调用toString方法,我们给当前的对象添加一个私有的tostring方法即可,就不会去调用原型上的方法了。 //思路二,使用属性劫持 Let n = 0 Object.defineProperty(window,a,{ get(){ return ++n } }) var a = { n:0, toString(){ return ++this.n } }
通过new操作符调用构造函数,会经历哪些阶段?
答:1、创建一个新的对象; 2、链接到原型; 3、将构造函数的this指向这个新对象,执行构造函数的代码,为这个对象添加属性,方法等; 4、返回新对象。
请写出以下代码的输出,并解释
数组和字符串有哪些原生方法?(包括常用的ES6/7)
答:详见文档(这些常用方法都记不住!要什么自行车)
什么是polyfill?
答:Polyfill 指的是用于实现浏览器并不支持的原生 API 的代码。 比如说 Object.assign()是很多现代浏览器都支持的原生 Web API,但是有些古老的浏览器并不支持,那么假设有人写了一段代码来实现这个功能使这些浏览器也支持了这个功能,那么这就可以成为一个 Polyfill。