Javascript闭包 - 这些之间的区别是什么

时间:2012-02-09 12:57:44

标签: javascript closures

修改

回复的数量说“你可以做私事!”下面,我将把它添加到顶部:

我知道你可以在闭包中模拟私有变量。那不是我要问的。我问,鉴于以下两个例子,我从封闭中“导出”了一切,这两个例子之间的根本区别是什么。

鉴于这两种创建对象/方法的方法:

var test = {}

test = (function(){
    var a_method = function(print_me){
        return "hello "+print_me;
    }

    return {print_me: a_method};
})();

test.print_me2 = function(print_me2){
   return "hello "+print_me2;
}

test.print_me('world');
>>> returns "hello world"

test.print_me2('world');
>>> returns "hello world"

据我所知,第一种方法允许私有变量(作为一个python开发人员,我并不真正关心使用),但两者似乎对我来说都是等同的,只有第一个看起来“更酷”(如所有大型javascript人员似乎都是这样做的,而第二种方式看起来非常过时。

那么,有什么区别?

我在这里查看了关闭问题 - 大多数都围绕着你使用它们的原因或原因;我理解他们的实用性,我只是想知道为什么你会在第二天做第一个以及它有什么好处。

我更喜欢有关猜想的确凿证据 - 不是在寻找“这就是酷孩子们这样做的原因”或“我听说当你使用封闭时mozilla会更好地记忆使用”,而是寻找定性证据一个人比另一个人“更好”。

3 个答案:

答案 0 :(得分:3)

方法之间的区别在于创建闭包的匿名函数包装器,但第一个方法替换整个对象,而第二个方法只是在现有方法中设置属性。

向对象添加方法有多种方法。您可以在创建对象时将它们放在那里:

var test = {
  print_me: function(text) { return "hello " + text; }
};

您可以将方法作为属性添加到现有对象:

var test = {};
test.print_me = function(text) { return "hello " + text; };

您可以创建构造函数,并将方法添加到其原型中:

function Test() {}
Test.prototype.print_me = function(text) { return "hello " + text; };
var test = new Test();

由于Javascript具有基于原型的对象模型,最后一个是如何创建方法。其他方式是可行的,因为对象属性可以具有函数作为值。


您可以在任何需要局部变量的代码周围使用函数包装器,因此您可以使用第二种设置属性的方法来实现:

test.print_me2 = (function(){

  var method = function(print_me2) {
    return "hello "+print_me2;
  }

  return method;
})();

答案 1 :(得分:2)

在第一个示例中,闭包用于将局部变量保留在全局范围之外。

var thisIsGlobal = 2;
var test = (function () {
  var thisIsLocal = 3;
  return function () {
    return thisIsLocal;
  };
}());

你得到的是一个函数test,它在被调用时返回局部变量thisIsLocal的值。无法更改变量的值。您可以将其视为私有变量。

答案 2 :(得分:0)

您提供的第一种方法(立即执行的匿名函数)使您的程序远离全局范围。在该私有范围内,您可以决定要将哪些属性公开为API:

(function(win){
  var a, b, c = 1;  

  function init(){ 
    return aa(b);
  }

  function exit(){
    if(cc()){
      return a;
    }
  }

  function aa(){
  }

  function bb(){
  }

  function cc(){
  }

  win.myProgram = {init: init,
                   exit: exit };
})(window);


// We now have access to your API from within the global namespace:    
myProgram.init();    
//etc