二、闭包

\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"
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言:swift是一门很优雅,很简洁,功能很强大的语言,同时也是一门很复杂的语言。进门比较简单,看完苹果官方的文档...
    一剑孤城阅读 6,124评论 0 10
  •   函数表达式是 JavaScript 中的一个既强大有容易令人困惑的特性。定义函数的的方式有两种: 函数声明; ...
    霜天晓阅读 831评论 0 1
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,149评论 0 21
  • 作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包保存的是整个变...
    BertFu阅读 268评论 0 0
  • 提升(var) 我们都认为JavaScript代码执行的时候是由上到下一行一行执行的。但实际上这并不完全正确,有一...
    hhooke阅读 1,899评论 0 1