前端技术千千万,到底如何才能快速掌握?!
作者
郭东东
本文经授权转载自前端小专栏(ID:QianDuanXiaoZhuanLan)
引言
当下,正面临着近几年来的最严重的互联网寒冬,听得最多的一句话便是:相见于江湖。缩减HC、裁员不绝于耳,大家都是人心惶惶,年前如此,年后想必肯定又是一场更为惨烈的江湖厮杀。但笔者始终相信,寒冬之中,人才更是尤为珍贵。只要有过硬的操作和装备,在逆风局下,同样也能来一波收割翻盘。
笔者也是年前经历了一番厮杀,最终拿到多家大厂的offer。在闭关修炼的过程中,整理出了一套面试秘籍供自己反复研究,后来给了多位有需要的兄台,均表示相当靠谱,理应在这寒冬之中回报于社会。于是决定花点精力整理成文,让大家能比较系统的反复学习,快速提升自己。
面试固然有技巧,但绝不是伪造与吹流弊,通过一段短时间沉下心来闭关修炼,出山收割,步入大厂,薪资翻番,岂不爽哉?
修炼原则
想必大家很厌烦笔试和考察知识点。因为其实在平时实战中,讲究的是开发效率,很少会去刻意记下一些细节和深挖知识点,脑海中都是一些分散的知识点,无法系统性地关联成网,一直处于时曾相识的状态。不知道多少人和博主一样,至今每次写阻止冒泡都需要Google一番如何拼写。
以如此的状态,定然是无法在面试的战场上纵横的。其实面试就犹如考试,大家回想下高考之前所做的事,无非就是理解和系统性关联记忆。本秘籍的知识点较多,花点时间一个个理解并记忆后,自然也就融会贯通,无所畏惧。
由于本秘籍为了便于记忆,快速达到应试状态,类似于复习知识大纲。知识点会尽量的精简与提炼知识脉络,并不去展开深入细节,面面俱到。有兴趣或者有疑问的童鞋可以自行Google下对应知识点的详细内容。
CSS
1.盒模型
页面渲染时,dom元素所采用的布局模型。可通过box-sizing进行设置。根据计算宽高的区域可分为:
content-box(W3C标准盒模型)border-box(IE盒模型)padding-boxmargin-box2.BFC
格式化上下文,是一个独立的渲染区域,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。
IE下为Layout,可通过zoom:1触发
触发条件根元素positon:absolute/fixeddisplay:inline-block/tablefloat元素ovevflow!==visible规则:属于同一个BFC的两个相邻Box垂直排列属于同一个BFC的两个相邻Box的margin会发生重叠BFC中子元素不会超出他的包含块BFC的区域不会与float的元素区域重叠计算BFC的高度时,浮动子元素也参与计算文字层不会被浮动层覆盖,环绕于周围应用:阻止margin重叠可以包含浮动元素——清除内部浮动(清除浮动的原理是两个div都位于同一个BFC区域之中)自适应两栏布局可以阻止元素被浮动元素覆盖3.层叠上下文
元素提升为一个比较特殊的图层,在三维空间中(z轴)高出普通元素一等。
触发条件flextransformopacticyfilterwill-change-webkit-overflow-scrolling根层叠上下文(html)positioncss3属性层叠等级:层叠上下文在z轴上的排序在同一层叠上下文中,层叠等级才有意义z-index的优先级最高
4.居中布局
水平居中行内元素:text-align:center块级元素:margin:0autoabsolute+transformflex+justify-content:center垂直居中line-height:heightabsolute+transformflex+align-items:centertable水平垂直居中absolute+transformflex+justify-content+align-items5.选择器优先级
!important行内样式#id.classtag*继承默认选择器从右往左解析6.去除浮动影响,防止父级高度塌陷
通过增加尾元素清除浮动:after/br:clear:both创建父级BFC父级设置高度7.link与
import的区别link功能较多,可以定义RSS,定义Rel等作用,而
import只能用于加载css当解析到link时,页面会同步加载所引的css,而import所引用的css会等到页面加载完才被加载import需要IE5以上才能使用link可以使用js动态引入,import不行8.CSS预处理器(Sass/Less/Postcss)CSS预处理器的原理:是将类CSS语言通过Webpack编译转成浏览器可读的真正CSS。在这层编译之上,便可以赋予CSS更多更强大的功能,常用功能:
嵌套变量循环语句条件语句自动前缀单位转换mixin复用面试中一般不会重点考察该点,一般介绍下自己在实战项目中的经验即可~
9.CSS动画
transition:过渡动画transition-property:属性transition-duration:间隔transition-timing-function:曲线transition-delay:延迟常用钩子:transitionendanimation/keyframesforwards:停止时,保留最后一帧backwards:停止时,回到第一帧both:同时运用forwards/backwardsalternate:反向播放infinite:循环动画animation-name:动画名称,对应
keyframesanimation-duration:间隔animation-timing-function:曲线animation-delay:延迟animation-iteration-count:次数animation-direction:方向animation-fill-mode:静止模式常用钩子:animationend动画属性:尽量使用动画属性进行动画,能拥有较好的性能表现translatescalerotateskewopacitycolor经验通常,CSS并不是重点的考察领域,但这其实是由于现在国内业界对CSS的专注不够导致的,真正精通并专注于CSS的团队和人才并不多。因此如果能在CSS领域有自己的见解和经验,反而会为相当的加分和脱颖而出。
JavaScript
1.原型/构造函数/实例
原型(prototype):一个简单的对象,用于实现对象的属性继承。可以简单的理解成对象的爹。在Firefox和Chrome中,每个JavaScript对象中都包含一个__proto__(非标准)的属性指向它爹(该对象的原型),可obj.__proto__进行访问。构造函数:可以通过new来新建一个对象的函数。实例:通过构造函数和new创建出来的对象,便是实例。实例通过__proto__指向原型,通过constructor指向构造函数。说了一大堆,大家可能有点懵逼,这里来举个栗子,以Object为例,我们常用的Object便是一个构造函数,因此我们可以通过它构建实例。
//实例constinstance=newObject()
则此时,实例为instance,构造函数为Object,我们知道,构造函数拥有一个prototype的属性指向原型,因此原型为:
//原型constprototype=Object.prototype
这里我们可以来看出三者的关系:
实例.__proto__===原型原型.constructor===构造函数构造函数.prototype===原型原型.constructorr===构造函数
放大来看,我画了张图供大家彻底理解:
2.原型链:
原型链是由原型对象组成,每个对象都有__proto__属性,指向了创建该对象的构造函数的原型,__proto__将对象连接起来组成了原型链。是一个用来实现继承和共享属性的有限的对象链。
属性查找机制:当查找对象的属性时,如果实例对象自身不存在该属性,则沿着原型链往上一级查找,找到时则输出,不存在时,则继续沿着原型链往上一级查找,直至最顶级的原型对象Object.prototype,如还是没找到,则输出undefined;属性修改机制:只会修改实例对象本身的属性,如果不存在,则进行添加该属性,如果需要修改原型的属性时,则可以用:b.prototype.x=2;但是这样会造成所有继承于该对象的实例的属性发生改变。3.执行上下文(EC)
执行上下文可以简单理解为一个对象:
它包含三个部分:变量对象(VO)作用域链(词法作用域)this指向它的类型:全局执行上下文函数执行上下文eval执行上下文代码执行过程:创建全局上下文(globalEC)全局执行上下文(caller)逐行自上而下执行。遇到函数时,函数执行上下文(callee)被push到执行栈顶层函数执行上下文被激活,成为activeEC,开始执行函数中的代码,caller被挂起函数执行完后,callee被pop移除出执行栈,控制权交还全局上下文(caller),继续执行4.变量对象
变量对象,是执行上下文中的一部分,可以抽象为一种数据作用域,其实也可以理解为就是一个简单的对象,它存储着该执行上下文中的所有变量和函数声明(不包含函数表达式)。
活动对象(AO):当变量对象所处的上下文为activeEC时,称为活动对象。
5.作用域
执行上下文中还包含作用域链。理解作用域之前,先介绍下作用域。作用域其实可理解为该上下文中声明的变量和声明的作用范围。可分为块级作用域和函数作用域
特性:
声明提前:一个声明在函数体内都是可见的,函数优先于变量非匿名自执行函数,函数变量为只读状态,无法修改constfoo=1(functionfoo(){foo=10//由于foo在函数中只为可读,因此赋值无效console.log(foo)}())//结果打印:foo(){foo=10;console.log(foo)}
6.作用域链
我们知道,我们可以在执行上下文中访问到父级甚至全局的变量,这便是作用域链的功劳。作用域链可以理解为一组对象列表,包含父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数。
由两部分组成:[[scope]]属性:指向父级变量对象和作用域链,也就是包含了父级的[[scope]]和AOAO:自身活动对象如此[[scopr]]包含[[scope]],便自上而下形成一条链式作用域。
7.闭包
闭包属于一种特殊的作用域,称为静态作用域。它的定义可以理解为:父函数被销毁的情况下,返回出的子函数的[[scope]]中仍然保留着父级的单变量对象和作用域链,因此可以继续访问到父级的变量对象,这样的函数称为闭包。
闭包会产生一个很经典的问题:多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。解决变量可以通过函数参数的形式传入,避免使用默认的[[scope]]向上查找使用setTimeout包裹,通过第三个参数传入使用块级作用域,让变量成为自己上下文的属性,避免共享8.script引入方式:
html静态script引入js动态插入scriptscriptdefer:异步加载,元素解析完成后执行scriptasync:异步加载,与元素渲染并行执行9.对象的拷贝
浅拷贝:以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响Object.assign展开运算符(...)深拷贝:完全拷贝一个新对象,修改时原对象不再受到任何影响具有循环引用的对象时,报错当值为函数或undefined时,无法拷贝JSON.parse(JSON.stringify(obj)):性能最快递归进行逐一赋值10.new运算符的执行过程
新生成一个对象链接到原型:obj.__proto__=Con.prototype绑定this:apply返回新对象11.instanceof原理
能在实例的原型对象链中找到该构造函数的prototype属性所指向的原型对象,就返回true。即:
//__proto__:代表原型对象链instance.[__proto__...]===instance.constructor.prototype//returntrue
12.代码的复用
当你发现任何代码开始写第二遍时,就要开始考虑如何复用。一般有以下的方式:
函数封装继承复制extend混入mixin借用apply/call13.继承
在JS中,继承通常指的便是原型链继承,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。
最优化:圣杯模式varinherit=(function(c,p){varF=function(){};returnfunction(c,p){F.prototype=p.prototype;c.prototype=newF();c.uber=p.prototype;c.prototype.constructor=c;}})();
使用ES6的语法糖class/extends14.类型转换
大家都知道JS中在使用运算符号或者对比符时,会自带隐式转换,规则如下:
-、*、/、%:一律转换成数值后计算+:数字+字符串=字符串,运算顺序是从左到右数字+对象,优先调用对象的valueOf-toString数字+boolean/null=数字数字+undefined==NaN[1].toString()===1{}.toString()===[objectobject]NaN!==NaN、+undefined===NaN15.类型判断
判断Target的类型,单单用typeof并无法完全满足,这其实并不是bug,本质原因是JS的万物皆对象的理论。因此要真正完美判断时,我们需要区分对待:
基本类型(null):使用String(null)基本类型(string/number/boolean/undefined)+function:直接使用typeof即可其余引用类型(Array/Date/RegExpError):调用toString后根据[objectXXX]进行判断很稳的判断封装:
letclass2type={}ArrayDateRegExpObjectError.split().forEach(e=class2type[[object+e+]]=e.toLowerCase())functiontype(obj){if(obj==null)returnString(obj)returntypeofobj===object?class2type[Object.prototype.toString.call(obj)]
object:typeofobj}
16.模块化
模块化开发在现代开发中已是必不可少的一部分,它大大提高了项目的可维护、可拓展和可协作性。通常,我们在浏览器中使用ES6的模块化支持,在Node中使用