欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2017前端面试题总结

程序员文章站 2022-06-09 11:09:59
...

2017前端面试题总结

1:为何选择前端这个方向和对前端的理解

为什么:

第一的话就是对前端很感兴趣,之前也接触过其他的语言,但是直到接触到前端才发现真的有兴趣做下去,兴趣是一个人最好的老师,

第二的话前端很有前途,像现在nodejs,rn,微信小程序这类工具和框架可以让前端进行后端和移动开发,所以我觉得前端的前途会更多一点。

理解:

首先前端工程师最核心的技能还是:Html、CSS、JS。前端负责的是用户可以看到的部分,所以也是最接近用户的工程师。同时在产品研发流程中前端要同时与产品、设计、后端等很多人合作。

2:Vue双向数据绑定的实现

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者(文本节点则是作为订阅者),在收到消息后执行相应的更新操作。

compile主要做的事情是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

AngularJS 采用“脏值检测”的方式,数据发生变更后,对于所有的数据和视图的绑定关系进行一次检测,识别是否有数据发生了改变。

3:react和vue有哪些不同 说说你对这两个框架的看法

都用了virtual dom的方式, 性能都很好

ui上都是组件化的写法,开发效率很高

vue是双向数据绑定,react是单项数据绑定,当工程规模比较大时双向数据绑定会很难维护

vue适合不会持续的 小型的web应用,使用vue.js能带来短期内较高的开发效率. 否则采用react

4:let和const的区别

let声明的变量可以改变,值和类型都可以改变,没有限制。

const声明的变量不得改变值

5:平时用了es6的哪些特性,体验如何 和es5有什么不同

let const关键字 箭头函数 字符串模板 class类 模块化 promise

es5 require react.createclass

6:浏览器原生支持module吗,如果支持,会带来哪些便利

不支持

7:介绍一下你对webpack的理解,和gulp有什么不同

Webpack是模块打包工具,他会分析模块间的依赖关系,然后使用loaders处理它们,最后生成一个优化并且合并后的静态资源。

gulp是前端自动化工具 能够优化前端工作流程,比如文件合并压缩

8:webpack打包速度慢,你觉得可能的原因是什么,该如何解决

模块太多

Webpack 可以配置 externals 来将依赖的库指向全局变量,从而不再打包这个库 或者dllplugin

webpack-parallel-uglify-plugin 并行压缩

CommonsChunkPlugin提取公共的模块

happypack 多进程构建

9:http响应中content-type包含哪些内容

请求中的消息主体是用何种方式编码

application/x-www-form-urlencoded

这是最常见的 POST 提交数据的方式 按照 key1=val1&key2=val2 的方式进行编码

application/json

告诉服务端消息主体是序列化后的 JSON 字符串

10:浏览器缓存有哪些,通常缓存有哪几种方式

强缓存 强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。

协商缓存 当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回(304),若未命中请求,则将资源返回客户端,并更新本地缓存数据(200)。

HTTP头信息控制缓存

Expires(强缓存)+过期时间 Expires是HTTP1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间

Cache-control(强缓存) 描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断 管理更有效,安全一些 Cache-Control: max-age=3600

服务端返回头Last-Modified/ 客户端请求头If-Modified-Since(协商缓存) 标示这个响应资源的最后修改时间。Last-Modified是服务器相应给客户端的,If-Modified-Sinces是客户端发给服务器,服务器判断这个缓存时间是否是最新的,是的话拿缓存。

服务端返回头Etag/客户端请求头If-None-Match(协商缓存) etag和last-modified类似,他是发送一个字符串来标识版本。

强缓存不请求服务器,客户端判断 、协商缓存要请求服务器

11:如何取出一个数组里的图片并按顺序显示出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

function loadImage(imgList,callback){
if(!.isArray(imgList)!.isArray(imgList) || !.isFunction(callback)) return ;
var imageData = [] ;
$.each(imgList, function(i,src){
var img = new Image() ;
img.onload = function(){
$(imageData.shift()).appendTo(“body”) ;
if(!imageData.length){
callback() ;
return ;
}
this.onload = null ;
} ;
img.src= src ;
imageData.push(img) ;
}) ;
} ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

