闭包及其作用

时间:2021-01-18 22:44:40

形成

解释1:当在函数内部创建其他函数时,就创建了闭包,闭包就是能读取函数内部变量的函数
解释2:当函数可以记住并访问所在的作用域,(即使函数是在当前作用域之外执行的,这时就形成了闭包)

闭包的作用域链:

  1. 自己的作用域
  2. 外部函数的作用域
  3. 全局作用域
通常函数在执行结束后其作用域和变量都会被销毁,但函数返回闭包时,函数的作用域会一直保存到闭包消失。

作用

1. 模仿块级作用域

创建并立即执行一个函数,函数中的变量会立即被销毁,除非将其赋值给了全局作用域中的变量。

2. 在对象中创建私有变量

用闭包实现公有方法,用其访问作用域中的私有变量

var fun = (function () {
var a = 1;
function geta() {
return a;
}
Outer = function () {}
Outer.prototype.publicMethod = function () {
a++;
return geta();
}
})();
var o = new Outer();

o.publicMethod();返回2

使用闭包的注意点

1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

实例

实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
输入例子:
var arr = [1, 2, 3]; var square = function (x) { return x * x; }; var funcs = makeClosures(arr, square); funcs1;

输出例子: 4

直接匿名函数

function makeClosures(arr, fn) {
var funcs = [];
for(var i=0; i
(function(v){
funcs[v] = function(){
return fn.call(null,arr[v]);
}
})(i);
}
return funcs;
}

forEach()

function makeClosures(arr, fn) {
var result = new Array();
arr.forEach(function(curr){
result.push(function(){return fn(curr)});
})
return result;
}

使用ES5的bind()方法

function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i
result[i] = fn.bind(null,arr[i]);
}
return result;
}

参考《JavaScript高级程序设计》的典型方法

function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i
result[i] = function(num){
return function(){
return fn(num);
}
}(arr[i]);
}
return result;
}

思考题

 var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
var a = object.getNameFunc;
a()();//这里的调用者一直是window,因此输出"The Window";
object.getNameFunc()();//这里object.getNameFunc()时调用者是object,但是将object.getNameFunc()作为一个整体,他的调用者是window,是window来调用object.getNameFunc()(),此时调用者是window,因为输出"The Window";
 var name = "The Window";
  var object1 = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  object1.getNameFunc()();//这里类似上面object.getNameFunc()时调用者是object的,但是在object1.getNameFunc()的返回函数中,将this赋值给that,因此object1.getNameFunc()()中,this仍然是object,所以输出"My Object",
var e = object1.getNameFunc;
e()();//这里this一直是window,因此不管如何赋值,都输出"The Window"

下面是this的其他

var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return this.name;
}
};
object.getNameFunc()
//"My Object"
(object.getNameFunc)()
//"My Object"
(object.getNameFunc = object.getNameFunc)()
//"The Window"
//最后一个object.getNameFunc的值是函数本身。function (){return this.name;}