JavaScript私有方法

要使用公共方法创建JavaScript类,我需要执行以下操作:

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something here
}

Restaurant.prototype.use_restroom = function(){
   // something here
}

这样,我班的用户可以:

var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();

如何创建一个私有方法,该私有方法可以由buy_fooduse_restroom方法调用,但不能由该类的用户外部调用

换句话说,我希望我的方法实现能够做到:

Restaurant.prototype.use_restroom = function() {
   this.private_stuff();
}

但这不起作用:

var r = new Restaurant();
r.private_stuff();

如何将其定义private_stuff为私有方法,使两者都适用?

我已经读过Doug Crockford的文章几次,但似乎公共方法不能调用“私有”方法,而外部可以调用“特权”方法。

Tony达蒙Mandy2020/03/12 20:50:57

There are many answers on this question already, but nothing fitted my needs. So i came up with my own solution, I hope it is usefull for someone:

function calledPrivate(){
    var stack = new Error().stack.toString().split("\n");
    function getClass(line){
        var i = line.indexOf(" ");
        var i2 = line.indexOf(".");
        return line.substring(i,i2);
    }
    return getClass(stack[2])==getClass(stack[3]);
}

class Obj{
    privateMethode(){
        if(calledPrivate()){
            console.log("your code goes here");
        }
    }
    publicMethode(){
        this.privateMethode();
    }
}

var obj = new Obj();
obj.publicMethode(); //logs "your code goes here"
obj.privateMethode(); //does nothing

As you can see this system works when using this type of classes in javascript. As far as I figured out none of the methods commented above did.

樱西里猴子2020/03/12 20:50:57
Class({  
    Namespace:ABC,  
    Name:"ClassL2",  
    Bases:[ABC.ClassTop],  
    Private:{  
        m_var:2  
    },  
    Protected:{  
        proval:2,  
        fight:Property(function(){  
            this.m_var--;  
            console.log("ClassL2::fight (m_var)" +this.m_var);  
        },[Property.Type.Virtual])  
    },  
    Public:{  
        Fight:function(){  
            console.log("ClassL2::Fight (m_var)"+this.m_var);  
            this.fight();  
        }  
    }  
});  

https://github.com/nooning/JSClass

神乐古一2020/03/12 20:50:57

You have to put a closure around your actual constructor-function, where you can define your private methods. To change data of the instances through these private methods, you have to give them "this" with them, either as an function argument or by calling this function with .apply(this) :

var Restaurant = (function(){
    var private_buy_food = function(that){
        that.data.soldFood = true;
    }
    var private_take_a_shit = function(){
        this.data.isdirty = true;   
    }
    // New Closure
    function restaurant()
    {
        this.data = {
            isdirty : false,
            soldFood: false,
        };
    }

    restaurant.prototype.buy_food = function()
    {
       private_buy_food(this);
    }
    restaurant.prototype.use_restroom = function()
    {
       private_take_a_shit.call(this);
    }
    return restaurant;
})()

// TEST:

var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);
Tony西门古一2020/03/12 20:50:57

私有函数无法使用模块模式访问公共变量

Itachi小卤蛋凯2020/03/12 20:50:57
var TestClass = function( ) {

    var privateProperty = 42;

    function privateMethod( ) {
        alert( "privateMethod, " + privateProperty );
    }

    this.public = {
        constructor: TestClass,

        publicProperty: 88,
        publicMethod: function( ) {
            alert( "publicMethod" );
            privateMethod( );
        }
    };
};
TestClass.prototype = new TestClass( ).public;


var myTestClass = new TestClass( );

alert( myTestClass.publicProperty );
myTestClass.publicMethod( );

alert( myTestClass.privateMethod || "no privateMethod" );

与georgebrock相似,但略微冗长(IMHO)这样操作有任何问题吗?(我没在任何地方看到它)

编辑:我意识到这是没有用的,因为每个独立的实例都有自己的公用方法副本,从而破坏了原型的使用。

TomSam2020/03/12 20:50:57

那这个呢?

