执行环境(execution context,也有称之为执行上下文)是JS语言中最重要的一个概念。javascript
Javascript没有代码块做用域的概念,局部做用域是针对函数来讲的。前端
执行环境定义了变量或者函数有权访问到的其余数据,决定了他们的各自行为。java
每一个执行环境都有一个与之关联的变量对象(variable object),执行环境中定义的全部变量和函数都保存在这个对象中。没法访问,可是解析器在后台执行中要用到。jquery
全局执行环境是最外围的执行环境。根据ECMAScript实现的宿主不一样,表示执行环境的对象也不同。Web浏览器中,全局执行环境是window对象,所以全局函数和全局变量都是做为window的对象和方法。浏览器
某个执行环境中的全部代码执行完毕后将被销毁,全局执行环境在关闭网页的时候才会被销毁。闭包
每一个函数都有本身的执行环境。当执行流进入函数的时候,函数的环境被推入到一个环境栈中。在函数执行之后,栈将其环境弹出,把控制权交给以前的执行环境。框架
当代码在一个环境中执行时,会建立变量对象的一个做用域链(scope chain)。函数
做用域链的做用是:是保证对执行环境有权访问的全部变量和函数的有序访问。做用域的前端始终是当前执行的代码所在的环境变量的变量对象。若是这个环境是一个函数,则将其活动对象(activation object)做为变量对象。做用域链中的下一个变量对象来自于包含环境。全局执行环境始终是做用域链中最后一个对象。ui
标识符解析始终是沿着做用域链一级一级地搜索标识符的过程,前端开始,逐级向上,直到找到标识符为止,找不到就会报错。this
函数的做用域链包含着两个对象:它本身的变量对象(其中定义了arguments),和全局环境的变量对象。
当代码在一个环境中执行时,会建立变量对象的一个做用域链(scope chain)。
做用域链的做用是:是保证对执行环境有权访问的全部变量和函数的有序访问。做用域的前端始终是当前执行的代码所在的环境变量的变量对象。若是这个环境是一个函数,则将其活动对象(activation object)做为变量对象。做用域链中的下一个变量对象来自于包含环境。全局执行环境始终是做用域链中最后一个对象。
标识符解析始终是沿着做用域链一级一级地搜索标识符的过程,前端开始,逐级向上,直到找到标识符为止,找不到就会报错。
函数的做用域链包含着两个对象:它本身的变量对象(其中定义了arguments),和全局环境的变量对象。
虽然js中的执行环境总共就两种:全局和函数(局部),可是仍是有其余的办法来延长做用域链。就是在做用域的前端添加一个临时增长的变量对象。
具体使用:try...catch语句块的catch块;和with语句。
对于with语句来讲,会将指定的对象添加到做用域链中。
function buildUrl(){
var qs = "?debug=ture";
with(location){
var url = href + qs;
}
return url;
}
js中没有块级做用域,只有全局做用域和函数做用域。注意在if语句||for语句中定义的变量会被添加到全局变量中。
可使用自执行语句来模拟块级做用域。
使用var声明的变量会被添加到最接近的环境中,函数内部就是函数做用域。若是初始化没有使用var,就会被添加到全局做用域中。
沿着做用域链向上查找。
闭包与匿名函数不要搞混。
闭包:就是指有权访问另外一个函数做用域中的变量的函数。建立闭包最多见的方式,就是在一个函数做用域内建立另外一个函数。而且返回另外一个函数。
须要闭包的缘由:当使用函数被调用时,会建立一个执行环境(上下文环境)以及相应的做用域链,使用arguments和其余命名参数的值来初始化函数的活动对象(activation object)。函数执行过程就须要在做用域链中查找变量,查找过程不能向下,因此就须要闭包来读取函数内部的变量。闭包会让外层函数的变量一直存在于内存中。直到都不调用为止。
外层函数的变量对象(活动对象)存在于内层函数的做用域链中。
闭包的问题:
一、过分使用闭包会形成内存占用过多。
二、做用域链的这种配置引出一个问题,就是闭包只能取得包含函数中任何变量的最后一个值,闭包保存的是整个变量对象,而不是某个特殊的变量。
这里打印的0~9是console.log打印的。最终保存的结果i都是10。
以上函数,在for循环中使用闭包,这样最后读取到的i是最后一个值。存在风险。改用以下的方式,将当前值保存下来,用一个自执行的闭包函数来保存变量,以后结果传出。
函数的执行依赖于变量做用域,这个做用域在函数定义的时候决定的,不是在函数调用的时候决定的。
古老解释对于闭包:函数对象经过做用域链来相互关联,函数体内的变量均可以保存在函数做用域内。
闭包能够捕捉到局部变量(和参数),并一直保存下来。
应用场景:一、闭包的典型框架应该就是jquery了。
二、闭包是javascript语言的一大特色,主要应用闭包场合主要是为了:设计私有的方法和变量(模块设计,自执行闭包)。
三、这在作框架的时候体现更明显,有些方法和属性只是运算逻辑过程当中的使用的,不想让外部修改这些属性,所以就能够设计一个闭包来只提供方法获取。
优势:1. 逻辑连续,当闭包做为另外一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
2. 方便调用上下文的局部变量。
3. 增强封装性,第2点的延伸,能够达到对变量的保护做用。
缺点:闭包有一个很是严重的问题,那就是内存浪费问题,这个内存浪费不只仅由于它常驻内存,更重要的是,对闭包的使用不当会形成无效内存的产生。
关于闭包,就我本身的习惯而言,能不用就不用,若是非用不可,那就想办法保持闭包对象的数量不多甚至惟一。
this对象在运行时是基于函数的执行环境绑定的:在全局函数中,this等于window,当函数被看成某个对象的方法调用的时候,this等于那个对象,非对象的函数调用,this都会指向window。也就至关于说,谁调用这个函数,this就指向谁。
匿名函数的执行环境具备全局性。这时候this对象指向window。
每当建立一个函数的时候,函数在被调用的时候自动获取两个特殊的变量,this和arguments。