javascript 执行环境,做用域链和闭包

首先看下这条语句:数组

(function($) {…})(jQuery);闭包

1.原理:函数

function(arg){…}
这就定义了一个匿名函数,参数为argthis

而调用函数时,是在函数后面写上括号和实参的,因为操做符的优先级,函数自己也须要用括号,即:
(function(arg){…})(param)
这就至关于定义了一个参数为arg的匿名函数,而且将param做为参数来调用这个匿名函数spa

而(function($){…})(jQuery)则是同样的,之因此只在形参使用$,是为了避免与其余库冲突,因此实参用jQuery
至关于code

funtion output(s){…};对象

output(jQuery);blog

或者索引

var fn=function(s){…};fn(jQuery);内存

2.做用:

这种写法的最大好处是造成闭包。在(function($) {…})(jQuery)在内部定义的函数和变量只能在此范围内有效。

造成私有函数、私有变量的概念。

几个概念:

一、执行环境(execution context):

每一个函数都有本身的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行后,栈将其环境弹出,把控制权返回给以前的执行环境。

二、做用域链(scope chain):

函数的内部环境能够经过做用域链访问到全部的外部环境,可是外部环境却不能够访问外部环境,这就是做用域

ES5中只有全局做用域和函数做用域,没有块级做用域。

(但在ES6中多了一个let,他能够保证外层块不受内层块的影响。即内层块造成了一个块级做用域,这是let的一个特色。

它不简单,由于在许多的函数嵌套的情景下,只有对它理解深入,才能更好的去分析。)

三、闭包 :指有权访问另外一个函数做用域中的变量的函数

建立闭包的常见方式,就是在一个函数内部建立另外一个函数(一般是匿名函数)。

在一个函数a内部定义的另外一个函数b,当b在a以外被执行时,就会造成闭包。同时b函数仍然能够访问到a函数中的局部变量与函数。

弊端:闭包会携带包含他的函数的做用域,会比其余函数占用更多的内存。因此请慎用闭包

function fn(){
  var array=[];
  for(var i=0;i<10;i++){
     array[i]=function(){
        return i;
}
}
return array;
}
fn();//[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]

咱们的本意是获得这个数组中每一个函数都能返回本身的索引值,但是获得的是每一个函数却都返回了10.

闭包保存的是定义它的那个函数内部的局部变量丶参数和其余内部函数,也就是说保存的是这个函数执行上下文中的整个VO,而不是一个变量。上面代码中的函数做用域链中都保存着fn的活动对象,他们引用的都是一个i,当fn返回时,i的值是10,因此每一个函数都引用保存i那个变量的同一个变量。咱们若是想获得原先想获得的那个结果,能够加上另外一个匿名函数改变他的父做用域(其实应该是建立它的做用域),将它包裹起来。

function fn(){
  var array=[];
  for(var i=0;i<10;i++){
     array[i]=function(num){
        return function(){
           return num;
};
}(i);
}
return array;
}

这个匿名函数有一个参数num,同时是返回值。在调用每一个匿名函数时,传入了变量i。因为参数是按值传递的,因此i就会复制给num,而这个匿名函数的内部又建立了一个访问num的闭包,返回后可以访问到该匿名函数中的VO(包括参数),因而每一个函数返回的都是num的一个副本,因此能够获得不一样的值。

其实,说了这么多,咱们只要熟悉闭包的两个应用场景,就能比较好的理解闭包的意义。

一.做为函数的返回值.。做为函数返回值被执行后仍然能够访问定义它的那个函数环境的VO。

function f(){
   var a=1;
   return function(){
      console.log(a);
}  
}

var g=f();
g();//1;

二.做为一个函数的参数。做为函数返回值被当作另外一个函数的参数传入时,仍然是访问定义它的那个函数环境的VO

function f(){
   var a=1;
   return function(){
      console.log(a);
}  
}
var g=f();
g();//1;


function F(fn){
var a=2;
fn();
}
F(g);//1

上面两个小例子也正好说明了闭包能够访问定义它的那个函数做用域下的内部变量和内部函数。实际上是整个VO,因此还包含参数。

关于this对象

咱们知道,this对象是在运行时基于函数的执行环境绑定的,全局函数中,this=window;

当某个函数被做为某个对象的方法调用时,this=对象

匿名函数的执行环境具备全局性,所以其this对象一般指向window

因此在闭包中使用this对象或arguments对象,必须将该对象的引用保存到闭包可以访问到的另外一个变量中。

相关文章
相关标签/搜索