var Restaurant = (function() {

 var _id = 0;
 var privateVars = [];

 function Restaurant(name) {
     this.id = ++_id;
     this.name = name;
     privateVars[this.id] = {
         cooked: []
     };
 }

 Restaurant.prototype.cook = function (food) {
     privateVars[this.id].cooked.push(food);
 }

 return Restaurant;

})();

在立即函数的范围之外,无法进行私有变量查找。没有功能重复,节省了内存。

缺点是私有变量的查找笨拙privateVars[this.id].cooked,很难键入。还有一个额外的“ id”变量。

番长樱梅2020/03/12 20:50:57

如果要使用公共功能访问私有功能的所有公共和私有功能,请为对象布局代码,如下所示:

function MyObject(arg1, arg2, ...) {
  //constructor code using constructor arguments...
  //create/access public variables as 
  // this.var1 = foo;

  //private variables

  var v1;
  var v2;

  //private functions
  function privateOne() {
  }

  function privateTwon() {
  }

  //public functions

  MyObject.prototype.publicOne = function () {
  };

  MyObject.prototype.publicTwo = function () {
  };
}
十三Tony伽罗2020/03/12 20:50:57

在大多数情况下,模块模式是正确的。但是,如果您有数千个实例,则类可以节省内存。如果需要节省内存,并且您的对象包含少量私有数据,但是具有很多公共函数,那么您将希望所有公共函数都驻留在.prototype中以节省内存。

这是我想出的:

var MyClass = (function () {
    var secret = {}; // You can only getPriv() if you know this
    function MyClass() {
        var that = this, priv = {
            foo: 0 // ... and other private values
        };
        that.getPriv = function (proof) {
            return (proof === secret) && priv;
        };
    }
    MyClass.prototype.inc = function () {
        var priv = this.getPriv(secret);
        priv.foo += 1;
        return priv.foo;
    };
    return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2

该对象priv包含私有属性。可以通过public函数访问它getPriv(),但是false除非您将它传递给secret否则该函数将返回,并且仅在主闭包内部才知道。

Green达蒙Harry2020/03/12 20:50:57

模块模式的神化:揭示模块模式

精巧的扩展,非常强大的模式。

理查德西门Near2020/03/12 20:50:57

所有这些关闭将使您付出代价。确保测试速​​度的影响,尤其是在IE中。您会发现使用命名约定会更好。仍然有很多公司网络用户被迫使用IE6 ...

Stafan西门逆天2020/03/12 20:50:57

在这些情况下,当您拥有公共API并想要私有和公共方法/属性时,我总是使用模块模式。这种模式在YUI库中很流行,详细信息可以在这里找到:

http://yuiblog.com/blog/2007/06/12/module-pattern/

这确实很简单,其他开发人员也很容易理解。举个简单的例子:

var MYLIB = function() {  
    var aPrivateProperty = true;
    var aPrivateMethod = function() {
        // some code here...
    };
    return {
        aPublicMethod : function() {
            aPrivateMethod(); // okay
            // some code here...
        },
        aPublicProperty : true
    };  
}();

MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay
小小猪猪2020/03/12 20:50:57

您可以像下面这样模拟私有方法:

function Restaurant() {
}

Restaurant.prototype = (function() {
    var private_stuff = function() {
        // Private code here
    };

    return {

        constructor:Restaurant,

        use_restroom:function() {
            private_stuff();
        }

    };
})();

var r = new Restaurant();

// This will work:
r.use_restroom();

// This will cause an error:
r.private_stuff();

有关此技术的更多信息,请访问:http : //webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html

古一番长小小2020/03/12 20:50:56

您可以做到,但缺点是它不能成为原型的一部分:

function Restaurant() {
    var myPrivateVar;

    var private_stuff = function() {  // Only visible inside Restaurant()
        myPrivateVar = "I can set this here!";
    }

    this.use_restroom = function() {  // use_restroom is visible to all
        private_stuff();
    }

    this.buy_food = function() {   // buy_food is visible to all
        private_stuff();
    }
}