基本上都是围绕着几个主要的标签,像标题(H1~H6)、列表(li)、强调(strongem)等等>
根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析。
(2)为什么要语义化?
为了在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构:为了裸奔时好看;
用户体验:例如title、alt用于解释名词或解释图片信息、label标签的活用;
方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
(3)写HTML代码时应注意什么?
尽可能少的使用无语义的标签div和span;
在语义不明显时,既可以使用div或者p时,尽量用p,因为p在默认情况下有上下间距,对兼容特殊终端有利;
不要使用纯样式标签,如:b、font、u等,改用css设置。
需要强调的文本,可以包含在strong或者em标签中(浏览器预设样式,能用CSS指定就不用他们),strong默认样式是加粗(不要用b),em是斜体(不用i);
使用表格时,标题要用caption,表头用thead,主体部分用tbody包围,尾部用tfoot包围。表头和一般单元格要区分开,表头用th,单元格用td;
表单域要用fieldset标签包起来,并用legend标签说明表单的用途;
每个input标签对应的说明文本都需要使用label标签,并且通过为input设置id属性,在lable标签中设置for=someld来让说明文本和相对应的input关联起来。
(4)HTML5新增了哪些语义标签,详述之。
1、
定义文档中的主体部分的节、段。
2、
3、
4、
定义文档、页面的页眉。通常是一些引导和导航信息,不局限于整个页面头部,也可以用在内容里。
5、
定义了文档、页面的页脚,和header类似。
6、
定义了一个链接组组成的导航部分,其中的链接可以链接到其他网页或者当前页面的其他部分。
7、
用于对网页或区段(section)的标题元素(h1~h6)进行组合。
8、
用于对元素进行组合。
9、
为figure元素加标题。一般放在figure第一个子元素或者最后一个。
10、
定义元素的细节,用户可以点击查看或者隐藏。
11、
12、
用来进行canvas绘图。
13、
定义视频。
14、
定义音频。
15、
定义嵌入网页的内容。比如插件。
16、
该标签为媒介元素(比如video、audio)定义媒介元素。
17、
定义可选数据的列表,与input配合使用(
18、
在视觉上向用户展现出那些想要突出的文字。比如搜索结果中向用户高亮显示搜索关键词。
19、
度量衡,用红黄绿表示出一个数值所在范围。
20、
定义不同类型的输出,样式与span无异。
21、
进度条,运行中的进度。
22、
23、
定义加密内容。
24、
定义命令行为。
2、浏览器的标准模式和怪异模式
(1)盒模型的处理差异:
元素溢出的处理
标准模式下,overflow取值默认为visible;在怪异模式在,该溢出会被当做扩展box来对待,即元素的大小由内容决定,溢出不会裁剪,元素框自动调整,包含溢出内容。
元素的百分比高度
当一个元素使用百分比高度时,标准模式下,高度取决于内容变化,怪异模式下,百分比高度被准确应用
内联元素的尺寸
标准模式下,non-replacedinline元素无法自定义大写;
怪异模式下,定义这些元素的width、height属性可以影响这些元素显示的尺寸。
行内元素的垂直对齐
元素中的字体
CSS中,对于font的属性都是可以继承的。怪异模式下,对于table元素,字体的某些元素将不会从body等其他封装元素继承中的得到,特别是font-size属性。
3、xhtml和html的区别
1、XHTML要求正确嵌套
2、XHTML所有元素必须关闭
3、XHTML区分大小写
4、XHTML属性值要用双引号
5、XHTML用id属性代替name属性
6、XHTML特殊字符的处理
4、使用data-的好处
data-*属性用于存储页面或应用程序的私有自定义数据。
data-*属性赋予我们在所有HTML元素上嵌入自定义data属性的能力。
存储的(自定义)数据能够被页面的JavaScript中利用,以创建更好的用户体验(不进行Ajax调用或服务器端数据库查询)。
H5的新属性
元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。
标签永远位于head元素内部。
元数据总是以名称/值的形式被成对传递的。
6、canvas
7、HTML废弃的标签
8、IE6bug,和一些定位写法
9、cssjs放置位置和原因
10、什么是渐进式渲染
一开始先加载首屏显示的内容
11、html模板语言
Ejsjsxhtmljadejsp
12、metaviewport原理
metaviewport的6个属性:
属性
值
width
设置layoutviewport的宽度,为一个正整数,或字符串”width-device”
initial-scale
设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale
允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale
允许用户的最大缩放值,为一个数字,可以带小数
height
设置layoutviewport的高度,这个属性并不重要,很少使用
user-scalable
是否允许用户进行缩放,值为”no”或”yes”,no代表不允许,yes代表允许
devicePixelRatio=物理像素/独立像素
layoutviewport:通过document.documentElement.clientWidth来获取。
visualviewport:通过window.innerWidth来获
idealviewport的宽度等于移动设备的屏幕宽度,只要在css中把某一元素的宽度设为idealviewport的宽度(单位用px),那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100%的效果。
二.CSS
1、盒模型,box-sizing
在标准模型中,盒模型的宽高只是内容(content)的宽高,
而在IE模型中盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高。
/*标准模型*/box-sizing:content-box;
/*IE模型*/box-sizing:border-box;
请解释*{box-sizing:border-box;}的作用,并说明使用它的好处
固定的盒子大小padding增加不改变大小至改变内部位置border改变也不会改变他的大小
省略号:
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;多行display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;注:
实现方法:
注:
2、CSS3新特性,伪类,伪元素,锚伪类
3、CSS3的选择器
4、@Font-face
5、圆角
6、多列布局(multi-columnlayout)
7、阴影(Shadow)
8、CSS3的渐变效果
9、css弹性盒子模型
10、CSS3制作特效
Transition对象变换时的过渡效果
Transforms
Animation动画特效
11、CSS实现隐藏页面的方式
Display:noneOpacity:0position:absolute(z-index)
12、如何实现水平居中和垂直居中。
13、说说position,display
14、浮动元素引起的问题和解决办法?绝对定位和相对定位,元素浮动后的display值
1.使用空标签清除浮动。这种方法是在所有浮动标签后面添加一个空标签定义cssclear:both.弊端就是增加了无意义标签。
2.使用overflow。给包含浮动元素的父标签添加css属性overflow:auto;zoom:1;zoom:1用于兼容IE6。
3.使用after伪对象清除浮动。该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置height:0,否则该元素会比实际高出若干像素;二、content属性是必须的,但其值可以为空,content属性的值设为”.”,空亦是可以的。
4.浮动外部元素
15、link和@import引入css的区别
差别2:功能范围不同link属于XHTML标签,而@import是CSS提供的一种方式,link标签除了可以加载CSS外,还可以定义RSS,定义rel连接属性等,@import就只能加载CSS。
差别3:加载顺序不同当一个页面被加载的时候,link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再被加载。所以有时候浏览@import加载CSS的页面时开始会没有样式(就是闪烁),网速慢的时候还挺明显。
差别4:兼容性由于@import是css2.1提出的,所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题。
差别5:控制样式时的差别使用link方式可以让用户切换CSS样式.现代浏览器如Firefox,Opera,Safari都支持rel=”alternatestylesheet”属性(即可在浏览器上选择不同的风格),当然你还可以使用Javascript使得IE也支持用户更换样式。
16、解释一下css3的flexbox,以及适用场景
17、inline和inline-block的区别
18、哪些是块级元素那些是行级元素,各有什么特点
19、布局
流式布局如何实现,响应式布局如何实现
移动端布局方案
实现三栏布局(圣杯布局,双飞翼布局,flex布局)
静态布局:给页面元素设置固定的宽度和高度,单位用px,当窗口缩小,会出现滚动条,拉动滚动条显示被遮挡内容。针对不同分辨率的手机端,分别写不同的样式文件。
自适应布局:创建多个静态布局,每个静态布局对应一个屏幕分辨率范围,使用@media媒体查询技术。
流式布局:元素的宽高用百分比做单位,元素宽高按屏幕分辨率调整,布局不发生变化。屏幕尺度跨度过大的情况下,页面不能正常显示。
响应式布局:采用自适应布局和流式布局的综合方式,为不同屏幕分辨率范围创建流式布局。
弹性布局:要点在于使用em和rem单位来定义元素宽度,与流式布局有极大的相似性,但也有不同之处,主要区别在于弹性布局的尺寸主要根据字体大小而变化。
grid布局
table布局的作用
20、cssdpi
每英寸包含点的数量(dotsperinch)
普通屏幕通常包含96dpi,一般将2倍于此的屏幕称之为高分屏,即大于等于192dpi的屏幕,比如Mac视网膜屏就达到了192dpi(即2dppx),打印时一般会需要更大的dpi;
21、你知道attribute和property的区别么
Attribute就是dom节点自带的属性,例如html中常用的id、class、title、align等:
而Property是这个DOM元素作为对象,其附加的内容,例如childNodes、firstChild等:
css布局问题?css实现三列布局怎么做?如果中间是自适应又怎么做?
22、清除浮动的原理
23、overflow:hidden有什么缺点?
24、padding百分比是相对于父级宽度还是自身的宽度
25、css3动画,transition和animation的区别,animation的属性,加速度,重力的模拟实现
26、CSS3如何实现旋转图片(transform:rotate)
27、sassless
28、对移动端开发了解多少?(响应式设计、Zepto;@media、viewport、JavaScript正则表达式判断平台。)
29、什么是bfc,如何创建bfc?解决什么问题?
首先要明确BFC是什么意思,其全英文拼写为BlockFormattingContext直译为“块级格式化上下文”
BFC的原理
内部的box会在垂直方向,一个接一个的放置
每个元素的marginbox的左边,与包含块borderbox的左边相接触(对于从做往右的格式化,否则相反)
box垂直方向的距离由margin决定,属于同一个bfc的两个相邻box的margin会发生重叠
bfc的区域不会与浮动区域的box重叠
bfc是一个页面上的独立的容器,外面的元素不会影响bfc里的元素,反过来,里面的也不会影响外面的
计算bfc高度的时候,浮动元素也会参与计算
怎么取创建bfc
float属性不为none(脱离文档流)
position为absolute或fixed
display为inline-block,table-cell,table-caption,flex,inine-flex
overflow不为visible
根元素
应用场景
自适应两栏布局
清除内部浮动
防止垂直margin重叠
30、CSS中的长度单位(px,pt,rem,em,ex,vw,vh,vh,vmin,vmax)
31、CSS选择器的优先级是怎样的?
32、雪碧图
33、Svg
34、媒体查询的原理是什么?
35、窗口的onresize事件,得到窗口大小匹配对应的样式修改
36、CSS的加载是异步的吗?表现在什么地方?
37、常遇到的浏览器兼容性问题有哪些?常用的hack的技巧
38、外边距合并
39、解释一下“::before”和“:after”中的双冒号和单冒号的区别
单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。
三.JS
offsetWidth//返回元素的宽度(包括元素宽度、内边距和边框,不包括外边距)
offsetHeight//返回元素的高度(包括元素高度、内边距和边框,不包括外边距)
clientWidth//返回元素的宽度(包括元素宽度、内边距,不包括边框和外边距)
clientHeight//返回元素的高度(包括元素高度、内边距,不包括边框和外边距)
style.width//返回元素的宽度(包括元素宽度,不包括内边距、边框和外边距)
style.height//返回元素的高度(包括元素高度,不包括内边距、边框和外边距)
scrollWidth//返回元素的宽度(包括元素宽度、内边距和溢出尺寸,不包括边框和外边距),无溢出的情况,与clientWidth相同
scrollHeigh//返回元素的高度(包括元素高度、内边距和溢出尺寸,不包括边框和外边距),无溢出的情况,与clientHeight相同
1.style.width返回的是字符串,如28px,offsetWidth返回的是数值28;
2.style.width/style.height与scrollWidth/scrollHeight是可读写的属性,clientWidth/clientHeight与offsetWidth/offsetHeight是只读属性
3.style.width的值需要事先定义,否则取到的值为空。而且必须要定义在html里(内联样式),如果定义在css里,style.height的值仍然为空,但元素偏移有效;而offsetWidth则仍能取到。
//---------------------------------------------------------------------------offsetTop//返回元素的上外缘距离最近采用定位父元素内壁的距离,如果父元素中没有采用定位的,则是获取上外边缘距离文档内壁的距离。所谓的定位就是position属性值为relative、absolute或者fixed。返回值是一个整数,单位是像素。此属性是只读的。
offsetLeft//此属性和offsetTop的原理是一样的,只不过方位不同,这里就不多介绍了。
scrollLeft//此属性可以获取或者设置对象的最左边到对象在当前窗口显示的范围内的左边的距离,也就是元素被滚动条向左拉动的距离。返回值是一个整数,单位是像素。此属性是可读写的。
scrollTop//此属性可以获取或者设置对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,也就是元素滚动条被向下拉动的距离。返回值是一个整数,单位是像素。此属性是可读写的。
//---------------------------------------------------------------------------
当鼠标事件发生时(不管是onclick,还是omousemove,onmouseover等)
clientX鼠标相对于浏览器(这里说的是浏览器的有效区域)左上角x轴的坐标;不随滚动条滚动而改变;
clientY鼠标相对于浏览器(这里说的是浏览器的有效区域)左上角y轴的坐标;不随滚动条滚动而改变;
pageX鼠标相对于浏览器(这里说的是浏览器的有效区域)左上角x轴的坐标;随滚动条滚动而改变;
pageY鼠标相对于浏览器(这里说的是浏览器的有效区域)左上角y轴的坐标;随滚动条滚动而改变;
screenX鼠标相对于显示器屏幕左上角x轴的坐标;
screenY鼠标相对于显示器屏幕左上角y轴的坐标;
offsetX鼠标相对于事件源左上角X轴的坐标
offsetY鼠标相对于事件源左上角Y轴的坐标
1、js的基本类型有哪些?引用类型有哪些?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?null和undefined的区别。
基本类型:Number,String,Boolean,Null,undefined。
引用类型:Object,Array,Date,RegExp,Function
if(!undefined)console.log('undefinedisfalse');//undefinedisfalseif(!null)console.log('nullisfalse');//nullisfalseundefined==null//true
null是对象Number(null)//0
Number(undefined)//NaN
null表示"没有对象",即该处不应该有值。典型用法是:
(1)作为函数的参数,表示该函数的参数不是对象。
(2)作为对象原型链的终点。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
区别:
基本类型:(1)基本类型的值是不可变得。(2)基本类型的比较是值的比较:(3)基本类型的变量是存放在栈区的(栈区指内存里的栈内存)
引用类型:(1)引用类型的值是可变的(2)引用类型的比较是引用的比较(3)引用类型的值是同时保存在栈内存和堆内存中的对象
2、如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)
(1)instanceof操作符
(2)对象的constructor属性
(3)Object.prototype.toString.call(o)==='[objectArray]';(4)Array.isArray()
(5)functionisArrayFn(value){
if(typeofArray.isArray==="function"){
returnArray.isArray(value);
}else{
returnObject.prototype.toString.call(value)==="[objectArray]";}}
1.优化图片
2.图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)
3.优化CSS(压缩合并css,如margin-top,margin-left...)
4.网址后加斜杠(如www.campr.com/目录,会判断这个“目录是什么文件类型,或者是目录。)
4、线程与进程的区别
一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
5、JS中的类
//对象的直接量
varBiology_1={};
//new来创建
varBiology_2=newObject();
//Object.create()创建,es5以上支持
varBiology_3=Object.create(null);
与此同时,顺便提下三个词:
prototype实例指向原型,构造函数指向原型。
construtor原型指向构造函数。该构造函数的原型指向Object,而该Object的的construtor又指回该构造函数。或者又说,属性返回对创建此对象的数组函数的引用。
proto实例指向构造函数的原型(其中,如果原型是Object,则它的proto指向function,而该function的proto又指向Object)。
听着有点绕,看看实例就明白了。
工厂模式
functionBiology(name){
vartempObj=newObject();
tempObj.name=name;
tempObj.printName=function(){
console.log(this.name);
};
returntempObj;
}
varanimals=Biology('animals');
varplants=Biology('plants');
animals.printName();//animals
plants.printName();//plants
animals.constructor;//functionObject(){[nativecode]}
其实是实例化Object,缺点是无法识别对象类型
构造模式
this.name=name;
this.printName=function(){
varanimals=newBiology('animals');
varplants=newBiology('plants');
animals.constructor;//functionBiology(name){...}
构造函数的方式,实现对象类型识别,不过性能或封装性差
原型模式
functionBiology(){};
Biology.prototype.name='biology';
Biology.prototype.printName=function(){
varanimals=newBiology();
animals.printName();//biology
varplants=newBiology();
plants.printName();//biology
console.log(animals.name);//biology
animals.name='animals';
console.log(animals.name);//animals
console.log(plants.name);//biology
animals.printName=function(){
console.log('animals');
原型的属性方法是所有实例共享的,而如果实例属性(方法)与原型属性(方法)重复时,优先实例属性(方法),其中有个hasOwnProperty用来判断是否实例属性。
因为上述例子中,使用Biology.prototype.name,Biology.prototype.printName这样的直接修改,过于分散与重复,于是我们进行一个合并:
Biology.prototype={
name:'biology',
printName:function(){
varbiology=newBiology();
console.log(biology.name);//biology
console.log(biology.constructor);//functionObject(){}
合并后,看起来没什么问题,不过biology的构建函数不再是Biology,那并不是我们想要的。所以把构建函数指回Biology:
constructor:Biology,
console.log(biology.constructor);//functionBiology(){}
已经如我们所愿,这是因为创建一个函数,同是会创建他的prototype对象,同时这对象自动获得constructor,重写prototype时,constructor不再指向原Biology
那如果实例化之后修改原型,会发生什么?
console.log(biology.name);//undefined
undefined!,你没有看错。
如之前所说,同时,因为实例指向的是原型,而不是构造函数,所以,如果在实例化之后原型有变化,原来的实例指向的还是旧原型
不过总的来说,原型模式如果修改的原型属性或方法,之后的创建的实例都会变化,没有隐私而言,所以还有改进空间
构造模式与原型模式组合
functionBiology(age){
this.age=age;
printAll:function(){
console.log(this.name+':'+this.age);
varbiology_1=newBiology(16);
varbiology_2=newBiology(18);
biology_1.printAll();//biology:16
biology_2.printAll();//biology:18
把共享部分使用原型,不公享部分使用构造,本方法比较常见。
其他像的模式还有很多,像什么动态原型模式、寄生构造函数模式,原理上都是使用上述方式自由组合,就不一一列举了。
类的属性与方法
比较Java,类有私有属性,公共属性,私有方法,公共方法,原型属性,原型方法,可惜在JS没有这些好东西,不过,我们知道JS中var有作用域以及原型的概念,所以我们可以模拟出这些东西。
functionBiology(){
//私有方法
functionprivateMethod(){
return'私有方法';
//私有属性
varprivateProperty='私有属性';
//实例属性
this.publicProperty='实例属性';
//原型属性
Biology.prototype.staticProperty='原型属性';
varprivateMethod=function(){
//实例方法
this.publicMethod=function(){
return'实例方法';
//原型方法
Biology.prototype.staticMethod=function(){
return'原型方法';
//获得私有属性
this.getPrivateProperty=function(){
returnprivateProperty;
//设置私有属性
this.setPrivateProperty=function(property){
privateProperty=property;
//执行私有方法
this.getPrivateMethod=function(){
returnprivateMethod();
varbiology_2=newBiology();
console.log(biology.privateProperty);//undefined
console.log(biology.publicProperty);//实例属性
biology.publicProperty='修改后的实例属性';
console.log(biology.publicProperty);//修改后的实例属性
console.log(biology_2.publicProperty);//实例属性
console.log(biology.getPrivateProperty());//私有属性
biology.setPrivateProperty('改变后的私有属性');
console.log(biology.getPrivateProperty());//改变后的私有属性
console.log(biology_2.getPrivateProperty());//私有属性
console.log(privateProperty);//undefined
console.log(biology.privateProperty);//underfined
console.log(biology.staticProperty);
Biology.prototype.staticProperty='修改后的原型属性';
console.log(biology_2.staticProperty);
console.log(biology.privateMethod);//undefined
console.log(biology.publicMethod());//实例方法
console.log(biology.getPrivateMethod());//私有方法
console.log(biology.staticMethod());
return'修改后的原型方法';
console.log(biology.staticMethod());//修改后的原型方法
console.log(biology_2.staticMethod());//修改后的原型方法
类的继承
原型继承
functionAnimals(){};
Animals.prototype=newBiology('animals');
varanimals=newAnimals();
不过,为了便于使用与理解,我们一般会换成形式写:
varBiology={
name:'IamBiology'
//继承parent
functioninherit(parent){
vartype=typeofparent;
if(!(type==='object'||type==='function'))throwTypeError;
if(Object.create){
returnObject.create(parent);
functiontemp(){};
temp.prototype=parent;
returnnewtemp;
varanimals=inherit(Biology);
console.log(animals.name);//IamBiology
构造函数继承
functionAnimals(name,age){
this.temp=Biology;
this.temp(name);
this.printAll=function(){
varanimals=newAnimals('animals',16);
animals.printAll();//animals:16
apply,call继承
functionAnimals(age){
Biology.call(this,age);
functionPlants(address){
this.address=address;
Biology.apply(this,[address]);
varplants=newPlants('plants','深圳');
ES6类
下面这个例子,简单的对ES6对类进行阐述:
classBiology{
constructor(name){
printName(){
staticprintNameTwice(){
console.log(this.name+','+this.name);
varbiology=newBiology('biology');
biology.printName();//biology
Biology.printNameTwice();//biology,biology
classAnimalsextendsBiology{
constructor(name,age){
super(name);
printAll(){
console.log('animalsname');
getname(){
returnthis._name.toUpperCase();
setname(name){
this._name=name;
console.log(animals.name);//ANIMALS
console.log(animals._name);//animals
animals.printName();//animalsname
animals.printAll();//ANIMALS:16
Animals.printNameTwice();//Animals,Animals
5、js判断对象是否为空对象的几种方法js判断对象是否为空对象的几种方法
1.将json对象转化为json字符串,再判断该字符串是否为"{}"
vardata={};
varb=(JSON.stringify(data)=="{}");
alert(b);//true
2.forin循环判断
varobj={};
varb=function(){
for(varkeyinobj){
returnfalse;
returntrue;
alert(b());//true
3.jquery的isEmptyObject方法
此方法是jquery将2方法(forin)进行封装,使用时需要依赖jquery
varb=$.isEmptyObject(data);
4.Object.getOwnPropertyNames()方法
此方法是使用Object对象的getOwnPropertyNames方法,获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的length来判断此对象是否为空
注意:此方法不兼容ie8,其余浏览器没有测试
vararr=Object.getOwnPropertyNames(data);
alert(arr.length==0);//true
5.使用ES6的Object.keys()方法
与4方法类似,是ES6的新方法,返回值也是对象中属性名组成的数组
vardata={};vararr=Object.keys(data);
6、JS常见的dom操作api
7、解释一下事件冒泡和事件捕获
addEventListener("click",function(e){
console.log("body捕获",e.target.nodeName,e.currentTarget.nodeName);
},true);
console.log("body冒泡",e.target.nodeName,e.currentTarget.nodeName);
},false);
8、事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何阻止默认事件?
9、对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?
闭包就是一个函数,捕获作用域内的外部绑定。这些绑定是为之后使用而被绑定,即使作用域已经销毁。
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(PublicMethod),把内部变量当作它的私有属性(privatevalue),这时一定要小心,不要随便改变父函数内部变量的值。
10、this有哪些使用场景?跟C,Java中的this有什么区别?如何改变this的值?
this永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。匿名函数或不处于任何对象中的函数指向window。
1.如果是call,apply,with,指定的this是谁,就是谁。
2.普通的函数调用,函数被谁调用,this就是谁。
call,apply,bind
11、显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链
显式原型:prototype隐式原型:__proto__
12、创建对象的多种方式
12、实现继承的多种方式和优缺点
核心:子构造函数的原型指向父构造函数的实例
每个构造函数都有一个原型对象,原型对象中都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。当原型对象等于另外一个类型的实例即继承。
缺点:子类实例共享属性,造成实例间的属性会相互影响
functionParent1(){
this.name=['super1']
this.reName=function(){
this.name.push('super111')
}functionChild1(){
Child1.prototype=newParent1()
varchild11=newChild1()
varchild12=newChild1()
varparent1=newParent1()
child11.reName()
console.log(child11.name,child12.name)//['super1','super111']['super1','super111'],可以看到子类的实例属性皆来自于父类的一个实例,即子类共享了同一个实例console.log(child11.reName===child12.reName)//true,共享了父类的方法
缺点:父类的方法没有被共享,造成内存浪费
functionChild2(){
Parent1.call(this)
varchild21=newChild2()
varchild22=newChild2()
child21.reName()
console.log(child21.name,child22.name)//['super1','super111']['super1'],子实例的属性都是相互独立的
console.log(child21.reName===child22.reName)//false,实例方法也是独立的,没有共享同一个方法
组合继承
缺点:父类构造函数被调用两次,子类实例的属性存在两份。造成内存浪费
functionParent3(){
this.name=['super3']
Parent3.prototype.reName=function(){
this.name.push('super31')
functionChild3(){
Parent3.call(this)//生成子类的实例属性(但是不包括父对象的方法)
Child3.prototype=newParent3()//继承父类的属性和方法(副作用:父类的构造函数被调用的多次,且属性也存在两份造成了内存浪费)
varchild31=newChild3()
varchild32=newChild3()
child31.reName()
console.log(child31.name,child32.name)//['super3','super31']['super3'],子类实例不会相互影响
console.log(child31.reName===child32.reName)//true,共享了父类的方法
寄生继承
完美:子类都有各自的实例不会相互影响,且共享了父类的方法
functionParent4(){
this.name=['super4']
Parent4.prototype.reName=function(){
this.name.push('super41')
}functionChild4(){
Parent4.call(this)//生成子类的实例属性(但是不包括父对象的方法)
Child4.prototype=Object.create(Parent4.prototype)//该方法会使用指定的原型对象及其属性去创建一个新的对象
varchild41=newChild4()
varchild42=newChild4()
child41.reName()
console.log(child41.name,child42.name)//['super4','super41']['super4'],子类实例不会相互影响
console.log(child41.reName===child42.reName)//true,共享了父类的方法
ES6class和寄生继承实现的效果一致
classParent5{
constructor(){
this.name=['super5']
reName(){
this.name.push('new5')
classChild5extendsParent5{
super()
varchild51=newChild5()varchild52=newChild5()
child51.reName()
console.log(child51.name,child52.name)//['super5','new5'],子类实例不会相互影响
console.log(child51.reName===child52.reName)//true,共享了父类的方法
2.确定原型和实例的关系
1)通过使用instanceof
instanceinstanceofObject//true
instanceinstanceofSuperType//true
instanceinstanceofSubType//true
2)通过使用isPrototypeOf()
只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型
Object.prototype.isPrototypeOf(instance)//true
SuperType.prototype.isPrototypeOf(instance)//true
SubType.prototype.isPrototypeOf(instance)//true
3.谨慎定义方法
子类型覆盖超类型中的某个方法,或者是需要添加超类中不存在的方法,都需要将给原型添加方法的代码放在继承之后(即替换原型的语句之后)
14、new一个对象具体做了什么
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
(3)执行构造函数中的代码(为这个新对象添加属性);
(4)返回新对象。
15、手写Ajax,XMLHttpRequest
functionajax(){
if(window.XMLHttpRequest){
//codeforIE6,IE5
//判定执行状态
/*
readyState
0:请求未初始化
1:服务器连接已建立
2:请求已接收
3:请求处理中
4:请求已完成,且响应已就绪
status
200:请求成功
404:未找到
500:服务器内部错误
*/
//responseXML获得XML形式的响应数据
vartxt="";
varnum=xmlDoc.getElementsByName("value");//获取节点name=value的值
for(vari=0;i txt=txt+num[i].childNodes[0].nodeValue+" document.getElementById("myDiv2").innerHTML=txt; (function(){ vardate=newDate(); returndate.getSeconds(); }) ,true); //设置头信息 //将信息发送到服务器 16、变量提升 console.log(global);//undefinedvarglobal='global';console.log(global);//globalfunctionfn(){console.log(a);//undefinedvara='aaa';console.log(a);//aaa}fn(); 之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的: 17、举例说明一个匿名函数的典型用例 第一种:函数申明,这也是最常规的一种 functiondouble(x){ return2*x; 第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用。 vardouble=newFunction('x','return2*x;'); 第三种: vardouble=function(x){return2*x;} 18、指出JS的宿主对象和原生对象的区别,为什么扩展JS内置对象不是好的做法?有哪些内置对象和内置函数? 19、documentload和documentDOMContentLoaded两个事件的区别 DOMContentLoaded不等图片、视频、音频等加载完 load等图片、视频、音频等加载完 最后我们来回答这个问题:我们为什么一再强调将css放在头部,将js文件放在尾部? 20、请指出document.onload和document.ready两个事件的区别。 页面加载完成有两种事件,一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件),二是onload,指示页面包含图片等文件在内的所有元素都加载完成。 21、===和==,[]===[],undefined===undefined,[]==[],undefined==undefined 首先,==equality等同,===identity恒等。==,两边值类型不同的时候,要先进行类型转换,再比较。===,不做类型转换,类型不同的一定不等。 先说===,这个比较简单。下面的规则用来判断两个值是否===相等: 如果类型不同,就[不相等] 如果两个都是数值,并且是同一个值,那么[相等];(!例外)的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断) 如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。 如果两个值都是true,或者都是false,那么[相等]。 如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。 如果两个值都是null,或者都是undefined,那么[相等]。 再说==,根据以下规则: 如果两个值类型相同,进行===比较。 如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较: 如果一个是null、一个是undefined,那么[相等]。 如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。 如果任一值是true,把它转换成1再比较;如果任一值是false,把它转换成0再比较。 如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂) 任何其他组合,都[不相等]。 22、typeof能够得到哪些值 typeof运算符用来检测给定变量的数据类型,返回一个用来表示表达式的数据类型的字符串。 可能的返回值有:"number"、"string"、"boolean"、"object"、"function"和"undefined"。 表达式 返回值 typeofundefined 'undefined'如果值是undefined typeofnull 'object'如果这个值是对象或者null typeoftrue 'boolean'如果这个值是布尔值 typeof123 'number'如果这个值是数字 typeof"abc" 'string'如果这个字是字符串 typeoffunction(){} 'function'如果这个值是函数 typeof{} typeof[] typeofunknownVariable 'undefined'如果这个值没有定义 "symbol"——ES6引入的一种新的原始数据类型Symbol,表示独一无二的值 23什么是“usestrict”,好处和坏处 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为; 消除代码运行的一些不安全之处,保证代码运行的安全; 提高编译器效率,增加运行速度; 为未来新版本的Javascript做好铺垫。 24、函数的作用域是什么?js的作用域有几种? 块级全局 25、JS如何实现重载和多态 重载可认为是静态的多态,静态联编,发生在编译阶段; 重载就是一组具有相同名字、不同参数列表的函数(方法)。 重载,函数特征之一,表现为在一个类中同名不同参的方法分别被调用会产生不同的结果。 js本身不支持重载,所以只能通过其他方式实现,arguments检测传参的个数,然后再执行不同的方式;根据传参的类型,调用不同的方法,用typeof进行检测 多态是动态的,动态联编,发生在运行阶段; 多态,面向对象特征之一,表现为不同对象调用相同方法会产生不同的结果。可以理解一个方法被不同实现后展现不同的效果及状态。 静态的比动态的效率高,但动态的最大优点是多态性,提高代码复用性。 26、常用的数组api,字符串api 27、原生事件绑定(跨浏览器),dom0和dom2的区别?
";
document.getElementById("btn").onclick=function(){alert("hello");}//脚本里面绑定
document.getElementById("btn").addeventlistener("click",clickone,false);//通过侦听事件处理相应的函数
上边两个会造成覆盖,第三个不会。
.关于获取事件源
event.srcElement是[IE8-]唯一的方式,IE9+未知,其它浏览器都支持标准的event.target方式
关于阻止事件默认行为
event.preventDefault()是标准方法,但[IE8-]不支持,IE自己的方式是event.returnValue=false;
.关于停止事件传播
event.stopPropagation()是标准方法,IE又有意见了,他要这么玩:event.cancelBubble=true;这里需要特别注意了,因为cancel是属性而不是方法,与标准相差甚远,容易记错
DOM0级方式
ele.onclick=handler;ele.onclick=null;最古老的一种方式
优点:全浏览器兼容
缺点:同一事件只能绑定/解绑一个事件处理器
DOM2级方式
ele.add/removeEventListener(eventType,handler,catch);
和IE方式:ele.attach/detachEvent(‘on’+eventType,handler);
优点:支持绑定/解绑多个事件处理器
缺点:需要做兼容性判断。需要注意的是:标准方式中最后一个参数表示是否在事件捕获阶段绑定/解绑,IE不支持事件捕获,所以也就没有第三个参数了
注意:IE方式不仅方法名与标准不同,参数中事件类型还要加上on,否则绑定无效但不报错
给定一个元素获取它相对于视图窗口的坐标
28、如何实现图片滚动懒加载
即在页面载入的时候将页面上的img标签的src指向一个小图片,把真实地址存放在一个自定义属性中,这里我用data-src来存放然后将页面img标签获取并保存,开启一个定时器,遍历保存的img标签,判断其位置是否出现在了可视区域内。如果出现在可视区域了那么就把真实的src地址给赋值上。
并且从数组中删除,避免重复判断。我们可以获取当前img的相对于文档顶的偏移距离减去scrollTop的距离,然后和浏览器窗口高度在进行比较,如果小于浏览器窗口则出现在了可视区域内了,反之,则没有。
29、js的字符串类型有哪些方法?正则表达式的函数怎么使用?
30、深拷贝
31、编写一个通用的事件监听函数
32、web端cookie的设置和获取
33、setTimeout和promise的执行顺序
34、JavaScript的事件流模型都有什么?
dom0,dom2
35、navigator对象,location和history
36、js的垃圾回收机制
37、内存泄漏的原因和场景
全局变量引起的内存泄漏
闭包引起的内存泄漏
dom清空或删除时,事件未清除导致的内存泄漏
子元素存在引用引起的内存泄漏
39、DOM事件中target和currentTarget的区别
3.通常情况下terget和currentTarget是一致的,我们只要使用terget即可,但有一种情况必须区分这三者的关系,那就是在父子嵌套的关系中,父元素绑定了事件,单击了子元素(根据事件流,在不阻止事件流的前提下他会传递至父元素,导致父元素的事件处理函数执行),这时候currentTarget指向的是父元素,因为他是绑定事件的对象,而target指向了子元素,因为他是触发事件的那个具体对象,
40、typeof和instanceof区别,instanceof原理
typeof是一个一元运算,放在一个运算数之前,运算数可以是任意类型。
它返回值是一个字符串,该字符串说明运算数的类型。typeof一般只能返回如下几个结果:
instance:实例,例子
ainstanceofbalert("true"):alert("false");//a是b的实例?真:假
instanceof用于判断一个变量是否某个对象的实例,如vara=newArray();alert(ainstanceofArray);会返回true,同时alert(ainstanceofObject)也会返回true;这是因为Array是object的子类。再如:functiontest(){};vara=newtest();alert(ainstanceoftest)会返回
谈到instanceof我们要多插入一个问题,就是function的arguments,我们大家也许都认为arguments是一个Array,但如果使用instaceof去测试会发现arguments不是一个Array对象,尽管看起来很像。
另外:
测试vara=newArray();if(ainstanceofObject)alert('Y');elsealert('N');
得'Y’
但if(windowinstanceofObject)alert('Y');elsealert('N');
得'N'
所以,这里的instanceof测试的object是指js语法中的object,不是指dom模型对象。
使用typeof会有些区别
alert(typeof(window))会得object
40、js动画和css3动画比较
JS动画
缺点:(1)JavaScript在浏览器的主线程中运行,而主线程中还有其它需要运行的JavaScript脚本、样式计算、布局、绘制任务等,对其干扰导致线程可能出现阻塞,从而造成丢帧的情况。
(2)代码的复杂度高于CSS动画
优点:(1)JavaScript动画控制能力很强,可以在动画播放过程中对动画进行控制:开始、暂停、回放、终止、取消都是可以做到的。
(2)动画效果比css3动画丰富,有些动画效果,比如曲线运动,冲击闪烁,视差滚动效果,只有JavaScript动画才能完成
(3)CSS3有兼容性问题,而JS大多时候没有兼容性问题
CSS动画
缺点:
(2)代码冗长。想用CSS实现稍微复杂一点动画,最后CSS代码都会变得非常笨重。
优点:(1)浏览器可以对动画进行优化。
强制使用硬件加速(通过GPU来提高动画性能)
CSS动画流畅的原因
渲染线程分为mainthread(主线程)和compositorthread(合成器线程)。如果CSS动画只是改变transform和opacity,这时整个CSS动画得以在compositorthread完成(而JS动画则会在mainthread执行,然后触发compositor进行下一步操作)在JS执行一些昂贵的任务时,mainthread繁忙,CSS动画由于使用了compositorthread可以保持流畅,
在主线程中,维护了一棵Layer树(LayerTreeHost),管理了TiledLayer,在compositorthread,维护了同样一颗LayerTreeHostImpl,管理了LayerImpl,这两棵树的内容是拷贝关系。因此可以彼此不干扰,当Javascript在mainthread操作LayerTreeHost的同时,compositorthread可以用LayerTreeHostImpl做渲染。当Javascript繁忙导致主线程卡住时,合成到屏幕的过程也是流畅的。为了实现防假死,鼠标键盘消息会被首先分发到compositorthread,然后再到mainthread。这样,当mainthread繁忙时,compositorthread还是能够响应一部分消息,例如,鼠标滚动时,加入mainthread繁忙,compositorthread也会处理滚动消息,滚动已经被提交的页面部分(未被提交的部分将被刷白)。
CSS动画比JS流畅的前提:
JS在执行一些昂贵的任务
同时CSS动画不触发layout或paint在CSS动画或JS动画触发了paint或layout时,需要mainthread进行Layer树的重计算,这时CSS动画或JS动画都会阻塞后续操作。
只有如下属性的修改才符合“仅触发Composite,不触发layout或paint”:
backface-visibility
opacity
perspective
perspective-origin
transfrom
所以只有用上了3D加速或修改opacity时,css3动画的优势才会体现出来。
(2)代码相对简单,性能调优方向固定
(3)对于帧速表现不好的低版本浏览器,CSS3可以做到自然降级,而JS则需要撰写额外代码
结论
如果动画只是简单的状态切换,不需要中间过程控制,在这种情况下,css动画是优选方案。它可以让你将动画逻辑放在样式文件里面,而不会让你的页面充斥Javascript库。然而如果你在设计很复杂的富客户端界面或者在开发一个有着复杂UI状态的APP。那么你应该使用js动画,这样你的动画可以保持高效,并且你的工作流也更可控。所以,在实现一些小的交互动效的时候,就多考虑考虑CSS动画。对于一些复杂控制的动画,使用javascript比较可靠。
42、JavaScript倒计时(setTimeout)
43、js处理异常
44、js的设计模式知道那些
45、轮播图的实现,以及轮播图组件开发,轮播10000张图片过程
46、websocket的工作原理和机制。
就变成了这样,只需要经过一次HTTP请求,就可以做到源源不断的信息传送了。(在程序设计中,这种设计叫做回调,即:你有信息了再来通知我,而不是我傻乎乎的每次跑来问你)
这样的协议解决了上面同步有延迟,而且还非常消耗资源的这种情况。那么为什么他会解决服务器上消耗资源的问题呢?
其实我们所用的程序是要经过两层代理的,即HTTP协议在Nginx等服务器的解析下,然后再传送给相应的Handler(PHP等)来处理。简单地说,我们有一个非常快速的接线员(Nginx),他负责把问题转交给相应的客服(Handler)。
本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太慢。,导致客服不够。Websocket就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接,有信息的时候客服想办法通知接线员,然后接线员在统一转交给客户。
这样就可以解决客服处理速度过慢的问题了。
同时,在传统的方式上,要不断的建立,关闭HTTP协议,由于HTTP是非状态性的,每次都要重新传输identityinfo(鉴别信息),来告诉服务端你是谁。
但是Websocket只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP协议,还要查看identityinfo的信息。
同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的。。),没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的客服(Handler)了
至于怎么在不支持Websocket的客户端上使用Websocket。。答案是:不能
但是可以通过上面说的longpoll和ajax轮询来模拟出类似的效果
47、JS代码调试-
48、响应式编程和命令式编程
函数式编程
函数式编程是一系列被不公平对待的编程思想的保护伞,它的核心思想是,它是一种将程序看成是数学方法的求值、不会改变状态、不会产生副作用(后面我们马上会谈到)的编程方式。
FP核心思想强调:
明确性——代码应该尽可能的明显。尤其是要隔离副作用避免意外。要明确定义数据流和错误处理,要避免GOTO语句和异常,因为它们会将应用置于意外的状态。
并发——因为纯函数的概念,大多数函数式代码默认都是并行的。由于CPU运行速度没有像以前那样逐年加快((详见摩尔定律)),普遍看来这个特点导致函数式编程渐受欢迎。以及我们也必须利用多核架构的优点,让代码尽量的可并行。
高阶函数——函数和其他的语言基本元素一样是一等公民。你可以像使用string和int一样的去传递函数。
不变性——变量一经初始化将不能修改。一经创建,永不改变。如果需要改变,需要创建新的。这是明确性和避免副作用之外的另一方面。如果你知道一个变量不能改变,当你使用时会对它的状态更有信心。
函数式编程:JS、Scala、Erlang
响应式编程
响应式系统具备如下特点:
响应性——一个系统应该总是能够及时响应用户请求,并且保持很低的延迟。
可伸缩性——一个系统在负载增加时应该能够根据需求增加资源以确保响应性,但同时也应该能在负载降低时减少资源,保持高效的资源利用率。
消息驱动——在一个系统的不同部分之间传递消息,Ledbrook认为这是响应式系统的一个必备特点。
响应式实际上是观察者模式加上事件源的完成通知能力、错误传播能力和监听者同事件源通信的能力。
响应式流是一种规范,ReactiveX是一种常用的跨平台实现。
下面三个重要的概念是响应式流API的构建基础:
发布者是事件的发送方,可以向它订阅。
订阅者是事件订阅方。
订阅将发布者和订阅者联系起来,使订阅者可以向发布者发送信号。
响应式编程是一种基于异步数据流概念的编程模式。数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。
响应式编程的一个关键概念是事件。事件可以被等待,可以触发过程,也可以触发其它事件。事件是唯一的以合适的方式将我们的现实世界映射到我们的软件中:如果屋里太热了我们就打开一扇窗户。同样的,当我们更改电子表(变化的传播)中的一些数值时,我们需要更新整个表格或者我们的机器人碰到墙时会转弯(响应事件)。
今天,响应式编程最通用的一个场景是UI:我们的移动App必须做出对网络调用、用户触摸输入和系统弹框的响应。在这个世界上,软件之所以是事件驱动并响应的是因为现实生活也是如此。
响应式编程的具体实现-RxJava。RxJava提供了一种以面向时序的方式考虑数据的机会:所有事情都是持续变化的,数据在更新,事件在触发,然后你就可以创建事件响应式的、灵活的、运行流畅的App。
49、手指点击可以触控的屏幕时,是什么事件?什么是函数柯里化?以及说一下JS的API有哪些应用到了函数柯里化的实现?(函数柯里化一些了解,以及在函数式编程的应用,-最后说了一下JS中bind函数和数组的reduce方法用到了函数柯里化。)
柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果。
提高适用性
延迟执行
固定易变因素(bind)
//add函数柯里化
functionadd(){
//建立args,利用闭包特性,不断保存arguments
varargs=[].slice.call(arguments);
//方法一,新建_add函数实现柯里化
var_add=function(){
if(arguments.length===0){
//参数为空,对args执行加法
returnargs.reduce(function(a,b){
returna+b});
//否则,保存参数到args,返回一个函数
[].push.apply(args,arguments);
return_add;
//返回_add函数return_add;
////方法二,使用arguments.callee实现柯里化
//returnfunction(){
//if(arguments.length===0){
//returnargs.reduce(function(a,b){returna+b});
//}
//Array.prototype.push.apply(args,arguments);//returnarguments.callee;//}}console.log(add(1,2,3)(1)(2)(3)(4,5,6)(7,8)());//42
实现的原理主要是:
闭包保存args变量,存储之前的参数
新建一个_add函数,参数的长度为0,就执行加法,否则,存储参数到args,然后返回函数自身(可以选择匿名函数,返回arguments.callee即可,意思相同,见代码中注释掉的部分,但是在严格模式下不能使用,所以还是使用方法一比较稳妥)。
49、escape,encodeURI,encodeURIComponent
escape()函数用于js对字符串进行编码,不常用。
encodeURI()用于整个url编码
encodeURIComponent()用于参数的传递,参数包含特殊字符可能会造成间断。
50、js事件循环
检查Macrotask队列是否为空,若不为空,则进行下一步,若为空,则跳到3
检查Microtask队列是否为空,若不为空,则进入下一步,否则,跳到1(开始新的事件循环)
macro-task包括:script(整体代码),setTimeout,setInterval,setImmediate,I/O,UIrendering。
micro-task包括:process.nextTick,Promises,Object.observe,MutationObserver
执行顺序:函数调用栈清空只剩全局执行上下文,然后开始执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次执行macro-task中的一个任务队列,执行完之后再执行所有的micro-task,就这样一直循环。
四.ES6
1、谈一谈promise
2、所有的ES6特性你都知道吗?如果遇到一个东西不知道是ES6还是ES5,你该怎么区分它
3、es6的继承和es5的继承有什么区别
4、promise封装ajax
5、letconst的优点
6、es6generator是什么,async/await实现原理
都是一步函数的同步表达
Generator函数总是返回一个遍历器,ES6规定这个遍历器是Generator函数的实例,也继承了Generator函数的prototype对象上的方法。
*yeild
一旦遇到yield命令,就会暂时退出堆栈,但是并不消失,里面的所有变量和对象会冻结在当前状态。等到对它执行next命令时,这个上下文环境又会重新加入调用栈,冻结的变量和对象恢复执行。
async用来申明里面包裹的内容可以进行同步的方式执行,await则是进行执行顺序控制,每次执行一个await,程序都会暂停等待await返回值,然后再执行之后的await。
await后面调用的函数需要返回一个promise,另外这个函数是一个普通的函数即可,而不是generator。
await只能用在async函数之中,用在普通函数中会报错。
await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
其实,async/await的用法和co差不多,await和yield都是表示暂停,外面包裹一层async或者co来表示里面的代码可以采用同步的方式进行处理。不过async/await里面的await后面跟着的函数不需要额外处理,co是需要将它写成一个generator的。
7、ES6和node的commonjs模块化规范区别
es6{
export:'可以输出多个,输出方式为{}',
exportdefault:'只能输出一个,可以与export同时输出,但是不建议这么做',
解析阶段确定对外输出的接口,解析阶段生成接口,
模块不是对象,加载的不是对象,
可以单独加载其中的某个接口(方法),
静态分析,动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变,
this指向undefined
commonJS{
module.exports=...:'只能输出一个,且后面的会覆盖上面的',
exports....:'可以输出多个',
运行阶段确定接口,运行时才会加载模块,
模块是对象,加载的是该对象,
加载的是整个模块,即将所有的接口全部加载进来,
输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,
this指向当前模块
8、箭头函数,以及它的this,和普通函数的this有什么区别
ES6的箭头函数的this指向是,在哪里定义的箭头函数那么它的this就指向哪里。
而ES5普通函数的this指向是,在哪里调用的函数,那么this就指向哪里。
其实箭头函数里是没有this的,而普通函数的是有this的。
但是普通函数在定义的时候并不知道自己的this要指向哪里,所以在被调用的时候普通函数里的this会指向调用它的那个对象。
而箭头函数因为本身没有this,它会直接绑定到它的词法作用域内的this,也就是定义它时的作用域内的this值。
varname='window';
varobj={
name:'obj',
nameprintf:function(){
console.log(this.name)
obj.nameprintf();//'obj'
varw=obj.nameprintf;
w();//'window'
五.计算机网络
HTTPS和HTTP的区别主要如下:
以下是具体一些分析
一、HTTP和HTTPS的基本概念
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
二、HTTP和HTTPS的主要特点和工作流程
HTTP特点
1.支持客户/服务器模式。(C/S模式)
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快
HTTP工作流程
第一步:建立TCP/IP连接,客户端与服务器通过Socket三次握手进行连接
第三步:客户端发送请求头信息,请求内容,最后会发送一空白行,标示客户端请求完毕
第四步:服务器做出应答,表示对于客户端请求的应答,例如:HTTP/1.1200OK
第五步:服务器向客户端发送应答头信息
第六步:服务器向客户端发送请求头信息后,也会发送一空白行,标示应答头信息发送完毕,接着就以Content-type要求的数据格式发送数据给客户端
第七步:服务端关闭TCP连接,如果服务器或者客户端增Connection:keep-alive就表示客户端与服务器端继续保存连接,在下次请求时可以继续使用这次的连接
HTTPS特点
HTTPS是HTTP协议的修改,它加密数据并确保其机密性。其配置可保护用户在与网站交互时免于窃取个人信息和计费数据。
1、优点
2、缺点
第二步:Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
第三步:客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
第四步:客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
第五步:Web服务器利用自己的私钥解密出会话密钥。
第六步:Web服务器利用会话密钥加密与客户端之间的通信。
最后说一句,ssl证书阿里云上可以免费申请一年
1、HTTP协议头含有哪些重要的部分,HTTP状态码
2、网络url输入到输出怎么做?
3、性能优化为什么要减少HTTP访问次数?
4、Http请求的过程与原理
三次握手:
1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。
#netstat-nap|grepSYN_RECV
四次挥手:
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
TLS为安全传输层协议,所以属于传输层
7、TCP连接的特点,TCP连接如何保证安全可靠的?
8、为什么TCP连接需要三次握手,两次不可以吗,为什么
9、为什么tcp要三次握手四次挥手?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
10、tcp的三次握手和四次挥手画图(当场画写ack和seq的值)?
11、tcp与udp的区别
12、get和post的区别?什么情况下用到?
15、有没有自己写过webpack的loader,他的原理
loader本质就是接收字符串(或者buffer),再返回处理完的字符串(或者buffer)的过程。webpack会将加载的资源作为参数传入loader方法,交于loader处理,再返回。
constfs=require('fs')
constpath=require('path')
constloaderUtils=require('loader-utils')
constdefaultOptions={
placeholder:'{{__content__}}',
decorator:'layout'
constrender=(layoutPath,placeholder,source)=>{
try{
varlayoutHtml=fs.readFileSync(layoutPath,'utf-8')
}catch(error){
throwerror
returnlayoutHtml.replace(placeholder,source)
module.exports=function(source){
this.cacheable&&this.cacheable()
constoptions=Object.assign(loaderUtils.getOptions(this),defaultOptions)
const{placeholder,decorator,layout}=options
constreg=newRegExp(`(@${decorator}\\()(.*)\\)`)
constregResult=reg.exec(source)
varcallback=this.async()
if(regResult){
constrequest=loaderUtils.urlToRequest(regResult[2])
this.resolve('/',request,(err,rs)=>{
if(err){
rs=path.resolve(this.resourcePath,'../',request)
source=source.replace(regResult[0],'')
callback(null,render(rs,placeholder,source))
}elseif(layout){
callback(null,render(layout,placeholder,source))
callback(null,source)
15、babel是如何将es6代码编译成es5的
Babel工作分为三个阶段:
1.解析:将代码字符串解析成抽象语法树
2.变换:将抽象语法树
3.再建:根据变换后的抽象语法树再生成代码字符串
ES6代码输入==》babylon进行解析==》得到AST==》plugin用babel-traverse对AST树进行遍历转译==》得到新的AST树==》用babel-generator通过AST树生成ES5代码
17、域名解析时是tcp还是udp
18、域名发散和域名收敛
19、Post一个file的时候file放在哪的?
20、HTTPResponse的Header里面都有些啥?
1、跨域,为什么JS会对跨域做出限制
2、前端安全:xss,csrf
XSS全称跨站脚本攻击(CrossSiteScripting),顾名思义,就是通过向某网站写入js脚本来实现攻击。
1、在url上注入
2、注入js脚本
防范
1.过滤用户输入
2.对不可信输出编码
3.安全Cookie
4.提高防范意识、多测试
CSRF全称跨站请求伪造(Cross-siterequestforgery)
1、通过GET请求
2.通过XSS
防御
1.规范请求类型。
3.设置请求Token
4.防住第一道防线-XSS再次强调,如果cookie被别人拿走,任何防御都将在理论上失效。上述的防御手段仅仅是提高攻击门槛。有了你的cookie,我可以直接请求你的页面,获取你的token,获取你的验证码图片并解析出来,然后再发起请求。而服务器还以为这是你本人。
3、浏览器怎么加载页面的?script脚本阻塞有什么解决方法?defer和async的区别?
async是异步下载并立即执行,然后文档继续解析,defer是异步加载后解析文档,然后再执行脚本,这样说起来是不是理解了一点了;
它们的核心功能就是异步,那么两种属性怎么去区分什么情况下用哪个那,主要的参考是如果脚本不依赖于任何脚本,并不被任何脚本依赖,那么则使用defer,如果脚本是模块化的,不依赖于任何脚本,那么则使用async;
5、浏览器的全局变量有哪些
7、按需加载,不同页面的元素判断标准
8、web存储、session、cookies、localstroge、sessionStory等的使用和区别
cookie和session
cookie保存在浏览器端,session保存在服务器端
9、浏览器的内核
10、如何实现缓存机制?(从200缓存,到cache到etag再到)
HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
分类
分类描述
1**
信息,服务器收到请求,需要请求者继续执行操作
2**
成功,操作被成功接收并处理
3**
重定向,需要进一步的操作以完成请求
4**
客户端错误,请求包含语法错误或无法完成请求
5**
服务器错误,服务器在处理请求的过程中发生了错误
HTTP状态码列表
状态码
状态码英文名称
中文描述
100
Continue
101
SwitchingProtocols
切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200
OK
请求成功。一般用于GET与POST请求
201
Created
已创建。成功请求并创建了新的资源
202
Accepted
已接受。已经接受请求,但未处理完成
203
Non-AuthoritativeInformation
204
NoContent
无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205
ResetContent
重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206
PartialContent
部分内容。服务器成功处理了部分GET请求
300
MultipleChoices
多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301
MovedPermanently
永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302
Found
临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303
SeeOther
查看其它地址。与301类似。使用GET和POST请求查看
304
NotModified
未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305
UseProxy
使用代理。所请求的资源必须通过代理访问
306
Unused
已经被废弃的HTTP状态码
307
TemporaryRedirect
临时重定向。与302类似。使用GET请求重定向
400
BadRequest
客户端请求的语法错误,服务器无法理解
401
Unauthorized
请求要求用户的身份认证
402
PaymentRequired
保留,将来使用
403
Forbidden
服务器理解请求客户端的请求,但是拒绝执行此请求
404
NotFound
服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405
MethodNotAllowed
客户端请求中的方法被禁止
406
NotAcceptable
服务器无法根据客户端请求的内容特性完成请求
407
ProxyAuthenticationRequired
408
RequestTime-out
409
Conflict
服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
410
Gone
客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411
LengthRequired
服务器无法处理客户端发送的不带Content-Length的请求信息
412
PreconditionFailed
客户端请求信息的先决条件错误
413
RequestEntityTooLarge
由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414
Request-URITooLarge
请求的URI过长(URI通常为网址),服务器无法处理
415
UnsupportedMediaType
服务器无法处理请求附带的媒体格式
416
Requestedrangenotsatisfiable
客户端请求的范围无效
417
ExpectationFailed
服务器无法满足Expect的请求头信息
500
InternalServerError
服务器内部错误,无法完成请求
501
NotImplemented
服务器不支持请求的功能,无法完成请求
502
BadGateway
充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
503
ServiceUnavailable
由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504
GatewayTime-out
充当网关或代理的服务器,未及时从远端服务器获取请求
505
HTTPVersionnotsupported
服务器不
1.强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;
强制缓存
cache-control除了该字段外,还有下面几个比较常用的设置值:
-no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
-no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
-public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
-private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
2.协商缓存:向服务器发送请求,服务器会根据这个请求的requestheader的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的responseheader通知浏览器从缓存中读取资源;
协商缓存
Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。
ETag和Last-Modified的作用和用法,他们的区别:
3.在优先级上,服务器校验优先考虑Etag。
浏览器缓存过程
3.服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;;
这个主要涉及到两组header字段:Etag和If-None-Match、Last-Modified和If-Modified-Since。上面以及说得很清楚这两组怎么使用啦~复习一下:
Etag和If-None-Match
Etag/If-None-Match返回的是一个校验码。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。
与Last-Modified不一样的是,当服务器返回304NotModified的响应时,由于ETag重新生成过,responseheader中还会把这个ETag返回,即使这个ETag跟之前的没有变化。
Last-Modify/If-Modify-Since
如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。
为什么要有Etag
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
3.常见问题
用户行为对浏览器缓存的影响
4.解决方案
点击刷新按钮或者按F5
浏览器直接对本地的缓存文件过期,但是会带上If-Modifed-Since,If-None-Match,这就意味着服务器会对文件检查新鲜度,返回结果可能是304,也有可能是200.
用户按Ctrl+F5(强制刷新)
浏览器不仅会对本地文件过期,而且不会带上If-Modifed-Since,If-None-Match,相当于之前从来没有请求过,返回结果是200.
地址栏回车
浏览器发起请求,按照正常流程,本地检查是否过期,然后服务器检查新鲜度,最后返回内容。
21、什么是预加载、懒加载
22、一个XMLHttpRequest实例有多少种状态?
23、dns解析原理,输入网址后如何查找服务器
24、服务器如何知道你?
25、浏览器渲染过程
26、ie的某些兼容性问题
28、拖拽实现
29、拆解url的各部分-
30、从输入URL到页面展现中间发生了什么?
DNS查询DNS缓存
建立TCP连接(三次握手)连接复用
发送HTTP请求(请求的四部分)
后台处理请求
监听80端口
路由
渲染HTML模板
生成响应
发送HTTP响应
关闭TCP连接(四次挥手)
解析HTML
下载CSS(缓存)
解析CSS
下载JS(缓存)
解析JS
下载图片
解析图片
渲染DOM树
渲染样式树
执行JS
七.工程化
1、对webpack,gulp,grunt等有没有了解对比。
2、webpack的入口文件怎么配置,多个入口怎么分割。
3、webpack的loader和plugins的区别
4、gulp的具体使用。
5.前端工程化的理解、如何自己实现一个文件打包,比如一个JS文件里同时又ES5和ES6写的代码,如何编译兼容他们
八.模块化
1、对AMD,CMD,CommonJS有没有了解
(1)CMDSea.js在推广过程中对模块定义的规范化产出物是淘宝团队提供的
define(function(require,exports,module){...});
以来就近,那个地方用到就在哪个地方require同步的概念
(2)AMDrequriejs在推广过程中对模块定义的规范化产出物
define(
[module-name]/*可选*/,模块标识,可以省略。如果没有这个属性,则称为匿名模块。
[array-of-dependencies]/*可选*/,所依赖的模块,可以省略[module-factory-or-object]模块的实现,或者一个JavaScript对象。);
以来前置,用数组定义引用
//foo,bar为外部模块,加载以后的输出作为回调函数的参数传入,以便访问
requrie(["foo","bar"],function(foo,bar){
//其他代码
foo.doSomething();
});
(3)CommonJSnodejs服务端里用的
CommonJS模块由两部分组成:变量exports和require函数
modele.export==>exportdefault
export.area==>export
(4)es6特性export/import
2、为什么要模块化?不用的时候和用RequireJs的时候代码大概怎么写?
3、说说有哪些模块化的库,有了解过模块化的发展的历史吗?
4、分别说说同步和异步模块化的应用场景,说下AMD异步模块化实现的原理?
5、如何将项目里面的所有的require的模块语法换成import的ES6的语法?
6、使用模块化加载时,模块加载的顺序是怎样的,如果不知道,根据已有的知识,你觉得顺序应该是怎么样的?
九.框架
1、使用过哪些框架?
7、请指出$和$.fn的区别,或者说出$.fn的用途。
1.那么这两个分别是什么意思?
$.extend(obj);是为了扩展jquery本身,为类添加新的方法。
$.fn.extend(obj);给JQUERY对象添加方法。
2.$.fn中的fn是什么意思,其实是prototype,即$.fn=$.prototype;
$.extend({
add:function(a,b){
returna+b;
$.add(5,8);//return13
注意没有,这边的调用直接调用,前面不用任何对象。直接$.+方法名
$.fn.extend(obj);对prototype进行扩展,为jquery类添加成员函数,jquery类的实例可以使用这个成员函数。
$.fn.extend({
clickwhile:function(){
$(this).click(function(){
alert($(this).val())
$('input').clickwhile();//当点击输入框会弹出该对象的Value值
注意调用时候前面是有对象的。即$('input')这么个东西。
2、zepto和jquery是什么关系,有什么联系么?
3、jquery源码如何实现选择器的,为什么$取得的对象要设计成数组的形式,这样设计的目的是什么
4、jquery如何绑定事件,有几种类型和区别
5、什么是MVVM,MVC,MVP
6、Vue和Angular的双向数据绑定原理
7、Vue,Angular组件间通信以及路由原理
8、React中调用setState之后发生了什么事情
React会将当前传入的参数对象与组件当前的状态合并,然后触发调和过程,在调和的过程中,React会以相对高效的方式根据新的状态构建React元素树并且重新渲染整个UI界面.
React得到的元素树之后,React会自动计算出新的树与老的树的节点的差异,然后根据差异对界面进行最小化的渲染,在React的差异算法中,React能够精确的知道在哪些位置发生看改变以及应该如何去改变,这样就保证了UI是按需更新的而不是重新渲染整个界面.
9、React中的refs属性的作用是什么
Refs是React提供给我们安全的访问DOM元素或者某个组件实例的句柄,我们可以为元素添加ref属性然后在回调函数中接收该元素在DOM树中的句柄,该值会作为回调函数的第一个参数的返回.
10、React中keys的作用是什么
Keys是React在操作列表中元素被修改,添加,或者删除的辅助标识
componentWillReceiveProps和componentWillUpdate的区别
componentWillReceiveProps在组件接收到一个新的prop(更新后)时被调用。这个方法在初始化render时不会被调用。
componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate在组件完成更新后立即调用。在初始化时不会被调用。
8、react-router
实现URL与UI界面的同步。其中在react-router中,URL对应Location对象,而UI是由reactcomponents来决定的,这样就转变成location与components之间的同步问题。
在react-router中最主要的component是RouterRouterContextLink,history库起到了中间桥梁的作用。
9、react和vue的生命周期
初始化
1、getDefaultProps()
设置默认的props,也可以用dufaultProps设置组件的默认属性.
2、getInitialState()
在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props
3、componentWillMount()
组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。
4、render()
react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
5、componentDidMount()
组件渲染之后调用,只调用一次。
更新
6、componentWillReceiveProps(nextProps)
组件初始化时不调用,组件接受新的props时调用。
7、shouldComponentUpdate(nextProps,nextState)
react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候
8、componentWillUpdata(nextProps,nextState)
组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state
9、render()
组件渲染
10、componentDidUpdate()
组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。
卸载
11、componentWillUnmount()
组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
10、react和vue的虚拟dom以及diff算法
引入了VirtualDOM之后,React是这么干的:你给我一个数据,我根据这个数据生成一个全新的VirtualDOM,然后跟我上一次生成的VirtualDOM去diff,得到一个Patch,然后把这个Patch打到浏览器的DOM上去。完事。并且这里的patch显然不是完整的虚拟DOM,而是新的虚拟DOM和上一次的虚拟DOM经过diff后的差异化的部分。
但是值得称道的是,React基于两个假设,大大提高了diff算法的性能:
两个相同的组件会产生两个类似的DOM结构,两个不同的组件会产生两个不同的DOM结构。
对于同一层级的一组子节点,它们可以通过唯一id进行区分。
基于这两个假设,将算法的复杂度由O(n^3)变成了O(n)。极大的提高了效率。
先通过虚拟DOM计算出对真实DOM的最小修改量,然后再修改真实的DOM。
一、不同节点类型的比较
在虚拟树中比较两个虚拟DOM节点,若两个节点类型不同,则直接销毁前面的节点,创建并插入新节点。
二、只会逐层比较节点
比如A节点下有子节点BC,要将A节点包括其子节点移动到其他节点下面,则不是将A赋值并移动到其他节点如D下面,而是重新创建每一个节点:
三、相同节点类型的比较
相同类型的节点,对属性进行重设。
四、列表节点的比较
列表中节点若没有唯一标识的key值的话,会提示警告。
假设在列表ABCD中B的后面插入E,若没有key值则会将C更新为E,将D更新为C,最后插入D节点。
但是若有key值的话,react会找到正确的插入位置。
还有若A下面有BC子节点,若未提供key值,则react认为BC类型不同,要调整BC的位置会将BC删除后重新新建再插入,若有key值的话,则只是更新BC和其父组件而已。
11、为什么选择Redux
传统Web开发面临的困境在于:如何将服务器端或者用户输入的动态数据高效地反映到复杂的用户界面上。
同时,React把前端页面组件化(比如Form表单),充分提高代码重复利用率,提高了产品开发效率的同时,代码也更容易理解、测试和维护。
在HackerNews发布的求职技能需求数据中,React已连续12个月成为最受企业欢迎的技能,需求指数一度达到25.93%,足可见React被认可的程度。
掌握React不仅可以帮你应对前端应用开发,而且它的编程思想还可以应用到ReactNative原生App开发和服务器端渲染的后端开发。所以不论你是否从事前端开发工作,学习React对技能提升和职业发展都有很大的帮助。
12、Redux
Redux的核心是一个store。
provider
store是一个JavaScript对象,通过Redux提供的createStore(reducers)方法创建。
store有两个核心方法:.getState()和.dispatch()。
.getState()返回一个JavaScript对象,代表store当前的状态。
.dispatch()接受一个action作为参数,将这个action分发给所有订阅了更新的reducer。
reducer是一个JavaScript函数,函数签名为(previousState,action)=>newState,即接受previousState和action两个参数,根据action中携带的信息对previousState做出相应的处理,并返回一个新的state。
中间件:
redux的核心,就是控制和管理所有的数据输入输出,因此有了dispatch,由于dispatch是一个很纯的纯函数,就是单纯的派发action来更改数据,其功能简单且固定。
如果我们的程序中有很多的dispatch,我们就需要添加很多的重复代码,虽然编辑器提供批量替换,但这无疑是产生了很多样板代码。
middleware(store)(dispatch)就相当于是constlogger=store=>next=>{},这就是构造后的dispatch,继续向下传递。这里middlewares.reverse(),进行数组反转的原因,是最后构造的dispatch,实际上是最先执行的。因为在applyMiddleware串联的时候,每个中间件只是返回一个新的dispatch函数给下一个中间件,实际上这个dispatch并不会执行。只有当我们在程序中通过store.dispatch(action),真正派发的时候,才会执行。而此时的dispatch是最后一个中间件返回的包装函数。然后依次向前递推执行。
12、ReduxvsMobx
那么具体到这两种模型,又有一些特定的优缺点呈现出来,先谈谈Redux的优势:
数据流流动很自然,因为任何dispatch都会导致广播,需要依据对象引用是否变化来控制更新粒度。
引入中间件,其实主要为了解决异步带来的副作用,业务逻辑或多或少参杂着magic。
但是灵活利用中间件,可以通过约定完成许多复杂的工作。
对typescript支持困难。
Mobx:
数据流流动不自然,只有用到的数据才会引发绑定,局部精确更新,但免去了粒度控制烦恼。
自始至终一份引用,不需要immutable,也没有复制对象的额外开销。
没有这样的烦恼,数据流动由函数调用一气呵成,便于调试。
业务开发不是脑力活,而是体力活,少一些magic,多一些效率。
由于没有magic,所以没有中间件机制,没法通过magic加快工作效率(这里magic是指action分发到reducer的过程)。
完美支持typescript。
13、vue的observer,watcher,compile
14、react和angular分别用在什么样的业务吗?性能方面和MVC层面上的区别
15、jQuery对象和JS的Element有什么区别
16、jQuery对象是怎么实现的
17、jQuery除了它封装了一些方法外,还有什么值得我们去学习和使用的?
18、jQuery的$(‘xxx’)做了什么事情
19、介绍一下bootstrap的栅格系统是如何实现的
20、纯函数
函数的返回结果只依赖于它的参数。
函数执行过程里面没有副作用。
23、高阶组件、和父组件有什么区别
高阶组件的主要功能是封装并分离组件的通用逻辑,让通用逻辑在组件间更好地被复用。
进阶用法
高阶组件最常见的函数签名形式是这样的:
HOC([param])([WrappedComponent])
注意事项
1)不要在组件的render方法中使用高阶组件,尽量也不要在组件的其他生命周期方法中使用高阶组件。因为高阶组件每次都会返回一个新的组件,在render中使用会导致每次渲染出来的组件都不相等(===),于是每次render,组件都会卸载(unmount),然后重新挂载(mount),既影响了效率,又丢失了组件及其子组件的状态。高阶组件最适合使用的地方是在组件定义的外部,这样就不会受到组件生命周期的影响了。
3)Refs不会被传递给被包装组件。尽管在定义高阶组件时,我们会把所有的属性都传递给被包装组件,但是ref并不会传递给被包装组件,因为ref根本不属于React组件的属性。如果你在高阶组件的返回组件中定义了ref,那么它指向的是这个返回的新组件,而不是内部被包装的组件。如果你希望获取被包装组件的引用,你可以把ref的回调函数定义成一个普通属性(给它一个ref以外的名字)。
24、.Nodejs
对nodejs有没有了解
Express和koa有什么关系,有什么区别?
启动方式
koa采用了newKoa()的方式,而express采用传统的函数形式,对比源码如下:
express处理多个中间件
constapp=require("express")();app.use((req,res,next)=>{console.log("first");//next();});app.use((req,res,next)=>{console.log("second");//next();});app.use((req,res,next)=>{console.log("third");res.status(200).send("
headers...
");});app.listen(3001);koa处理多个中间件
constKoa=require('koa');constapp=newKoa();app.use((ctx,next)=>{ctx.body='HelloKoa-1';next();});app.use((ctx,next)=>{ctx.body='HelloKoa-2';next();});app.use((ctx,next)=>{ctx.body='HelloKoa-3';next();});app.listen(3000);
分路由:
koa轻量级但是要install许多中间件
nodejs适合做什么样的业务?
适合NodeJS的场景
1.RESTfulAPI
2.统一Web应用的UI层
不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。如果所有的关键业务逻辑都封装成REST调用,就意味着在上层只需要考虑如何用这些REST接口构建具体的应用。那些后端程序员们根本不操心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是通过Ajax异步获取的还是通过刷新页面。
3.大量Ajax请求的应用
例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,NodeJS能响应大量的并发请求。
总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景。
三.NodeJS的优缺点
优点:1.高并发(最重要的优点)
2.适合I/O密集型应用
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
2.只支持单核CPU,不能充分利用CPU
3.可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
原因:单进程,单线程
解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;
4.开源组件库质量参差不齐,更新快,向下不兼容
5.Debug不方便,错误没有stacktrace
25、nodejs与php,java有什么区别
总结一下:Java、PHP也有办法实现并行请求(子线程),但NodeJS通过回调函数(Callback)和异步机制会做得很自然。
26、Nodejs中的Stream和Buffer有什么区别?
buffer
为数据缓冲对象,是一个类似数组结构的对象,可以通过指定开始写入的位置及写入的数据长度,往其中写入二进制数据
stream
27、node的异步问题是如何解决的?
1、callbackfunction
2、promise
generatorfunction(co)
asyncawaitfunction(es2016规范)
28、node是如何实现高并发的?
因为I/O操作是由node的工作线程去执行的(nodejs底层的libuv是多线程的线程池用来并行io操作),且主线程是不需要等待结果返回的,只要发出指令马上就可以去忙其他事情了。
29、说一下Nodejs的eventloop的原理
一个事件轮询EventLoop需要三个组件:
事件队列EventQueue,属于FIFO模型,一端推入事件数据,另外一端拉出事件数据,两端只通过这个队列通讯,属于一种异步的松耦合。
队列的读取轮询线程,事件的消费者,EventLoop的主角。
单独线程池ThreadPool,专门用来执行长任务,重任务,干繁重体力活的。
在Node.js中,因为只有一个单线程不断地轮回查询队列中是否有事件,对于数据库文件系统等I/O操作,包括HTTP请求等等这些容易堵塞等待的操作,如果也是在这个单线程中实现,肯定会堵塞影响其他工作任务的执行,Javascript/Node.js会委托给底层的线程池执行,并会告诉线程池一个回调函数,这样单线程继续执行其他事情,当这些堵塞操作完成后,其结果与提供的回调函数一起再放入队列中,当单线程从队列中不断读取事件,读取到这些堵塞的操作结果后,会将这些操作结果作为回调函数的输入参数,然后激活运行回调函数。
请注意,Node.js的这个单线程不只是负责读取队列事件,还会执行运行回调函数,这是它区别于多线程模式的一个主要特点,多线程模式下,单线程只负责读取队列事件,不再做其他事情,会委托其他线程做其他事情,特别是多核的情况下,一个CPU核负责读取队列事件,一个CPU核负责执行激活的任务,这种方式最适合很耗费CPU计算的任务。反过来,Node..js的执行激活任务也就是回调函数中的任务还是在负责轮询的单线程中执行,这就注定了它不能执行CPU繁重的任务,比如JSON转换为其他数据格式等等,这些任务会影响事件轮询的效率。
十一.数据结构
1、基本数据结构:(数组、队列、链表、堆、二叉树、哈希表等等)
2、8种排序算法,原理,以及适用场景和复杂度
排序算法(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
functionbubbleSort(arr){
varlen=arr.length;
for(vari=0;i for(varj=0;j if(arr[j]>arr[j+1]){//相邻元素两两对比 vartemp=arr[j+1];//元素交换 arr[j+1]=arr[j]; arr[j]=temp; returnarr; 2、选择: functionselectionSort(arr){ varminIndex,temp; minIndex=i; for(varj=i+1;j if(arr[j] minIndex=j;//将最小数的索引保存 temp=arr[i]; arr[i]=arr[minIndex]; arr[minIndex]=temp; 3、插入排序: functioninsertionSort(arr){ varpreIndex,current; for(vari=1;i preIndex=i-1; current=arr[i]; while(preIndex>=0&&arr[preIndex]>current){ arr[preIndex+1]=arr[preIndex]; preIndex--; arr[preIndex+1]=current; 二分查找法 翻转二叉树 3、说出越多越好的费波拉切数列的实现方法? 十二.性能优化 1、cdn的用法是什么?什么时候用到? 2、浏览器的页面优化? 3、如何优化DOM操作的性能 4、单页面应用有什么SEO方案? 5、单页面应用首屏显示比较慢,原因是什么?有什么解决方案? 十三.其他 1、正则表达式 2、前端渲染和后端渲染的优缺点 3、数据库的四大特性,什么是原子性,表的关系 4、你觉得前端体系应该是怎样的? 5、一个静态资源要上线,里面有各种资源依赖,你如何平稳上线 6、如果要你去实现一个前端模板引擎,你会怎么做 7、知道流媒体查询吗? 8、SEO 9、mysql和mongoDB有什么区别? 10、restful的method解释 11、数据库知识、操作系统知识 12、click在ios上有300ms延迟,原因及如何解决 13、移动端的适配,rem+媒体查询/meta头设置 14、移动端的手势和事件; 15、unicode,utf8,gbk编码的了解,乱码的解决 十四.开放性问题 1、你都看过什么书?最近在看什么书? 2、用过什么框架?有没有看过什么框架的代码? 3、有没有学过设计模式? 4、说一说观察者模式吧!能不能写出来? 5、你最大的优点是什么?那你最大的缺点呢? 6、你除了写博客还有什么输出? 7、现在你的领导给你了一份工作,要求你一个星期完成,但你看了需求以后估计需要3周才能完成,你该怎么办? 9、如何规划自己的职业生涯 10、项目过程中,有遇到什么问题吗?怎么解决的? 11、最近在研究哪方面的东西? 13、请介绍你参与的印象最深刻的一个项目,为什么?并且介绍你在项目中的角色和发挥的作用。 十五.HR面 1、你为什么要学习前端? 2、你平时的是怎么学习前端的?有什么输出? 3、你觉得自己最好的项目是什么? 4、身边比较佩服的人有什么值得你学习的?你为什么没有跟他们一样? 5、同事的什么问题会让你接受不了 6、压力最大的事情是什么? 7、身边的朋友通常对你的评价是什么 8、喜欢什么样的工作氛围 9、如何看待加班 10、有没有对象 11、意向城市 12、其他的offer 13、为什么要录取你? 14、周末都会干什么? 15、未来职业规划 Js数组的常用方法: 方法 描述 连接两个或更多的数组,并返回结果。 从数组的指定位置拷贝元素到数组的另一个指定位置中。 检测数值元素的每个元素是否都符合条件。 使用一个固定值来填充数组。 检测数值元素,并返回符合条件所有元素的数组。 返回符合传入测试(函数)条件的数组元素。 返回符合传入测试(函数)条件的数组元素索引。 数组每个元素都执行一次回调函数。 搜索数组中的元素,并返回它所在的位置。 把数组的所有元素放入一个字符串。 返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。 通过指定函数处理数组的每个元素,并返回处理后的数组。 删除数组的最后一个元素并返回删除的元素。 向数组的末尾添加一个或更多元素,并返回新的长度。 将数组元素计算为一个值(从左到右)。 将数组元素计算为一个值(从右到左)。 反转数组的元素顺序。 删除并返回数组的第一个元素。 选取数组的的一部分,并返回一个新数组。 检测数组元素中是否有元素符合指定条件。 对数组的元素进行排序。 从数组中添加或删除元素。 把数组转换为字符串,并返回结果。 向数组的开头添加一个或更多元素,并返回新的长度。 返回数组对象的原始值。 数组去重: 方法一: 双层循环,外层循环元素,内层循环时比较值 如果有相同的值则跳过,不相同则push进数组 Array.prototype.distinct=function(){ vararr=this, result=[], i, j, len=arr.length; for(i=0;i for(j=i+1;j if(arr[i]===arr[j]){ j=++i; result.push(arr[i]); returnresult; vararra=[1,2,3,4,4,1,1,2,1,1,1]; arra.distinct();//返回[3,4,2,1] 方法二:利用splice直接在原数组进行操作 值相同时,则删去这个值 注意点:删除元素之后,需要将数组的长度也减1. if(arr[i]==arr[j]){ arr.splice(j,1); len--; j--; vara=[1,2,3,4,5,6,5,3,2,4,56,4,1,2,1,1,1,1,1,1,]; varb=a.distinct(); console.log(b.toString());//1,2,3,4,5,6,56 优点:简单易懂 缺点:占用内存高,速度慢 方法三:利用对象的属性不能相同的特点进行去重 obj={}, for(i=0;i if(!obj[arr[i]]){//如果能查找到,证明数组元素重复了 obj[arr[i]]=1; 方法四:数组递归去重 运用递归的思想 先排序,然后从最后开始比较,遇到相同,则删除 arr.sort(function(a,b){//对数组进行排序才能方便比较 returna-b; functionloop(index){ if(index>=1){ if(arr[index]===arr[index-1]){ arr.splice(index,1); loop(index-1);//递归loop函数进行去重 loop(len-1); vara=[1,2,3,4,5,6,5,3,2,4,56,4,1,2,1,1,1,1,1,1,56,45,56]; console.log(b.toString());//1,2,3,4,5,6,45,56 方法五:利用indexOf以及forEach arr.forEach(function(v,i,arr){//这里利用map,filter方法也可以实现 varbool=arr.indexOf(v,i+1);//从传入参数的下一个索引值开始寻找是否存在重复 if(bool===-1){ result.push(v); vara=[1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,2,3,3,2,2,1,23,1,23,2,3,2,3,2,3]; console.log(b.toString());//1,23,2,3 方法六:利用ES6的set Set数据结构,它类似于数组,其成员的值都是唯一的。 利用Array.from将Set结构转换成数组 functiondedupe(array){ returnArray.from(newSet(array)); dedupe([1,1,2,3])//[1,2,3] 拓展运算符(...)内部使用for...of循环 letarr=[1,2,3,3]; letresultarr=[...newSet(arr)]; console.log(resultarr);//[1,2,3] Js实现addClasshasClassremoveClasstoggleClass functionhasClass(obj,cls){ returnobj.className.match(newRegExp('(\\s|^)'+cls+'(\\s|$)'));