1、什么是闭包?
闭包是指有权访问另一函数作用域中变量的函数。
创建方式:通常是在一个函数内部创建一个私有函数。
2、闭包的实现
闭包是另一个函数内部的函数,根据作用域链闭包函数在创建时作用域就已经确定了,就是它所在的环境,所以它有权访问另一个函数下的变量。
3、作用域和作用域链
- 作用域指的是一个变量的作用范围。
- 作用域链的用途是保证所有执行上下文都有权访问所有变量和函数的有序访问。在作用域链的前端,始终都是执行当前代码所在执行上下文的变量对象,变量对象里存放了内部声明的变量以及入参的arguments对象,作用域链中的下一个变量对象来自外部包含上下文。js里采取词法作用域,创建时就确定了它的作用域,作用域链的定义是静态的。
注意:原本作用域链是一层一层向上查找,js里是函数在声明时就确定了作用发域。
4、闭包的优缺点
- 优点:
- 能够使一个函数访问到另一个函数内部的变量。
- 可以避免全局变量的污染。
- 这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除。
- 缺点:
- 容易造成内存泄露,从而引起内存溢出。
- 闭包函数无法直接访问包含他的函数的this对象, 因为二者的this指向是不一样的. 外部函数的this指向调用他的对象, 内部函数的this指向了全局对象。
使用闭包要注意:闭包使得函数中的变量始终保存在内存中,内存消耗大,所以不要随意使用闭包,否则可能造成网页性能问题,造成内存泄露。解决办法是在推出函数之前把变量赋值为null。
闭包的应用
防抖和节流的原理都使用到了闭包的概念 :闭包的好处是里面的变量只会在闭包中使用,也就是外部的函数是不能使用这个变量的,也就不会修改这个变量,就不会受到外部的污染;
封装的ajax也使用了闭包,把服务器返回的数据赋值给一个变量,利用回调函数当作形参传回来,接收进行处理。
function showId() {
var el = document.getElementById("app")
el.onclick = function(){
aler(el.id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
}
}
// 改成下面
function showId() {
var el = document.getElementById("app")
var id = el.id
el.onclick = function(){
aler(id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
}
el = null // 主动释放el
}
5、内存溢出和内存泄漏
- 内存泄露:是指程序申请了一块内存之后,无法释放,一次内存泄漏可以忽略不计,如果次数多了就容易造成内存溢出。
- 内存溢出:是指申请一块内存的时候,没有足够的内存空间供其使用。比如:申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
6、哪些情况会导致内存溢出?
- 被遗忘的计时器和回调函数
- 闭包
- 脱离dom的应用。就是找到这个节点赋值给一个变量,只要这个变量一直被别人使用,就会一直在内存里存着。(其实使用完之后我们可以把这个变量赋值为null)
- 以外的全局变量
执行上下文
执行上下文是函数执行前的准备工作。
- 执行上下文是js中非常重要的一个概念,它定义了变量和函数有权访问其他数据。每一个执行上下文都有一个与之相关联的而变量对象,里面存放了变量和函数等内容。
- 全局执行上下文是最外围的一个执行上下文,根据ECMAScript的宿主不同,在全局环境下创建的变量都是全局变量,所有的变量和函数都是window的属性和方法。
- 当浏览器刚刚读取到js代码的时候,就会进去全局环境,从而生成全局执行上下文,全局上下文就会进入执行栈(入栈),并保持在栈底。js程序里有很多函数,浏览器读到函数的时候,就会对应生成函数执行上下文,该上下文也会入栈,它会在全局执行上下文的上面,当浏览器在读到一个函数时,还会生成上下文,依次入栈,在栈顶的永远是执行当前代码所在的执行上下文,当代码执行完以后,该执行上下文就会出栈,并且被销毁,里面的变量和函数也都会被销毁。全局上下文是在浏览器关闭时才销毁。
- 在js中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈。
- 由于js是属于单线程(就是从上到下依次的执行代码)的,就是同个时间段只能做一件任务,完成之后才可以继续下一个任务,所以程序中生成多个执行上下文,必须要有一个排队机制,谁先执行谁后执行。
- 栈遵循“先进后出,后进先出”的规则,或称LIFO(“last In first Out”)规则
还有Evavl函数,进入Eval环境,对应生成Eval函数上下文。(现已不推荐使用)
JSON的序列化
json序列划就是将对象转为json字符串
- json对象转为字符串语法:变量名=JSON.stringify(json对象)
- json字符串转为json对象语法:变量名=JSON.parse(json字符串)
- Eval可以把(“(“+jsonstr+”)”)里的代码运行一次,也可以直接把里面的json对象转换为json对象
解释:json是一种轻量级(指结构比较简单)的数据交互格式
js中的数据结构:
- 有序的数据集合:数组(有序指的是数组元素索引值都是有序的,从0开始)
- 无序的数据集合:对象(它是对象里典型的数据结构)
-
同步和异步
Javascript的单线程,与它的用途有关,作为浏览器脚本语言,javascript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
- Js是单进程、单线程的
- 单线程指的就是代码从上到下依次执行代码。
- 单进程:指的是只能干一件事。
- 浏览器是多进程、多线程的
- 多进程:干这件事情的时候也可以干这件事情。
所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,如果前一个任务耗时很长,后一个任务不得不一直等着,这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延这个程序的执行,常见的浏览器无响应(假死),往往就是因为某一段JavaScript代码运行时间较长(比如死循环),导致整个页面卡在这个地方,其他程序无法执行。于是就有一个概念——任务队列。
同步任务异步任务概念:
- 同步任务:所有同步任务都是放在主线程上的,只有上一个同步任务执行完以后,才能执行下一个任务。
- 异步任务:指的是不进入主线程,直接进入任务队列,一个异步任务有了结果,就会在异步里面放一个事件,会通知主线程可以执行了,该任务才会进入主线程执行。
- “任务队列“是一个事件的队列(也可以理解成消息的队列),IO(输入输出)设备完成一项任务,就在”任务队列“中添加一个事件,表示相关的异步任务可以进入”执行栈“了,,主线程读取”任务队列“,就是读取里面有哪些事件。
- “任务队列“中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入”任务队列“,等待主线程读取。
- 任务队列采取的是先进先出的顺序执行
事件轮询机制(问的也是同步异步问题)
具体来说,异步执行的运行机制如下。(同步执行也是如此,因为它可以被视为没有异步任务的异步执行)
(1) 所有同步任务都在主线程上执行,形成一个执行栈。
(2) 主线程之外,还存在一个“任务队列“(task queue)。只要异步任务有了运行结果,就在”任务队列“之中放置一个事件。
(3) 一旦“执行栈“中的所有同步任务执行完毕,系统就会读取”任务队列“,看看里面有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4) 主线程不断重复上面的第三步。
只要主线程空了,就会读取“任务队列“,这是JavaScript的运行机制,这个过程会不断重复,称之为”事件循环机制“(event loop)。
处理异步的几种方法
- 回调函数
- 事件监听
- 发布订阅
- promise对象(promise对象)
- setTimeout/setInterval/js里创建new Image()对象,它的src是异步的
同源策略
同源策略:浏览器自带的功能。
同源:指的是域名、协议、端口相同。
同源策略:指的是只有同源的两个页面才可以传输数据。(浏览器中规定只有同源的页面才可以传输数据)
同源策略是一种约定 ,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能都会受到影响。可以说web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持javascript的浏览器都会使用这个策略。
例如:当一个浏览器的两个tab页中分别打开百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面,即检查是否同源,只有和百度同源的脚本才会被执行,如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
Ajax是同源的,不支持跨域传输数据
非同源的就称之为跨域(理论上浏览器是不允许跨域传值的)
AJAX
ajax的工作原理
- js程序先创建一个XMLHttpRuquest()对象;
- 使用ajax对象向服器发送HTTP请求。
- 服务器响应请求并返回给客户端
- js程序接收到数据,并通过浏览器显示在窗口上
客户端向服务器发送请求时,由ajax引擎代替它发送请求给服务器,服务器响应请求给ajax引擎,它把返回的数据在转发给浏览器。以前的时候都是浏览器发送请求,必须等待数据请求回来之后才可以做下一次的事情,而通过ajax请求之后浏览器可以继续做别的事情,不需要再等待了 封装Ajax
ajax的实现
function my_ajax(url,callback,data,method){
method=method || 'post';
var xmlHttp=new XMLHttpRequest();
xmlHttp.open(method,url);
xmlHttp.setRequestHeader('content-type','application/x-www-form-urlencoded');
xmlHttp.send(data);
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200){
var data=xmlHttp.responseText;
callback(data);
}
}
}
整个程序只有send和onreadystatechange事件是异步的
ajax的状态码
- 0 请求未初始化(没有使用open方法)
- 1 建立连接,但未发送(使用了open,没有使用send方法)
- 2 服务器已接收到请求,正在处理中
- 3 服务器处理中,并已经相应一些数据可供使用,还没哟完全响应
- 4 请求已完成,相应已就绪,可以获得并使用数据 服务器的状态码
- 200 请求成功
- 301 请求的资源永久转移到其他url
- 404 请求的资源不存在
- 501 服务器不支持的请求方式
- 500 服务器内部错误,返回时多一个状态码
- 204 无内容,服务器已经响应了,但没有返回内容,在不刷新页面的情况下,保证用户还能继续访问页面
- 401 客户端请求语法错误,服务器无法理解
- 2xx 请求成功 - - 3xx重定向 - - 4xx客户端问题 - 5xx服务器错误
jquery的ajax
在juqery里是把ajax封装成了jquery对象的方法;
$.ajax({
url:"接口文档请求地址url";
dataType:"期待返回数据的类型,可以设置为json/text等,如果返回的和预期不一样,也不会强制转换"
type:"请求方式"
async:"设置ajax是同步还是异步"
data:"传输的数据"
success:"function(data){}处理函数,在这里设置形参接收服务器返回的数据"
})
$.get(url,callback)//设置callback形参接收服务器返回的数据
$.post(url,data(向服务器传输的数据,格式为json),callback)
HTTP工作原理
http通过三次握手实现。
- 首先客户端与服务器建立连接,只要用户做了一个点击的动作,http就已经开始工作了。
- 成功建立连接后,浏览器向服务器发送请求,请求格式为协议版本号,请求方式,MIME信息以及修饰符,需要携带的数据。
- 服务器处理信息,并响应请求给浏览器。返回的是一个状态行,首先是一个成功或错误的代码,MIME信息以及请求的数据及相关内容。
- 客户端接收到信息后,通过浏览器把请求会的数据渲染到用户的显示屏,并断开连接。
http请求构成
- http请求方式:get/post
- http请求url地址
- http请求头包含的内容
- http请求正文(这里一般是发送给服务器的数据)
http缓存 web缓存是一种缓存web资源副本并在下一次请求使用该副本的技术。
web缓存分为http缓存,CDN缓存、数据库缓存、服务器缓存。
http缓存机制:分为强缓存和协商缓存。强缓存和协商缓存最大的区别是强缓存不会向服务器发送请求,如果客户端有强缓存并命中,会直接显示在浏览器上,协商缓存是一定会向服务器发送请求,并通过请求资源的首部字段验证是否命中协商缓存,命中的划服务器返回请求,不会返回资源实体,而是可以通过客户端可以从缓存中加载这个资源。(如果没有强缓存,再去看有没有协商缓存)
http概念:http(HyperText Transfer Protocol:超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。简单来说就是一种发布和接收HTML页面的方法,被用于web浏览器和网站服务器之间传递信息。
https概念:HTTPS(HyperText Transfer Protocol Secure:超文本传输安全协议)是一种透过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包,HTTPS开发的主要目的,是提供网站服务器的身份认证,保护交换数据的隐私与完整性。
http和https的区别
- HTTP明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP)数据传输过程是加密的,安全性较好。
- 使用HTTPS协议需要到CA(certificate Authority,数字整数认证机构)申请证书,一般免费证书较少,因为需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy和GlobalSign等。
- HTTP页面响应速度比HTTPS快,主要是因为HTTP使用TCP三次握手建立连接,客户端服务器需要交换3个包,而HTTPS除了TCP的三个包,还要加上ssl握手需要的9个包,所以一共是12个包。
- HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443.
- HTTPS其实就是建构在SSL/TLS之上的HTTP协议,所以,要比较HTTPS比HTTP要更耗费服务器资源。