async function loadImgs(imgList, cb) {

console.log("start")
for( var i =0; i<imgList.length; i++) {
    await imgLoader(imgList[i], i);
    console.log("finish"+i)
}
cb();

}

async function imgLoader(url, num){
return new Promise((resolve, reject) => {
console.log(“request”+num)

    setTimeout(resolve, 1000);
    // let img = new Image();
    // img.onload = () => resolve(img);
    // img.onerror = reject;

    console.log("return"+num)
})

}

loadImgs([“xxx/a.png”,“xxx/b.png”],function() {
console.log(“开始干活”);
})

12:平时是怎么学新技术的

伯乐在线 infoq 掘金 简书 慕课网

13:Node,Koa用的怎么样

koa是一个相对于express来说,更小,更健壮,更富表现力的Web框架,不用写回调

koa是从第一个中间件开始执行,遇到next进入下一个中间件,一直执行到最后一个中间件,在逆序

async await语法的支持

14:使用模块化加载时,模块加载的顺序是怎样的,如果不知道,根据已有的知识,你觉得顺序应该是怎么样的

commonjs 同步 顺序执行

AMD 提前加载,不管是否调用模块,先解析所有模块 requirejs 速度快 有可能浪费资源

CMD 提前加载,在真正需要使用(依赖)模块时才解析该模块 seajs 按需解析 性能比AMD差

15: 介绍一下闭包和闭包常用场景

闭包是指有权访问另一个函数作用域中的变量的函数. 创建闭包常见方式,就是在一个函数内部创建另一个函数.
本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

应用场景 设置私有变量和方法让这些变量的值始终保持在内存中还有读取函数内部变量。

不适合场景:返回闭包的函数是个非常大的函数

闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

function f1(){

var n=999;

function f2(){
    alert(n);
  }

return f2;

}

var result=f1();

result(); // 999

16: 为什么会出现闭包这种东西,解决了什么问题

受JavaScript链式作用域结构的影响,父级变量中无法访问到子级的变量值,为了解决这个问题,才使用闭包这个概念

17: 介绍一下你所了解的作用域链,作用域链的尽头是什么,为什么

每一个函数都有一个作用域,比如我们创建了一个函数,函数里面又包含了一个函数,那么现在 就有三个作用域,这样就形成了一个作用域链。

作用域的特点就是,先在自己的变量范围中查找,如果找不到,就会沿着作用域链往上找。

18: 一个Ajax建立的过程是怎样的,主要用到哪些状态码

ajax:在不切换页面的情况下完成异步的HTTP请求

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.

