我的总结的比较全面的前端面试知识点。主要是一些我的认为面试时容易考到以及平时须要注意的一些知识点。javascript
本人只是对这些知识进行了一个大概的总结,还有一部分技术还没开始涉及,后期会持续添加。若是须要进行深刻了解能够根据知识点查询相关的技术文章。css
本文涵盖了如下各个方面的知识:html
HTML, CSS, JS基础知识前端
网站性能优化知识html5
前端项目自动化构建相关知识java
算法相关知识jquery
网络与HTTP协议相关知识css3
前端的安全相关知识git
插件编写相关知识github
JS模块化编程相关知识
Github Repo:
https://github.com/Erichain/Front-End-Interview-Points
持续更新中。欢迎fork和star进行完善。
混杂模式
标准模式
准标准模式
去掉或者丢失样式的时候可以让页面呈现出清晰的结构
有利于SEO:和搜索引擎创建良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来肯定上下文和各个关键字的权重
方便其余设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页
便于团队开发和维护,语义化更具可读性,是下一步网页的重要动向,遵循W3C标准的团队都遵循这个标准,能够减小差别化
块级:div, ul, li, ol, table, th, tbody, tfoot, tr, pre, fieldset, form, h1-6, p等
a, abbr, b, br, code, em, img, input, label, select, textarea, strong等
如何在不使用JS的状况下刷新页面(http-equiv="refresh", content="time")
设置页面缓存
移动端设置
etc.
标签嵌套层级不要太深,标签尽可能简洁化.如懒加载后将data属性去除
大量图片的懒加载策略,以及一些元素利用ajax在onload后实行延迟加载
对一些js的异步加载
使用空标签设置clear: both;
为父级元素设置overflow: hidden;
(利用BFC的原理)
使用伪元素,为要清除浮动的元素添加.clearfix
类(推荐)
使用min-height: contain-floats;
(不推荐,兼容性很差)
触发条件
position
属性不为static
或者relative
float
属性不为none
非块级的块级元素(inline-block, table-cell)
overflow
不为visible
特性
内部的Box会在垂直方向,从顶部开始一个接一个地放置
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生叠加
BFC的区域不会与float box叠加
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
计算BFC的高度时,浮动元素也参与计算
用处
解决margin边距叠加问题。为元素单首创建一个BFC来防止外边距的折叠
布局
清除浮动。为包含浮动元素的container建立BFC来清除浮动
总宽度 = margin+padding+border+content,IE的盒子模型的宽度不计padding和border
css3的box-sizing
属性,详见https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
content-box,border和padding不计算入width以内
border-box,border和padding计算入width以内
定位和浮动的区别
何时使用定位,何时使用浮动
可继承的样式
font-size
font-family
color
text-indent
条件hack
<!--[if IE]><![endif]-->
属性hack
_
IE6
*+
IE7
+
IE6/7
.
IE8
选择符hack
*
IE7
_
IE6
减小请求
双飞翼布局
圣杯布局
行内样式 > 内联样式 > 外部样式,ID > Class > Element
设置了!important
的样式优先级更高
link属于XHTML标签,而@import是CSS提供的
页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载
@import只在IE5以上才能识别,而link是XHTML标签,无兼容问题
link方式的样式的权重 高于@import的权重
设置父元素font-size
为0,再对里面的文字单独设置font-size
全兼容的样式解决方法
.finally-solve { letter-spacing: -4px; /*根据不一样字体字号或许须要作必定的调整*/ word-spacing: -4px; font-size: 0; } .finally-solve li { font-size: 16px; letter-spacing: normal; word-spacing: normal; display:inline-block; *display: inline; zoom:1; }
嵌套层级不要太深,通常三层最多
css解析从右向左,因此最右边的应该是相对少一点
html用了base64的img的话,并不会缓存起来,能够将这个base64的图片放在css文件里,css会缓存,图片就缓存起来了
尽可能不用后代元素选择器,最右边的一层不要是标签,尤为是像div这种很是经常使用的标签
多使用css的继承,而不是每一次都书写时都所有重写一遍。写多个css属性时,能连在一块儿写的就连在一块儿写
Sass
'use strict'
不能使用eval()
抑制this
的行为
不容许读写eval
和arguments
的值
不容许意外建立全局变量
使用var定义的全局变量不能使用delete删除
无var建立的全局变量可使用delete删除
隐式类型转换
数字与字符串相加,结果为字符串
数字与字符串相减,结果为数字
比较变量的是否相同时,要采用===
,==
会发生隐式类型转换
NaN与任何变量不相等
typeof
instanceof
constructor
Object.prototype.toString.apply()
全局做用域
函数做用域
hasOwnProperty, isPrototypeOf, propertyIsEnumerable
配置属性(configurable, enumerable, writable, value
)
特性
扩展: isExtensible
, preventExtensions
(是否能够添加新的属性)
密封: isSealed
, seal
(是否能够删除属性,是否能够配置属性)
冻结: isFrozen
, freeze
(全部属性是否可读可写)
定义属性
defineProperty
, defineProperties
数组的类型检测
数组的方法
slice()
map()
every()
some()
filter()
柯里化
概念:部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数并且返回结果的新函数的技术
function currying( fn ) { var args = Array.prototype.slice.call(arguments, 1); return function () { var newArgs = args.concat(Array.prototype.slice.call(arguments)); return fn.apply(null, newArgs); } }
arguments对象
JS函数不存在重载,后定义的函数会覆盖先定义的函数
函数调用模式
方法调用
函数调用
构造器调用
apply调用
new
操做符的原理使用new
关键字来建立实例的时候,原理以下:
首先,在构造函数内部使用Object.create(constructor.prototype)
建立一个对象继承自构造函数
而后,将这个对象引用到this
上
最后,返回this
概念
做用
建立匿名执行函数
缓存变量,防止被垃圾回收
实现函数的封装
应用场景
内部函数访问外部函数的变量
使用闭包代替全局变量
封装相关功能
回调函数
建立私有变量和公有变量
特性
经典例子:列表点击,弹出每个的index
/* 错误作法 */ var elems = document.getElementById('links').getElementsByTagName('li'); for ( var i = 0; i < elems.length; i++ ) { elems[i].addEventListener('click', function ( event ) { event.preventDefault(); alert(i); }, false); }
/* 正确的作法,使用闭包 */ var elems = document.getElementById('links').getElementsByTagName('li'); for ( var i = 0; i < elems.length; i++ ) { (function ( index ) { elems[i].addEventListener('click', function ( event ) { event.preventDefault(); alert(index); }, false); })( i ); }
函数的this
的值永远绑定在调用此函数的对象上
可使用apply
,call
或者bind
改变this
值的指向
工厂模式
/* 缺点:没法检测对象的类型 */ var createPerson = function ( name, age, job ) { var o = new Object(); o.name = name; o.age = age; o.job = job; return o; }; var person1 = createPerson('Erichain', 21, 'Web');
构造函数模式
/* 缺点:每一个方法要在每一个实例上从新建立一遍 */ var Person = function ( name, age, job ) { this.name = name; this.age = age; this.job = job; } var person1 = new Person('Erichain', 21, 'Web');
原型模式
var Person = function () {}; Person.prototype = { constructor: Person, // 若是这个属性十分重要的话 name: 'Erichain', age: 21, job: 'web' }; var person1 = new Person();
组合构造函数原型模式
动态原型模式
var Person = function ( name, age, job ) { this.name = name; this.age = age; this.job = job; if ( typeof this.sayName !== 'function' ) { Person.prototype.sayName = function () { alert( this.name ); } } };
寄生构造函数模式
除了使用new
来实例化外,与工厂模式没区别
不能依赖instanceof
来肯定对象类型,通常不建议使用
稳妥构造函数模式
原型链
借用构造函数
function Person( name ) { this.name = name; } function man() { // 继承自Person,能够选择是否传入参数 Person.call(this, 'Erichain'); }
组合继承
原型式继承
寄生式继承
寄生组合式继承
new Object()
和Object.create()
的区别
Object.create
建立的对象直接从他的第一个参数继承,而new Object
所建立的对象是从对象的原型上继承
使用Object.create
,能够建立一个不继承于任何东西的对象,可是,若是设置someConstructor.prototype = null
,那么,这个新建立的对象会继承自Object.prototype
函数声明优于变量声明
函数声明会覆盖变量声明,可是不会覆盖变量赋值
在闭包中保存变量状态
模块化
IIFE和自执行函数的区别
IIFE的几种表示方法
(function () {})(); (function () {}()); !function () { /* code */ } (); ~function () { /* code */ } (); -function () { /* code */ } (); +function () { /* code */ } ();
事件流
事件捕获
处于目标
事件冒泡
事件对象(IE的区别)
跨浏览器事件处理函数
var EventUtil = { getEvent: function ( event ) { return event ? event : window.event; }, getTarget: function ( event ) { return event.target || event.srcElement; }, addHandler: function ( elem, type, handler ) { if ( elem.addEventListener ) { elem.addEventListener(type, handler, false); } else if ( elem.attachEvent ) { elem.attachEvent('on' + type, handler); } else { elem['on' + type] = handler; } }, preventDefault: function ( event ) { if ( event.preventDefault ) { event.preventDefault(); } else { event.returnValue = false; } }, stopPropagation: function ( event ) { if ( event.stopPropagation ) { event.stopPropagation(); } else { event.cancelable = true; } } };
事件广播
事件委托
<ul id="links"> <li id="link1">Link1</li> <li id="link2">Link2</li> <li id="link3">Link3</li> </ul>
var links = document.getElementById('links'); // 使用以前定义的跨浏览器事件处理程序 EventUtil.addHandler(links, 'click', function ( event ) { var target = EventUtil.getTarget(event); event = EventUtil.getEvent(event); switch ( target.id ) { case 'link1': // do something break; case 'link2': // do something break; case 'link3': // do something break; } });
事件函数的参数(注意addEventListener()
的最后一个参数,若是为false表示在冒泡阶段获取事件,若是为true,表示在事件捕获阶段获取事件)
call(obj, args)
, apply(obj, array)
call
与apply
支持低版本浏览器,bind
只支持高版本浏览器
bind
原生代码实现
if ( !Function.prototype.bind ) { Function.prototype.bind = function ( oThis ) { if ( typeof this !== 'function') { throw new Error('What is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBound = this, fNOP = function () {}, fBound = function () { return fToBound.apply( this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)) ) }; if ( this.prototype ) { fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }
window
对象
location
对象
screen
对象
navigator
对象
检测插件navigator.plugins
检测用户代理navigator.userAgent
history
对象
查找
document.getElementById
document.getElementsByTagName
document.getElementsByName
document.getElementsByClassName
document.querySelector
document.querySelectAll
节点关系
element.childNodes
element.firstChild
element.lastChild
element.previousSibling
element.nextSibling
element.parentNode
element.appendChild()
element.insertBefore()
element.removeChild()
element.replaceChild()
属性操做
element.getAttribute()
element.setAttribute()
样式操做
element.style[PROPERTY_NAME]
element.classList
element.classList.add
element.classList.remove
element.classList.contains
element.classList.toggle
元素遍历
childElementCount
子元素数量
firstElementChild
第一个子元素: firstChild
的元素版
lastElementChild
最后一个子元素: lastChild
的元素版
previousElementSibling
->previousSibling
的元素版
nextElementSibling
->nextSibling
的元素版
遍历方法
document.createNodeIterator(root, whatToShow, filter)
参见https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator
document.createTreeWalker(root, whatToShow, filter, expandEntityReferences, currentNode)
参见https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
操做DOM的时候必定要缓存变量,避免发生大量的重排重绘
异步加载Javascript文件
使用document.write()
动态改变已有script标签的src
属性
使用DOM方法动态建立script元素
使用Ajax获取脚本内容再加载
在script标签中使用defer
以及async
属性
按需加载
合并文件
合理使用二进制
CDN加速,原理
图片懒加载
预加载
prefetch
函数节流
引用计数
/* 出现循环引用的例子 */ function () { var objectA = {}, objectB = {}; objectA.someOtherObject = objectB; objectB.anotherObject = objectA; }
标记清除
setTimeout 的第一个参数使用字符串而非函数的话,会引起内存泄漏
循环引用
优雅降级:Web站点在全部新式浏览器中都能正常工做,若是用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工做。因为IE独特的盒模型布局问题,针对不一样版本的IE的hack实践过优雅降级了,为那些没法支持功能的浏览器增长候选方案,使之在旧式浏览器上以某种形式降级体验却不至于彻底失效
渐进加强:从被全部浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面增长无害于基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥做用
JSON.stringify()
json序列化为字符串
JSON.parse()
将类JSON的字符串转化为JSON对象
一段比较完整的使用原生Javascript实现ajax请求方法
function createRequestObject() { if ( window.XMLHttpRequest ) { return new XMLHttpRequest(); } // 针对IE else if ( window.ActiveXObject ) { return new ActiveXObject('Microsoft.XMLHTTP'); } } // 请求的回调函数 function requestCallBack() { if ( request.readyState === 4 && request.status === 200 ) { console.log(request.responseText); } } var request = createRequestObject(); request.onreadystatechange = requestCallBack; // open函数的三个参数分别是请求的方法, 请求的地址, 是否异步(true表示异步) request.open('POST', url, true); request.send(null);
JSHint
JSLint
ESLint(针对ECMAScript 2015)
JSMin
YUI Compressor
Gzip
Array.prototype.slice.call()
原理IE: Trident
Chrome: Webkit, Blink(now)
Firefox: Gecko
Opera: Presto
cookie 由服务器生成,可设置失效时间。若是是浏览器端生成的cookie,则在浏览器关闭以后失效;而localStorage除非被清除,不然永久保存,sessionStorage则在关闭浏览器或者页面以后清除
cookie的大小为4k左右,localStorage和sessionStorage的大小通常为5MB
与服务器痛心的时候,cookie每次都会携带在http头中,可是其余两个不参与服务器通讯
cookie中最好不要放置任何的明文的东西,其余两个的数据若是提交到服务器必定要校验
防止XSS(跨站点脚本)攻击
防止CSRF(跨站点伪造请求攻击)
防止跨iframe攻击
Unix流
管道
管道是一个固定大小的缓冲区
从管道读数据是一次性操做,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据
能够把一个进程的标准输出流与另外一个进程的标准输入流链接起来
Mocha
Karma
Jasmine
同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。 指一段脚本只能读取来自同一来源的窗口和文档的属性
JSONP
document.domain
window.name
HTML5的window.postMessage
和window.onmessage
三次握手
客户端发起链接试探
服务端接收到试探请求,向客户端发送确认消息
客户端获得服务端的确认消息以后,再次向服务端发送确认消息
一次完整的http请求是怎么样的
域名解析
TCP三次握手
发起http请求
服务器端响应http请求,客户端获得html代码
浏览器解析html代码,并请求html代码中的资源
浏览器对页面进行渲染呈现给用户
如何组织jQuery项目的代码结构
栅格布局实现原理
.img-responsive
实现原理
内联表单实现原理
Bootstrap组件实现原理
双向绑定
$digest
循环
dirty checking
$watch
MVC
独立做用域
依赖注入
循环监听
ng-if
与ng-hide/show
的区别
ng-if
为true
的时候节点才会存在于DOM中
ng-show/hide
只是控制节点的显示和隐藏
factory
,service
与provider
的区别和关系
使用factory
建立的服务,是一个对象,而后,将方法和属性定义在这个对象上,在返回这个对象,就能够供外部controller调用了
使用service
建立的服务,是使用new
进行实例化的,因此,方法和属性要定义在this
上,而且这个服务会自动返回this
使用provider
建立的服务,是惟一能够注入到config()
函数的服务,能够用来提供模块化的配置。而且,定义在this
上的属性和方法,在config
函数里才能够访问,从this.$get()
函数里返回的属性和方法,才能被控制器所访问
ng-click
是否可使用原生函数
不能够,由于对应的方法不存在于其控制器中,除非在控制器中声明
ng-repeat
数组中有相同元素的解决办法
能够添加track by $index
$emit
,$broadcast
和$on
$emit
由子级向父级广播,$broadcast
由父级向子级广播
controllerAs
与$scope
的区别
AngularJS的缺点
强约束,学习成本高
不利于SEO
性能问题
减小监控项
主动设置索引
下降渲染的数据数量
数据扁平化
最简单的方法
function removeDuplicate( arr ) { var len = arr.length, temp = []; for ( var i = 0; i < len; i+=1 ) { if ( temp.indexOf(arr[i]) === -1 ) { temp.push(arr[i]); } } return temp; }
function clone( Obj ) { var buf; if ( Obj instanceof Array ) { buf = []; //建立一个空的数组 var i = Obj.length; while ( i-- ) { buf[i] = clone(Obj[i]); } return buf; } else if ( Obj instanceof Object ) { buf = {}; //建立一个空对象 for ( var k in Obj ) { //为这个对象添加新的属性 buf[k] = clone(Obj[k]); } return buf; } else { return Obj; } }
function clone( obj ) { var dest; switch( typeof obj ) { case 'undefined': break; case 'number': dest = +obj; break; case 'string': dest = obj + ''; break; case 'boolean': dest = obj; break; case 'object': if ( obj instanceof Array ) { dest = []; for ( var i = 0; i < obj.length; i++ ) { dest[i] = obj[i]; } } else { dest = {}; for ( var i in obj ) { dest[i] = obj[i]; } } default: break; } return dest; }
快速排序
function quickSort( arr ) { var left = [], right = [], len = arr.length, breakPoint = arr[0]; if ( len === 1 || len === 0 ) { return arr; } for ( var i = 1; i < len; i++ ) { if ( arr[i] < breakPoint ) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat(breakPoint, quickSort(right)); }
冒泡排序
function bubbleSort( arr ) { var len = arr.length, temp; for ( var i = 0; i < len - 1; i ++ ) { for ( var j = 0; j < len - 1 - i; j++ ) { if ( arr[j] > arr[j+1] ) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } return arr; }
插入排序
function insertSort( arr ) { var len = arr.length, temp; for ( var i = 1; i < len; i++ ) { var j; temp = arr[i]; j = i; while ( j > 0 && arr[j-1] > temp ) { arr[j] = arr[j-1]; j--; } arr[j] = temp; } return arr; }
function removePlace( str ) { var reg = /(^s*)|(s*)$/; if ( str && typeof str === 'string' ) { return str.replace(reg, ''); } }
function charCount( str ) { var obj = {}, len = str.length, i = 0; for ( ; i < len; i++ ) { var val = str.charAt(i); if ( obj[val] && obj[val].value === val ) { obj[val].count++; } else { obj[val] = {}; obj[val].count = 1; obj[val].value = val; } } for ( var key in obj ) { console.log( key + ' is ' + obj[key].count ); } return obj; }
关于插件编写,可参考:jQuery插件库
同步的方式加载模块,服务器优先
使用require
加载模块,使用module.exports
定义模块
浏览器优先的方式,经过异步加载的方式完成任务
使用define(['module'], function ( module ) {})
加载模块
不兼容 io、文件系统(filesystem)和其它经过 CommonJS 实现的面向服务器的功能
推崇依赖前置
对于依赖的模块提早执行
推崇依赖就近
对于依赖的模块延迟执行
使用define(function ( require, exports, module ) {})
加载模块
同时支持 AMD 和 CommonJS 特性