这是私人活动的好方法吗?

时间:2011-12-08 04:18:06

标签: javascript

在咖啡脚本中输入拼写错误时,只看到了一些有趣的代码。我得到了以下代码

var Mamal, mam;

Mamal = (function() {
  var __priv_func;

  function Mamal() {}

  Mamal.prototype.simple_var = 5;

  Mamal.prototype.test = function() {
    return __priv_func(this);
  };

  __priv_func = function(instance) {
    return alert(instance.simple_var);
  };

  return Mamal;

})();

mam = new Mamal();
mam.simple_var = 10;
mam.test();

现在我已经阅读了很多关于javascript中的模块模式以及为什么它是一件坏事(占用更多内存,创建更长时间......)但当然好处是拥有真正的私有函数/变量。上面的代码不是创建私有函数的好方法(这对变量不起作用,除非你想要静态私有变量)因为函数只在闭包中创建一次吗?

模块模式的一个优点还在于函数的执行速度,因为代码不必查找原型链。理论上这会改善速度吗?

2 个答案:

答案 0 :(得分:1)

要突出我正在制作的观点,因为显然问题不仅仅是标题:

  • 是的,模块模式是一种很好的常用方法,可以创建私有(呃,本地)数据(函数或其他),并导出某种接口。由于函数是唯一创建变量范围的方式,因此它是唯一方式来创建私有函数。

  • 因为这些函数将由Mamal创建的所有对象共享,所以它们对功能继承模式无效(对函数继承的引用)已从问题中删除)

  • 原型链中的查找没有性能提升,因为原型链需要遍历才能到达您的私有函数。


要解决更新帖子中的具体问题:

  

"这是一种做私人功能的好方法吗?"

当然,但那是因为将功能嵌套在另一个功能中是唯一的方式来定义功能。

  

"现在我已经在javascript中阅读了很多关于模块模式以及为什么这是一件坏事..."

对于一次性使用模块,我没有看到任何问题。此外,模块函数退出后不再需要的变量引用的任何数据都可以自由进行垃圾回收。如果它们是全局的,除非你使它们无效,否则就不会出现这种情况。

  

" ...当然,好处是拥有真正的私人功能/变量...... "

是的,虽然有些人会使用“#34; private"”这个词。可能"本地"是一个更好的词。

  

" ...除非你想要静态私有变量,否则这对变量不起作用......"

是的,虽然有些人可能会对使用“#34; static"”这个词有所例外。

  

"上述代码不是创建私有函数的好方法......因为函数只在闭包中创建一次?"

是的,嵌套函数是使它们成为私有"的唯一方法。或者说是本地的。

但是,是的,只要函数只需要访问对象的公共属性(任何可以访问对象的代码都可以访问)而不是构造函数的局部变量,那么你应该只创建一次这些函数,无论你是否使用模块模式。

  

"模块模式的一个优点还在于函数的执行速度,因为代码不必查找原型链。理论上这会改善速度吗?"

不,您还没有直接导出您的私有函数,而是调用它们的唯一方法是遍历原型链。

但是如果你放弃了原型链,并在创建的对象上直接添加了属性作为属性,那么你在那里有一些改进。

以下是一个例子:

Mamal = (function() {
  var __priv_func;

  function Mamal() {
    this.test = __priv_func;
  }

  Mamal.prototype.simple_var = 5;

  __priv_func = function() {
    return alert( this.simple_var );
  };

  return Mamal;

})();

现在您已经在查找test函数以及包装函数调用中删除了原型链,并且您仍在重用__priv_func

唯一剩下的原型是simple_var,你也可以将它直接带到对象上,但是当你试图修改它的值时它会发生,所以你也可以这么做把它留在那里。


原始答案:

如果您正在谈论模块模式,您在(通常)IIFE中设置了一堆代码,那么导出可以访问匿名函数中变量的方法,是的,它是一种很好的方法,而且非常普遍。

var MyNamespace = (function () {
    // do a bunch of stuff to set up functionality
    //    without pollution global namespace

    var _exports = {};

    _exports.aFunction = function() { ... };
    _exports.anotherFunction = function() { ... };

    return _exports;
})();

MyNamespace.aFunction();

但是在你的例子中,除了你决定使用上面的模块模式之外,我没有看到并优于典型的构造函数。

它现在的方式,相同的功能可以像这样完成,没有任何更多的全球污染,没有包装功能:

var Mamal, mam;

Mamal = function() {};

Mamal.prototype.test = function() {
    return console.log(this.simple_var);
};

Mamal.prototype.simple_var = 5;

mam = new Mamal();
mam.simple_var = 10;
mam.test();

  

&#34;上面的代码不是创建私有函数的好方法(除非你想要静态私有变量,否则这对变量不起作用),因为函数只在闭包中创建一次?&#34; < / em>的

鉴于上面重写的代码,该函数仍然只创建一次。原型对象在从构造函数创建的对象之间共享,因此它也只创建一次。

  

&#34;功能继承的优点之一也是函数的执行速度,因为代码不必查找原型链。理论上这会改善速度吗?&#34;

在你的代码中,函数是通过原型链中的函数调用的,因此它具有相同的开销,加上在变量作用域中查找本地函数并调用该函数的开销。

因此,两次查找和两次函数调用,而不是一次查找和一次调用。

答案 1 :(得分:0)

var Mamal, mam1, mam2;

Mamal = (function() {
  //private static method
  var __priv_func = function() {
    return 1;
  };

  function Mamal() {
  }

  Mamal.prototype.get = function() {
        return __priv_func();
  };

  Mamal.prototype.set = function(i) {
        __priv_func = function(){
          return i;
        };
  };

  return Mamal;

})();

mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); //output 1
mam2.set(2);
console.log(mam1.get()); //output 2

函数__priv_func不仅是私有的,而且是静态的。如果'静态'无关紧要,我认为这是获得私人功能的好方法。

以下是获取私有但非静态方法的方法。它可能需要更多的记忆,创建时间更长.......

var Mamal, mam1, mam2;

function Mamal() {
  //private attributes
  var __priv_func = function() {
    return 1;
  };

  //privileged methods
  this.get = function() {
      return __priv_func();
  };
  this.set = function(i) {
      __priv_func = function(){
        return i;
      };
  };
}

mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 1
mam2.set(2);
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 2