11.函数节流和防抖
(1).函数节流
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> html{ height: 500%; } </style> </head> <body> <div id="box"></div> <script type="text/javascript"> //面试题:什么是函数节流?什么是函数防抖 /* 函数节流:一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。 - 有个需要频繁触发的函数,出于优化性能的角度,在规定时间内,只让函数触发的第一次生效,后面不生效。 */ /* *节流函数 * fn 要被节流的函数 * delay 规定的时间 */ function throlle(fn,delay){ //记录上一次触发时间 var lastTime=0; return function(){ //记录当前触发时间 var nowTime=Date.now(); if(nowTime-lastTime>delay){ //修正this指向问题 fn.call(this); // 同步函数 lastTime=nowTime; } } } document.onscroll=throlle(function(){console.log('onscroll事件被触发'+Date.now());},2000); </script> </body> </html>
(2). 防抖函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> html{ height: 500%; } </style> </head> <body> <button id="btn">按钮</button> <script type="text/javascript"> /* 防抖函数:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效 */ /* *防抖函数 * fn 要被防抖的函数 * delay 规定的时间 */ function debounce(fn,delay){ //记录上一次触发时间 var timer=null; return function(){ //清除上一次的延迟 clearTimeout(timer); //重新设置延时器 timer=setTimeout(function(){ //修正this指向问题 fn.apply(this); },delay); } } document.getElementById('btn').onclick=debounce(function(){console.log('点击事件被触发了'+Date.now());},1000); </script> </body> </html>
12.跨域问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"></div> <script type="text/javascript"> // 面试题:什么是跨域?解决跨域的办法有哪些? /* 1.同源策略 - 浏览器安全策略 - 协议名、域名、端口号必须完全一致 2.跨域 -违背同源策略就会产生跨域 3.解决跨域 jsonp、cors、服务代理... (前端) (后端) */ //创建script标签 var script=document.createElement('script'); //设置回调函数 function getDate(data){ console.log(data); } //设置script 的src属性,设置请求地址 script.src='http://localhost:3000?callback=getDate'; //让script生效 document.body.appendChild(script); </script> </body> </html>
13.node.js事件轮询机制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"></div> <script type="text/javascript"> /* 面试题:nodejs的事件轮询机制 */ setTimeout(function(){ console.log('setTimeout()'); },0); setImmediate(function(){ console.log('setImmediate()'); }); process.nextTick(function(){ console.log('process.nextTick()') }) /* process.nextTick() setTimeout() setImmediate() nodejs的事件轮询机制:借助libuv库实现的 包括事件轮询机制,分为6个阶段 1.timers 定时器阶段 计时和执行到点的定时器回调函数 2.pending callbacks 某些操作系统(例如TCP错误类型)的回调函数 3.idle,prepare 准备工作 4.poll轮询阶段 如果轮询队列不为空,依次同步取出轮询队列中的第一个回调函数执行,直到轮询队列为空或者达到系统最大的限制 如果轮询队列为空 如果之前设置过setImmediate函数的 直接进入下一个check阶段 如果之前没有设置过setImmediate函数 在当前poll阶段等待 直到轮询队列添加回调函数,就去第一阶段执行 如果定时器到点了,也进入到下一个阶段 5.check查询阶段 执行setImmediate设置的回调函数 6.close callbacks 关闭阶段 执行close事件回调函数 process.nextTick能在任意阶段优先执行 */ </script> </body> </html>
14.从一个url地址到网页的最终渲染完成,发生了什么?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript"> /* 面试题:从一个url地址到最终页面渲染完成,发生了什么? */ /* 1.DNS解析:将域名地址解析为IP地址 - 浏览器DNS缓存 - 系统DNS缓存 - 路由器DNS缓存 - 网络运营商DNS缓存 - 递归搜索:blog.baidu.com -.com域名下查找DNS解析 -.baidu域名下查找DNS解析 -blog域名下查找DNS解析 -出错了 2.TCP连接:TCP三次握手 - 第一次握手,由浏览器发起,告诉服务器我要发送请求了 - 第二次握手,由服务器发起,告诉浏览器,我准备接收了,你赶紧发送吧。 - 第三次握手,由浏览器发送,告诉服务器,我马上就发了,你准备接收吧 3.发送请求 - 请求报文:HTTP协议的通信内容 4.接受相应 - 响应报文 5.渲染页面 - 遇见HTML标记,浏览器调用HTML解析器解析成Token并构建成dom树 - 遇见style/link标记,浏览器调用css解析器,处理css标记并构建cssom树 - 遇到script标记,调用JavaScript解析器,处理script代码(绑定事件,修改dom树/cssom树) - 根据渲染树来计算布局,计算每个节点的几何信息(布局) - 将各个节点颜色绘制到屏幕上(渲染) 注意:这个五个步骤不一定按照顺序执行,如果dom树或cssom树被修改,可能会执行多次布局和渲染,往往实际页面中,这些步骤会多次执行。 6. 断开连接:TCP四次挥手 第一次挥手,由浏览器发起的,发送给服务器,我东西发送完了,(请求报文)你准备关闭吧。 第二次挥手,由服务器发起的,告诉浏览器,我东西接收完了(请求报文),我准备关闭了,你也准备关闭吧。 第三次挥手,由服务器发起的,告诉浏览器,我东西发送完了(响应报文),你准备关闭吧。 第四次挥手,由浏览器发起的,告诉服务器,我东西接收完了(响应报文),我准备关闭了,你也准备关闭吧。 */ </script> </body> </html>
15.什么是闭包?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript"> /* 理解:什么是闭包? 1.密闭的容器, 类似于set,map容器 2.闭包是一个对象,存放数据的格式:key:value 形成的条件: 1.函数嵌套 2.内部函数引用外部函数的局部变量 闭包的优点: 延长外部函数局部变量的生命周期 闭包的缺点: 容易造成内存泄露 注意点: 1.合理的使用闭包 2.用完闭包要及时清除(销毁) */ // 简单的闭包 function fun(){ let a=1; function b(){ console.log(a); } b(); } fun(); // Global 全局的变量对象 // Local 函数里面局部的变量对象 //闭包的应用场景 function fun(){ let count=1; return function(){ count++; console.log(count); } } var fun2=fun(); fun2(); //2 fun2(); //3 /* 说说它们的输出情况 */ function fun(n,o){ console.log(o) return { fun:function(m){ return fun(m,n) } } } var a=fun(0) a.fun(1) a.fun(2) a.fun(3) //underfined,0,0,0 var b=fun(0).fun(1).fun(2).fun(3)// underfined,0,1,2 var c=fun(0).fun(1) c.fun(2) c.fun(3)// underfined,1,1 </script> </body> </html>
16.变量提升 && 执行上下文
/* 变量升级 预处理 */ /* js引擎在代码正式执行之前会做一个预处理的工作: 1.收集变量 2.收集函数 依据: var 将var后边的变量定义但不赋值 var username=undefined; function(){} */ console.log(username); //答案:underfined var username='kobe'; console.log(username) //kobe fun(); //答案:正常执行函数 function fun(){ console.log('fun()'); } /* 作用域:作用域是在代码定义的时候产生的 //执行上下文 执行上下文对象(this) 执行上下文(excute context) EC 理解:代码执行的环境 时机(产生时):代码正式执行之前会进入到执行环境 工作: 1.创建变量对象: 1)变量 2)函数及函数的参数 3)全局:window 4)局部:抽象的但是确实存在 2.确认this的指向 1)全局:this --->window 2)局部:this --->调用其的对象 3.创建作用域链 父级作用域链+当前的变量对象 4.扩展 ECobj={ 变量对象:{变量,函数,函数的形参} scopeChain(作用域链):父级作用域链+当前的变量对象 this:{window || 调用其的对象} } */