(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

(3)设置响应HTTP请求状态变化的函数.

(4)发送HTTP请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.
1
2
3
4
5
6
7
8
9
10
11
12
13

var xmlHttp = new XMLHttpRequest();

xmlHttp.open(‘GET’,‘demo.php’,‘true’);

xmlHttp.send()

xmlHttp.onreadystatechange = function(){

  if(xmlHttp.readyState === 4 & xmlHttp.status === 200){

  }

}

使用promise封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

function getJSON(url) {
return new Promise(function(resolve, reject) {
var XHR = new XMLHttpRequest();
XHR.open(‘GET’, url, true);
XHR.send();

    XHR.onreadystatechange = function() { 
        if (XHR.readyState == 4) { 
            if (XHR.status == 200) { 
                try { 
                    var response = JSON.parse(XHR.responseText); 
                    resolve(response); 
                } catch (e) { 
                    reject(e); 
                } 
            } else { 
                reject(new Error(XHR.statusText)); 
            } 
        } 
    } 
}) 

}

getJSON(url).then(res => console.log(res));

当前状态readystate

0 代表未初始化。 还没有调用 open 方法
1 代表正在加载。 open 方法已被调用,但 send 方法还没有被调用
2 代表已加载完毕。send 已被调用。请求已经开始
3 代表交互中。服务器正在发送响应
4 代表完成。响应发送完毕

常用状态码status

404 没找到页面(not found)
403 禁止访问(forbidden)
500 内部服务器出错(internal service error)
200 一切正常(ok)
304 没有被修改(not modified)(服务器返回304状态,表示源文件没有被修改)

19: 说说你还知道的其他状态码,状态码的存在解决了什么问题

302/307  临时重定向

301 永久重定向

借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了什么错误

20: 知道语义化吗?说说你理解的语义化,如果是你,平时会怎么做来保证语义化

像html5的新的标签header,footer,section等就是语义化

一方面,语义化就是让计算机能够快速的读懂内容,高效的处理信息,可以对搜索引擎更友好。

另一方面,便于与他人的协作,他人通过读代码就可以理解你网页标签的意义。

21: 说说content-box和border-box,为什么看起来content-box更合理,但是还是经常使用border-box

content-box 是W3C的标准盒模型 元素宽度=内容宽度+padding+border

border-box 是ie的怪异盒模型 他的元素宽度等于内容宽度 内容宽度包含了padding和border

比如有时候在元素基础上添加内距padding或border会将布局撑破 但是使用border-box就可以轻松完成

22:介绍一下HTML5的新特性

新的DOCTYPE声明  <!DOCTYPE html> 
完全支持css3
video和audio
本地存储
语义化标签
canvas
新事件 如ondrag onresize

23:对自己未来的规划是怎样的

对于刚毕业的人来说,前两年是很重要的,先打好基础,多提升js能力。三至四年在提升JS能力的同时,开始要往多方面发展,前端工程师远远不仅是JS而已。制作一个性能高、交互好、视觉美的页面,需要从前端框架选型、架构设计、构建工具,到后端通信机制、设计与交互、网络和浏览器优化等各方面的知识。一专多长才是前端工程师的终极目标。

24: 在一个UI李有10个li,实现点击对应的li,输出对应的下标
1
2
3
4
5
6
7
8

var lis = querySelectorAll(‘li’)
for(var i=0;i<10;i++){
lis[i].onclick = (function(a) {
return function() {
alert(a)
}
})(i)
}

事件委托

利用冒泡的原理,把事件加到父级上,触发执行效果。

1.可以大量节省内存占用,减少事件注册。
2.可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13

var ul = document.querySelector(‘ul’);
var list = document.querySelectorAll(‘ul li’);

ul.addEventListener(‘click’, function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElemnt;

for(var i = 0, len = list.length; i < len; i++){ 
    if(list[i] == target){ 
        alert(i + "----" + target.innerHTML); 
    } 
} 

});

25:实现三个DIV等分排布在一行(考察border-box)

1.设置border-box width33.3%

2.flexbox flex:1

26: 说说你知道JavaScript的内存回收机制

垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存。

一般使用标记清除方法 当变量进入环境标记为进入环境,离开环境标记为离开环境

还有引用计数方法

堆栈

stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小不定也不会自动释放。

基本数据类型存放在栈中

引用类型 存放在堆内存中,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据

27函数防抖和函数节流

函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次

函数防抖的要点,也是需要一个setTimeout来辅助实现。延迟执行需要跑的代码。
如果方法多次触发,则把上次记录的延迟执行代码用clearTimeout清掉,重新开始。
如果计时完毕,没有方法进来访问触发,则执行代码。
1
2
3
4
5
6
7
8

//函数防抖
var timer = false
document.getElementById(“debounce”).onScroll = function() {
clearTimeout(timer)
timer = setTimeout(function(){
console.log(‘函数防抖’)
}, 300)
}

函数节流是指一定时间内js方法只跑一次

函数节流的要点是,声明一个变量当标志位,记录当前代码是否在执行。
如果空闲,则可以正常触发方法执行。
如果代码正在执行,则取消这次方法执行,直接return。
1
2
3
4
5
6
7
8
9
10
11
12

//函数节流
var canScroll = true;
document.getElementById(‘throttle’).onScroll = function() {
if (!canScroll) {
return;
}
canScroll = false;
setTimeout(function(){
console.log(‘函数节流’);
canScroll = true;
},300)
}

28:编程实现输出一个数组中第N大的数据

29.实现两栏布局有哪些方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14

*{margin:0; padding: 0;}
html,body{
height: 100%;/高度百分百显示/
}
#left{
width: 300px;
height: 100%;
background-color: #ccc;
float: left;
}
#right{
height: 100%;
margin-left: 300px;
background-color: #eee;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

*{margin:0; padding: 0;}
html,body{
height: 100%;/高度百分百显示/
}
#left{
width: 300px;
height: 100%;
background-color: #ccc;
float: left;
}
#right{
height: 100%;
overflow:hidden;
background-color: #eee;
}

