JavaScript中的私有静态函数

13

我如何创建一个无法从外部调用的函数?

var obj = {
    function1: function(){
        alert("function1");
    },
    function2: function(){
        alert("function2...");
        obj.function1();
    }
};
// so how to make this function unaccessible 
obj.function1();
// and you could only call this function
obj.function2();

1
你想要静态函数还是静态方法?你是否需要它是静态的?(示例没有明确说明) - gblazex
1
静态方法和函数有什么区别?:S (顺便说一下,抱歉同时使用了这两个词) - user
8个回答

27

您可能想考虑使用Yahoo模块模式。这是一种单例模式,方法并不真正是静态的,但它可能是您正在寻找的:

var obj = (function () {

   //"private" variables:
   var myPrivateVar = "I can be accessed only from within obj.";

   //"private" method:
   var myPrivateMethod = function () {
      console.log("I can be accessed only from within obj");
   };

   return {
      myPublicVar: "I'm accessible as obj.myPublicVar",

      myPublicMethod: function () {
         console.log("I'm accessible as obj.myPublicMethod");

         //Within obj, I can access "private" vars and methods:
         console.log(myPrivateVar);
         console.log(myPrivateMethod());
      }
   };
})();

你需要在定义 myPrivateVarmyPrivateMethod 的位置定义私有成员,而在定义 myPublicVarmyPublicMethod 的位置定义公共成员。
你可以通过以下方式简单地访问公共方法和属性:
obj.myPublicMethod();    // Works
obj.myPublicVar;         // Works
obj.myPrivateMethod();   // Doesn't work - private
obj.myPrivateVar;        // Doesn't work - private

4
我的私有方法不是一个"静态"函数。你错过了这个标题。 - gblazex
1
我不相信雅虎对模块模式有任何权利 ;) - Crescent Fresh
@Crescent:我也不知道,但似乎每个人都这样称呼它……也许我应该说:“模块模式,又称雅虎模块模式或YUI模块模式” :) - Daniel Vassallo
3
我相信这种模式起源于Yahoo!的Douglas Crockford,并通过YUI团队的Eric Miraglia的一篇文章得到了普及:http://www.yuiblog.com/blog/2007/06/12/module-pattern/ - NickFitz

8
简单的回答是,你不能同时做到这两个。你可以创建“private”方法或“static”方法,但是你不能像其他语言中那样创建私有静态函数。
模拟私有性的方法是闭包:
function f() {

  function inner(){}

  return {
    publicFn:  function() {},
    publicFn2: function() {}
  }
}

由于闭包的原因,每次调用 f 时都会创建一个 inner 函数,公共函数可以访问这个 inner 函数,但对于外部世界来说,inner 将被隐藏。

创建对象的静态方法很简单:

function f() {}

f.staticVar = 5;
f.staticFn = function() {};
// or
f.prototype.staticFn = function() {};

这里函数对象f仅有一个staticFn,可以访问静态变量,但无法访问实例。请注意,使用prototype的版本将被继承,而第一个版本则不会。因此,您可以创建一个不访问任何实例内容的私有方法,或者创建一个静态方法,但不尝试从外部访问它。

我猜问题是JavaScript是否有静态方法。f.prototype.staticFn实际上只是原型对象的公共实例成员。它之所以是静态的,是因为作为另一个对象实例的成员,它无法访问此实例的私有成员。您也可以使用私有方法来实现这一点 - 只需给原型实例一个私有方法 - 只是这并没有什么帮助,因为子实例无法访问该方法。因此,更简短的答案是JavaScript中没有静态方法。 - Matthew

4
您可以使用闭包,大致如下...
var construct = function() {

   var obj = {};

   var method1 = function() {
      alert("method1");
   }

   obj.method2 = function() {
         alert("method2...");
         method1();
   }

   return obj;
}

obj = construct();

然后:

obj.method2 是可以访问的,但是 obj.method1 并不存在于公共使用中。它只能通过类的成员函数访问。


1
这是正确的做法。
var MyClass = new(function() {
    var privateStaticVariable = '';

    function privateStaticMethod() {

    }

    function construct() {
        var self = this;
        this.publicMethod = function() {};

        function privateMethod() {
            //maybe lest use our private static method
            privateStaticMethod();
        }
    }
    construct.publicStaticVariable = '';
    construct.publicStaticMethod = function() {};
    return construct;
})();

Now lets use it:

    var myClass = new MyClass();.....
MyClass.publicStaticMethod();
MyClass.publicStaticVariable = 'sfdsdf';
myClass.publicMethod();

.....


1
你可以这样做:
var obj = new function() {
  var method1 = function() { // private }
  this.method2 = function() { // public } 
}

obj.method1(); // not possible
obj.method2(); // possible

请注意我还使用了一个匿名构造函数。这有点类似于单例模式。

1
也许你想要一个只包含公共方法的代理对象,例如:
var obj = (function() {
  var obj = {
    method1: function(){
      alert("method1");
    },
    method2: function(){
      alert("method2...");
      obj.method1();
    }
  }
  return {
    method2: function() { return obj.method2.apply(obj, arguments) }
  }
})()

// you could only call this function
obj.method2();
// this function inaccessible 
obj.method1();

我不明白在 JavaScript 中使用私有方法的意义所在。如果你不希望别人调用一个方法,那就不要把它公开出来。私有方法也会让调试变得更困难。


1

使用 class。尽管有些功能仍未发布,如 它处于第 3 阶段

const instance = new (class Alpha {
 static #private_static_method() {
  console.info("I am private and static.");
 }
 static public_static_method() {
  Alpha.#private_static_method();
  console.info("I am public and static.");
 }
 #private_nonstatic_method() {
  console.info("I am private and non-static.");
 }
 public_nonstatic_method() {
  this.#private_nonstatic_method();
  console.info("I am public and non-static.");
 }
});

instance.constructor.public_static_method();
// instance.constructor.#private_static_method(); // impossible
instance.public_nonstatic_method();
// instance.#private_nonstatic_method(); // impossible


1
这似乎在所有浏览器中都已经发布了?https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields#browser_compatibility - gman

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接