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

Javascript 这是做私人活动的好方法吗?,javascript,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(ins

只是在用咖啡脚本打字时看到了一些有趣的代码。我得到了以下代码

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中的模块模式以及为什么这是一件坏事(需要更多的内存,更长的时间来创建…),但当然好处是拥有真正私有的函数/变量。上面的代码不是创建私有函数的好方法吗(这对变量不起作用,除非您需要静态私有变量),因为函数在闭包中只创建一次

模块模式的优点之一也是函数的执行速度,因为代码不必查找原型链。从理论上讲,这会带来同样的速度提升吗?

强调我的观点,因为很明显,问题不仅仅是标题:

  • 是的,模块模式是创建私有(呃,本地)数据(函数或任何东西)和导出某种接口的一种很好且常用的方法。因为函数是创建变量作用域的唯一方法,所以它是创建私有函数的唯一方法

  • 由于函数将由从
    Mamal
    创建的所有对象共享,因此它们对于函数继承模式没有用处(对函数继承的引用已从问题中删除)

  • 与原型链中的查找相比,性能没有任何改进,因为原型链无论如何都需要遍历才能到达您的私有函数


在更新后的帖子中回答具体问题:

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

当然可以,但那是因为在另一个函数中嵌套一个函数是确定函数范围的唯一方法

“现在我已经读了很多关于javascript中的模块模式以及为什么这是一件坏事…”

对于一次性使用的模块,我看不出任何问题。此外,模块函数退出后不再需要的变量引用的任何数据都可以进行垃圾收集。如果它们是全球性的,就不会出现这种情况,除非你取消它们

“…当然,好处是拥有真正私有的函数/变量…”

是的,尽管有些人会反对使用“私人”一词。也许“本地”是个更好的词

“…这不适用于变量,除非您需要静态私有变量…”

是的,不过有些人可能会反对使用“静态”一词

“上面的代码不是创建私有函数的好方法吗……因为函数在闭包中只创建一次?”

是的,同样,嵌套函数是使它们成为“私有”或“本地”的唯一方法

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

“模块模式的优点之一也是函数的执行速度,因为代码不必查找原型链。这在理论上会带来相同的速度改进吗?”

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

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

下面是一个例子:

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
函数和包装函数调用时,您已经消除了原型链,并且仍然在重用
\uu priv\u func

唯一剩下的原型是
simple\u 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();

“上面的代码不是创建私有函数的好方法吗(这对变量不起作用,除非您需要静态私有变量),因为函数在闭包中只创建一次?”

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

“函数继承的好处之一也是函数的执行速度,因为代码不必查找原型链。这在理论上会带来相同的速度改进吗?”

在您的代码中,函数是通过原型链中的函数调用的,因此它具有相同的开销,加上在变量范围中查找局部函数并调用该函数的开销

所以两次查找和两次函数调用,而不是一次查找和一次调用

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

我唯一要改变的不是将实例传递到私有方法,而是使用
.call(this)
。“函数继承的好处之一是