第二种方法,我利用的是创建一个新的BFC(块级格式化上下文)来防止文字环绕的原理来实现的。BFC就是一个相对独立的布局环境,它内部元素的布局不受外面布局的影响。它可以通过以下任何一种方式来创建:
float 的值不为 none
position 的值不为 static 或者 relative
display 的值为 table-cell , table-caption , inline-block , flex , 或者 inline-flex 中的其中一个
overflow 的值不为 visible

第三种flex布局

30:设置width的flex元素,flex属性值是多少

flex属性是flex-grow, flex-shrink 和 flex-basis的简写

flex-grow属性定义项目的放大比例,默认为0

flex-shrink属性定义了项目的缩小比例,默认为1

flex-basis属性定义了项目的固定空间

31get和post有什么不同

get是从服务器上获取数据,post是向服务器传送数据

get请求可以将查询字符串参数追加到url的末尾; post请求应该把数据作为请求的主体提交.

get请求数据有大小限制;post没有

post比get安全性更高

32:cookie和session有什么联系和区别

cookie数据存放在客户的浏览器上,session数据放在服务器上。

session比cookie更安全

单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

一般用cookie来存储sessionid

33:判断链表是否有环

使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。

34:输出二叉树的最小深度

判断左子树或右子树是否为空,若左子树为空,则返回右子树的深度,反之返回左子树的深度,如果都不为空,则返回左子树和右子树深度的最小值。

35: javaScript中的this是什么,有什么用,它的指向是什么

全局代码中的this 是指向全局对象

作为对象的方法调用时指向调用这个函数的对象。

作为构造函数指向新创建的对象

使用apply和call设置this

36写一个快速排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

var quickSort = function (arr){
if(arr.lenght <= 1) {
return arr;
}

   var left = [];
   var right = [];
   var mid = arr.splice(Math.floor(arr.length/2), 1);

   for(var i=0;i<arr.length;i++){
         if(arr[i]<mid) {
             left.push(arr[i]);
        }
         if(arr[i]>mid) {
             right.push(arr[i]);
        }
      return quickSort(left).concat(mid, quickSort(right));
 }  

}

37怎么实现从一个DIV左上角到右下角的移动,有哪些方法,都怎么实现

改变left值为window宽度-div宽度 top值为window高度-div高度

jquery的animate方法

css3的transition

38: 简单介绍一下promise,他解决了什么问题

Promise,就是一个对象,用来传递异步操作的消息。有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

39: 写一个组合继承
1
2
3
4
5
6
7
8
9

