二、闭包

2019-03-30  本文已影响0人  萘小蒽

\color{#ea4335}{一、闭包概念}\

闭包是指有权访问另一个函数作用域的变量的函数。

function createComparisonFunction(propertyName){
    return function(object1,object2){
          var value1 =  object1[propertyName];  // 注意点
          var value2 =  object2[propertyName];  // 注意点
         if(value1 < value2){
               return - 1;
          }else if(value1 > value2){
               return  1; 
          }else{
               return  0; 
        } 
     }
}
  • 上面匿名函数中的两行代码(注意点),访问了外部函数中的变量propertyName,即使这个内部函数被返回了,且在其他地方被调用了,但仍然可以访问变量propertyName
  • 之所以能访问,是因为内部函数的作用域链中包含了createComparisonFunction()的作用域,往下看。
var compare = createComparisonFunction("name");
var result = compare({name:"yujia"},{name:"yujiajia"});
compare = null; //解除对匿名函数的引用,以便释放内存
  • createComparisonFunction()被调用之后,它的作用域链初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。这样内部的匿名函数可以访问createComparisonFunction()定义的全部变量。
  • createComparisonFunction()执行完毕(返回匿名函数)后,它的活动对象不会被销毁(活动对象依然留在内存中),因为匿名函数的作用域链仍然在引用createComparisonFunction()的活动对象

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,请谨慎使用。

\color{#ea4335}{二、闭包与变量}\

作用域链的机制引出了一个值得注意的副作用,就是闭包只能取得包含函数中任何变量的最后一个值。

function createFunction(){ 
   var result = new Array();
  for(var i=0;i<10;i++){
      result[i] = function(){
       return i 
    } 
  }
  return result   
}
createFunction()[1]() //10
createFunction()[2]() //10
createFunction()[3]() //10

上面的函数组成的数组看上去每个result数组中的函数都会返回其对应的下标记,但是都返回了10。
原因是result中的函数(闭包)保存的是createFunction()函数的活动对象,所以他们引用的都是同一个变量i,当createFunction()返回数组后,变量i的值是10.

这样能强制让闭包的行为符合预期,或者将var变成let

function createFunction(){ 
   var result = new Array();
  for(var i=0;i<10;i++){
      result[i] = function(){
       return function(name){
          return name  
         } 
       }(i) 
  }
  return result   
}

\color{#ea4335}{二、闭包与}\this

在闭包中this对象也可能会导致一些问题

var name = "the window";
var object = {
   name:"My Object",
   getNameFunc:function(){
    return function(){
         console.log(this.name)
       }
   }
}
object.getNameFunc()() //  "the window"
  • 函数在被调用的时候,会自动取得两个特殊变量thisarguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能访问到外部函数中的这两个变量。
  • 要知道,上面也只是在getNameFunc()返回了一个匿名函数,而调用这个匿名函数的作用域环境是window

不过,我们可以把外部作作用域中的this对象保存在一个闭包能访问到的变量里:

var name = "the window";
var object = {
   name:"My Object",
   getNameFunc:function(){ 
      var that = this; 
    return function(){
         console.log(that.name)
       }
   }
}
object.getNameFunc()() //  "My Object"
上一篇 下一篇

猜你喜欢

热点阅读