var Super = function(name){
this.name = name;
}
Super.prototype.func1 = function() { console.log(‘func1’); }
var Sub = function(name,age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();

40:深拷贝方案有哪些,手写一个深拷贝
1
2
3
4
5
6
7

var clone = function(v) {
var o = v.constructor === Array ? [] : {};
for (var i in v) {
o[i] = typeof v[i] === “Object” ? clone(v[i]) : v[i];
}
return o;
}

41:判断数组有哪些方法

a instanceof Array
a.constructor == Array
Object.prototype.toString.call(a) == [Object Array]

42: 跨域通信有哪些方案,各有什么不同

JSONP:由于同源策略的限制,XmlHttpRequest只允许请求当前源,script标签没有同源限制

通过动态

简述原理与过程:首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成一个function , function 名字就是传递上来的参数。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里
1
2
3
4
5
6
7
8
9
10
11

74.setTimeout,setInterval,requestAnimationFrame之间的区别

setInterval如果函数执行的时间很长的话,第二次的函数会放到队列中,等函数执行完再执行第二次,导致时间间隔发生错误。

而settimeout一定是在这个时间定时结束之后,它才会执行

requestAnimationFrame是为了做动画专用的一个方法,这种方法对于dom节点的操作会比较频繁。

75.webpack常用到哪些功能

设置入口 设置输出目 设置loader extract-text-webpack-plugin将css从js代码中抽出并合并 处理图片文字等功能 解析jsx解析bable

76.介绍sass

&定义变量 css嵌套 允许在代码中使用算式 支持if判断for循环

77.websocket和ajax轮询

Websocket是HTML5中提出的新的协议,注意,这里是协议,可以实现客户端与服务器端的通信,实现服务器的推送功能。

其优点就是,只要建立一次连接,就可以连续不断的得到服务器推送的消息,节省带宽和服务器端的压力。

ajax轮询模拟长连接就是每个一段时间(0.5s)就向服务器发起ajax请求,查询服务器端是否有数据更新

其缺点显而易见,每次都要建立HTTP连接,即使需要传输的数据非常少,所以这样很浪费带宽

78.tansition和margin的百分比根据什么计算

transition是相对于自身,margin相对于参照物

79.冒泡排序、快速排序、去重、查找字符串最多值
1
2
3
4
5
6
7
8
9
10
11
12
13

//冒泡排序
var bubbleSort = function(arr) {
for (var i = 0; i < arr.length-1; i++) {
for (var j = i+1; j < arr.length; j++) {
if (arr[i]>arr[j]) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

//快速排序
var quickSort = function(arr) {
if (arr.length <= 1) {
return arr;
}
var len = arr.length;
var midIndex = Math.floor(len/2);
var mid = arr.splice(midIndex,1);
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < mid) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat(mid,quickSort(right))
}

1
2
3
4
5
6
7
8
9
10
11
12

// 去重
var distinct = function(arr) {
var map = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
if (!map[arr[i]]) {
map[arr[i]] = true;
result.push(arr[i]);
}
}
return result;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

//查找字符串中最多的值
var search = function(str) {
var json = {};
var max = 0;
var char;
for (var i = 0; i < str.length; i++) {
if (!json[str[i]]) {
json[str[i]]=1;
} else {
json[str[i]]++;
}
}
console.log(json);
for(var i in json){
if(json[i]>max){
max = json[i];
char = i;
}
}
console.log(max, char);
}

80.函数组合继承

原型继承、构造函数继承、call aplly继承
1
2
3
4
5
6
7
8
9

var Super = function(name){
this.name = name;
}
Super.prototype.func1 = function() { console.log(‘func1’); }
var Sub = function(name,age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();

81.事件绑定
1
2
3
4
5
6
7
8
9

var addEvent = function(e, type, handler, capture ) {
if (e.addEventListener) {
e.addEventListener(type, handler, capture);
} else if (e.attachEvent) {
e.attachEvent(‘on’+type, handler);
} else {
e[‘on’+type] = handler;
}
}

82.浅克隆和深度克隆

1
2
3
4
5
6
7
8
9

//浅克隆
function extendCopy§ {
    var c = {};
    for (var i in p) {
      c[i] = p[i];
    }
    c.uber = p;
    return c;
 }
1

1
2
3
4
5
6
7
8

//深度克隆
var clone = function(v) {
var o = v.constructor === Array ? [] : {};
for (var i in v) {
o[i] = typeof v[i] === “Object” ? clone(v[i]) : v[i];
}
return o;
}

es6的深度克隆

通过Object.getPrototypeOf函数得到obj被克隆函数的原型上的属性,然后通过Object.assign实现深度克隆。

1
2
3
4

const deepClone=(obj)=>{
var proto=Object.getPrototypeOf(obj);
return Object.assign({},Object.create(proto),obj);
}

83.实现一个秒针绕一点转动的效果
1
2
3
4
5
6
7
8
9
10
11
12

animation: move 60s infinite steps(60);
/设置旋转的中心点为中间底部/
transform-origin: center bottom;
/旋转从0度到360度/
@keyframes move {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

84.移动端兼容问题

IOS移动端click事件300ms的延迟响应

一些情况下对非可点击元素如(label,span)监听click事件,ios下不会触发,css增加cursor:pointer就搞定了

85.bootstrap的栅格系统如何实现的

box-sizing: border-box;
container row column设置百分比

85.js基本类型及判断方法

null, undefined,bool,number,string,object,symbol(es6 独一无二)

1.typeof()出来的没有null 对象,数组和null typeof(x) = “object”

2.instanceof() 对象的原型是否在对象的原型链上

如下:判断Person的原型是否在p的原型链上
1
2
3

function Person(){};
var p =new Person();
console.log(p instanceof Person);//true

3.Object.prototype.toString.call()

每种对象对toString都进行了改写,只有Object.prototype.toString.call(obj)可以进行类型判断
1
2
3
4

var a=new Number(12);
var toString=Object.prototype.toString;
console.log(toString.call(a));//’[object Number]’’
console.log(a.toString());//‘12’

86 JavaScript为什么是单线程?eventloop

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。

比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

异步执行:

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

node里的process.nextTick指定的回调函数是在本次”事件循环”触发,而setImmediate指定的是在下次”事件循环”触发,所以很显然,前者总是比后者发生得早,而且执行效率也高。

87 http http2 https

http(超文本传输协议)是一种常用于应用层的协议,它是基于文本传输内容。

https可以称为http安全版,主要是http下增加了SSL(安全套接层)或者TSL(传输层安全),在SSL或TSL在传输层对数据进行了加密处理。

http/2(超文本传输协议第二版),他对http进行了一些升级改造

新的二进制格式
多路复用
header压缩
支持server push

87 枚举

88 meta属性

1.name 网页描述

a.keword

b.description

c.viewport

2.http-equiv http相关描述

a.content-type

b.cache-control

c.expires

89 react 相关

react router:

实现URL与UI界面的同步。其中在react-router中,URL对应Location对象,而UI是由react components来决定的,这样就转变成location与components之间的同步问题。

react事件:

React并不是将click事件绑在该div的真实DOM上,而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装并交由真正的处理函数运行。

90 js css加载顺序

js全阻塞,css半阻塞

JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载。
CSS 不会阻塞后续 DOM 结构的解析,不会阻塞其它资源(如图片)的加载,但是会阻塞 JS 文件的加载。
现代浏览器很聪明,会进行 prefetch 优化,浏览器在获得 html 文档之后会对页面上引用的资源进行提前下载。

js为什么阻塞?

JS 运行在浏览器中,是单线程的,每个 window 一个 JS 线程,所以当然会阻塞后续 DOM 树的解析咯。
JS 有可能会修改 DOM 结构,给 DOM 添加样式等等,所以这就意味着在当前 JS 加载执行完成前,后续资源的加载可能是没有意义的

css为什么阻塞js?

JS 代码在执行前,浏览器必须保证在 JS 之前的所有 CSS 样式都解析完成,不然不就乱套了,前面的 CSS 样式可能会覆盖 JS 文件中定义的元素样式,这是 CSS 阻塞后续 JS 执行的根本原因。

defer,async?

JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载,这是在没有考虑到 defer, async 的情况下。

由于现代浏览器都存在 prefetch,所以 defer, async 可能并没有太多的用途,可以作为了解扩展知识,仅仅将脚本文件放到 body 底部就可以起到很不错的优化效果。
defer 和 async 都是异步加载脚本文件,defer异步加载,最后执行。
慎用 async,因为它完全不考虑依赖关系,只要下载完后就加载,不考虑此时页面样式先后的加载顺序,不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics。
耗时较长的脚本代码可以使用 defer 来推迟执行。
  1. 三次握手四次挥手

第一次握手:客户端请求与服务端建立连接。第二次:服务端返回确认信息。第三次:客户端收到。

客户:喂?你在吗?我想跟你聊会儿天儿!(发送SYN请求同步报文)

服务:好的,我听着呢(发送SYN请求同步报文,意思是说,咱俩同步着呢),你说吧!(发送ACK确认报文,即可以说了)

客户:好的!(发送ACK确认报文,开始吐槽XXXX)

第一次挥手:客户端传完了,想要断开连接。第二次:服务端收到,半关闭状态。第三次:服务端没信息发了,发送结束报文。第四次:客户端确认,关闭。

然后客户有事儿要挂电话了,又有了下面一段对话,即四次挥手:

客户:我有事儿要挂电话了!(发送Fin结束报文,1次挥手)

服务:好吧(发送ACK确认报文,2次挥手),对了,还有个事儿要跟你说!

服务:好了,就这些了,挂了吧!(发送Fin结束报文,3次挥手)

客户:行,挂了吧!(发送ACK确认报文,4次挥手)

服务挂断电话…

2MSL后…

客户:喂,你还在吗?

啪!(这才断开连接)

为什么四次挥手?

当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了。

但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,