JavaScript private methods
要用公共方法生成一个javascript类,我将执行如下操作:
1 2 3 4 5 6 7 8 9 | function Restaurant() {} Restaurant.prototype.buy_food = function(){ // something here } Restaurant.prototype.use_restroom = function(){ // something here } |
这样我班的用户就可以:
1 2 3 | var restaurant = new Restaurant(); restaurant.buy_food(); restaurant.use_restroom(); |
如何创建一个私有方法,该方法可以由
换句话说,我希望我的方法实现能够做到:
1 2 3 | Restaurant.prototype.use_restroom = function() { this.private_stuff(); } |
但这不应该奏效:
1 2 | var r = new Restaurant(); r.private_stuff(); |
我如何将
我读过道格·克罗克福德的文章几次,但它似乎不像"私有"方法可以被公共方法调用,"特权"方法可以从外部调用。
你可以这样做,但缺点是它不能成为原型的一部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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(); } } |
您可以这样模拟私有方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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
使用自调用函数和调用
JavaScript使用原型,并且没有类(或相关的方法)像面向对象的语言。一个javascript开发者需要在javascript中思考。
维基百科引言:
Unlike many object-oriented languages, there is no distinction between
a function definition and a method definition. Rather, the distinction
occurs during function calling; when a function is called as a method
of an object, the function's local this keyword is bound to that
object for that invocation.
使用自调用函数和调用函数调用私有"方法"的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var MyObject = (function () { // Constructor function MyObject (foo) { this._foo = foo; } function privateFun (prefix) { return prefix + this._foo; } MyObject.prototype.publicFun = function () { return privateFun.call(this, '>>'); } return MyObject; })(); var myObject = new MyObject('bar'); myObject.publicFun(); // Returns '>>bar' myObject.privateFun('>>'); // ReferenceError: private is not defined |
调用函数允许我们用适当的上下文(
如果您使用node.js,则不需要iife,因为您可以利用模块加载系统:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function MyObject (foo) { this._foo = foo; } function privateFun (prefix) { return prefix + this._foo; } MyObject.prototype.publicFun = function () { return privateFun.call(this, '>>'); } exports.MyObject = MyObject; |
加载文件:
1 2 3 4 5 | var MyObject = require('./MyObject').MyObject; var myObject = new MyObject('bar'); myObject.publicFun(); // Returns '>>bar' myObject.privateFun('>>'); // ReferenceError: private is not defined |
(实验)使用绑定运算符的ES7
绑定操作符
1 2 3 4 5 6 7 8 9 10 11 12 13 | export default class MyObject { constructor (foo) { this._foo = foo; } publicFun () { return this::privateFun('>>'); } } function privateFun (prefix) { return prefix + this._foo; } |
加载文件:
1 2 3 4 5 | import MyObject from './MyObject'; let myObject = new MyObject('bar'); myObject.publicFun(); // Returns '>>bar' myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function |
在这些情况下,当您有一个公共API,并且您想要私有和公共方法/属性时,我总是使用模块模式。此图案在Yui图书馆内非常流行,详情可在此处找到:
http://yuiblog.com/blog/2007/06/12/module-pattern/
它非常简单,其他开发人员也很容易理解。举个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
这是我创建的用来理解Douglas Crockford在其网站上用javascript的私有成员所建议的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | function Employee(id, name) { //Constructor //Public member variables this.id = id; this.name = name; //Private member variables var fName; var lName; var that = this; //By convention, we create a private variable 'that'. This is used to //make the object available to the private methods. //Private function function setFName(pfname) { fName = pfname; alert('setFName called'); } //Privileged function this.setLName = function (plName, pfname) { lName = plName; //Has access to private variables setFName(pfname); //Has access to private function alert('setLName called ' + this.id); //Has access to member variables } //Another privileged member has access to both member variables and private variables //Note access of this.dataOfBirth created by public member setDateOfBirth this.toString = function () { return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth; } } //Public function has access to member variable and can create on too but does not have access to private variable Employee.prototype.setDateOfBirth = function (dob) { alert('setDateOfBirth called ' + this.id); this.dataOfBirth = dob; //Creates new public member note this is accessed by toString //alert(fName); //Does not have access to private member } $(document).ready() { var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor employee.setLName('Bhaskar', 'Ram'); //Call privileged function employee.setDateOfBirth('1/1/2000'); //Call public function employee.id = 9; //Set up member value //employee.setFName('Ram'); //can not call Private Privileged method alert(employee.toString()); //See the changed object } |
我想起来了:编辑:事实上,有人链接到了一个相同的解决方案。啊!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var Car = function() { } Car.prototype = (function() { var hotWire = function() { // Private code *with* access to public properties through 'this' alert( this.drive() ); // Alerts 'Vroom!' } return { steal: function() { hotWire.call( this ); // Call a private method }, drive: function() { return 'Vroom!'; } }; })(); var getAwayVechile = new Car(); hotWire(); // Not allowed getAwayVechile.hotWire(); // Not allowed getAwayVechile.steal(); // Alerts 'Vroom!' |
我认为这样的问题一次又一次出现是因为对闭包缺乏理解。在JS中,C损耗是最重要的。每个JS程序员都必须感受到它的本质。
1。首先,我们需要做单独的范围(闭包)。
1 2 3 | function () { } |
2。在这方面,我们可以做任何我们想做的。没有人会知道的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function () { var name, secretSkills = { pizza: function () { return new Pizza() }, sushi: function () { return new Sushi() } } function Restaurant(_name) { name = _name } Restaurant.prototype.getFood = function (name) { return name in secretSkills ? secretSkills[name]() : null } } |
三。为了让全世界都知道我们的餐厅课程,我们必须把它从关闭处退回。
1 2 3 4 | var Restaurant = (function () { // Restaurant definition return Restaurant })() |
4。最后,我们有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var Restaurant = (function () { var name, secretSkills = { pizza: function () { return new Pizza() }, sushi: function () { return new Sushi() } } function Restaurant(_name) { name = _name } Restaurant.prototype.getFood = function (name) { return name in secretSkills ? secretSkills[name]() : null } return Restaurant })() |
5。此外,这种方法还具有继承和模板化的潜力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Abstract class function AbstractRestaurant(skills) { var name function Restaurant(_name) { name = _name } Restaurant.prototype.getFood = function (name) { return skills && name in skills ? skills[name]() : null } return Restaurant } // Concrete classes SushiRestaurant = AbstractRestaurant({ sushi: function() { return new Sushi() } }) PizzaRestaurant = AbstractRestaurant({ pizza: function() { return new Pizza() } }) var r1 = new SushiRestaurant('Yo! Sushi'), r2 = new PizzaRestaurant('Dominos Pizza') r1.getFood('sushi') r2.getFood('pizza') |
我希望这能帮助人们更好地理解这个问题
就我个人而言,我更喜欢以下在javascript中创建类的模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var myClass = (function() { // Private class properties go here var blueprint = function() { // Private instance properties go here ... }; blueprint.prototype = { // Public class properties go here ... }; return { // Public class properties go here create : function() { return new blueprint(); } ... }; })(); |
如您所见,它允许您定义类属性和实例属性,每个属性都可以是公共的和私有的。
演示1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | var Restaurant = function() { var totalfoodcount = 0; // Private class property var totalrestroomcount = 0; // Private class property var Restaurant = function(name){ var foodcount = 0; // Private instance property var restroomcount = 0; // Private instance property this.name = name this.incrementFoodCount = function() { foodcount++; totalfoodcount++; this.printStatus(); }; this.incrementRestroomCount = function() { restroomcount++; totalrestroomcount++; this.printStatus(); }; this.getRestroomCount = function() { return restroomcount; }, this.getFoodCount = function() { return foodcount; } }; Restaurant.prototype = { name : '', buy_food : function(){ this.incrementFoodCount(); }, use_restroom : function(){ this.incrementRestroomCount(); }, getTotalRestroomCount : function() { return totalrestroomcount; }, getTotalFoodCount : function() { return totalfoodcount; }, printStatus : function() { document.body.innerHTML += 'Buying food at '+this.name+'' + ' <ul> ' + ' <li> Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + ' </li> ' + ' <li> Food count at ' + this.name + ' : ' + this.getFoodCount() + ' </li> ' + ' <li> Total restroom count : '+ this.getTotalRestroomCount() + ' </li> ' + ' <li> Total food count : '+ this.getTotalFoodCount() + ' </li> ' + ' </ul> '; } }; return { // Singleton public properties create : function(name) { return new Restaurant(name); }, printStatus : function() { document.body.innerHTML += '<hr />' + 'Overview' + ' <ul> ' + ' <li> Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + ' </li> ' + ' <li> Total food count : '+ Restaurant.prototype.getTotalFoodCount() + ' </li> ' + ' </ul> ' + '<hr />'; } }; }(); var Wendys = Restaurant.create("Wendy's"); var McDonalds = Restaurant.create("McDonald's"); var KFC = Restaurant.create("KFC"); var BurgerKing = Restaurant.create("Burger King"); Restaurant.printStatus(); Wendys.buy_food(); Wendys.use_restroom(); KFC.use_restroom(); KFC.use_restroom(); Wendys.use_restroom(); McDonalds.buy_food(); BurgerKing.buy_food(); Restaurant.printStatus(); BurgerKing.buy_food(); Wendys.use_restroom(); McDonalds.buy_food(); KFC.buy_food(); Wendys.buy_food(); BurgerKing.buy_food(); McDonalds.buy_food(); Restaurant.printStatus(); |
另见这把小提琴。
所有这些关闭都会让你付出代价。一定要测试速度影响,尤其是在IE中。你会发现你最好使用命名约定。仍然有很多企业网络用户被迫使用IE6…
采取任何符合克罗克福德私人或私人模式的解决方案。例如:
1 2 3 4 5 6 7 8 9 10 | function Foo(x) { var y = 5; var bar = function() { return y * x; }; this.public = function(z) { return bar() + x * z; }; } |
在任何情况下,如果攻击者在JS上下文上没有"执行"权限,他就无法访问任何"公共"或"私有"字段或方法。如果攻击者具有该访问权限,他可以执行此一行程序:
1 2 3 | eval("Foo =" + Foo.toString().replace( /{/,"{ this.eval = function(code) { return eval(code); };" )); |
请注意,上述代码是所有构造函数类型隐私的通用代码。这里的一些解决方案会失败,但很明显,几乎所有基于闭包的解决方案都可以用不同的
执行此操作后,使用
1 2 3 4 | f = new Foo(99); f.eval("x"); f.eval("y"); f.eval("x = 8"); |
我能看到的唯一问题是,在只有一个实例并且是在加载时创建的情况下,它将不起作用。但是,没有理由实际定义原型,在这种情况下,攻击者可以简单地重新创建对象而不是构造函数,只要他有传递相同参数的方法(例如,它们是常量或根据可用值计算)。
在我看来,这几乎使克罗克福德的解决方案无济于事。由于"隐私"很容易被打破,他的解决方案的缺点(可读性和可维护性降低、性能降低、内存增加)使得基于"不隐私"原型的方法成为更好的选择。
我通常使用前导下划线来标记
因此,我不同意克罗克福德,除了他的第一句话。
那么,如何在JS中获得真正的隐私呢?在服务器端放置所有需要私有化的内容,并使用JS进行Ajax调用。
模块模式的神化:揭示模块模式
对一个非常健壮的模式的一个简单的小扩展。
如果您希望具有公共函数访问私有函数功能的公共和私有函数的全部范围,请使用如下对象的布局代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 () { }; } |
这个怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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; })(); |
私有变量查找不可能超出立即函数的范围。没有重复的功能,节省了内存。
缺点是查找私有变量是笨拙的
模块模式在大多数情况下都是正确的。但是,如果您有数千个实例,那么类会保存内存。如果保存内存是一个问题,并且您的对象包含少量私有数据,但有很多公共函数,那么您将希望所有公共函数都位于.prototype中以保存内存。
这就是我想到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 |
对象
以下是迄今为止我最喜欢的关于私有/公共方法/成员和JavaScript中的实例化的内容:
这是一篇文章:http://www.sefol.com/?P=1090
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | var Person = (function () { //Immediately returns an anonymous function which builds our modules return function (name, location) { alert("createPerson called with" + name); var localPrivateVar = name; var localPublicVar ="A public variable"; var localPublicFunction = function () { alert("PUBLIC Func called, private var is :" + localPrivateVar) }; var localPrivateFunction = function () { alert("PRIVATE Func called") }; var setName = function (name) { localPrivateVar = name; } return { publicVar: localPublicVar, location: location, publicFunction: localPublicFunction, setName: setName } } })(); //Request a Person instance - should print"createPerson called with ben" var x = Person("ben","germany"); //Request a Person instance - should print"createPerson called with candide" var y = Person("candide","belgium"); //Prints"ben" x.publicFunction(); //Prints"candide" y.publicFunction(); //Now call a public function which sets the value of a private variable in the x instance x.setName("Ben 2"); //Shouldn't have changed this : prints"candide" y.publicFunction(); //Should have changed this : prints"Ben 2" x.publicFunction(); |
jspiddle:http://jsfiddle.net/northkildonan/kopj3dt3/1/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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" ); |
类似于georebrock,但不太冗长(imho)这样做有什么问题吗?(我哪儿也没见过)
编辑:我意识到这有点无用,因为每个独立的实例化都有自己的公共方法副本,从而破坏了原型的使用。
用匿名函数包装所有代码:那么,所有函数都是私有的,只有附加到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (function(w,nameSpacePrivate){ w.Person=function(name){ this.name=name; return this; }; w.Person.prototype.profilePublic=function(){ return nameSpacePrivate.profile.call(this); }; nameSpacePrivate.profile=function(){ return 'My name is '+this.name; }; })(window,{}); |
使用此:
1 2 | var abdennour=new Person('Abdennour'); abdennour.profilePublic(); |
小提琴
我更喜欢将私有数据存储在关联的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | const data = new WeakMap(); function Foo(value) { data.set(this, {value}); } // public method accessing private value Foo.prototype.accessValue = function() { return data.get(this).value; } // private 'method' accessing private value function accessValue(foo) { return data.get(foo).value; } export {Foo}; |
请参阅此答案,以获得一个干净简单的"类"解决方案,该解决方案具有私有和公共接口,并支持组合。
关于这个问题已经有很多答案了,但没有一个符合我的需要。所以我提出了自己的解决方案,我希望它对某些人有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function calledPrivate(){ var stack = new Error().stack.toString().split(" "); 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 |
正如您所看到的,当在JavaScript中使用此类类时,该系统工作正常。据我所知,上述方法都没有。
这就是我的想法:
需要一类你可以在这里找到的糖代码。还支持受保护的、继承的、虚拟的、静态的东西…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ;( function class_Restaurant( namespace ) { 'use strict'; if( namespace["Restaurant" ] ) return // protect against double inclusions namespace.Restaurant = Restaurant var Static = TidBits.OoJs.setupClass( namespace,"Restaurant" ) // constructor // function Restaurant() { this.toilets = 3 this.Private( private_stuff ) return this.Public( buy_food, use_restroom ) } function private_stuff(){ console.log("There are", this.toilets,"toilets available") } function buy_food (){ return"food" } function use_restroom (){ this.private_stuff() } })( window ) var chinese = new Restaurant console.log( chinese.buy_food() ); // output: food console.log( chinese.use_restroom() ); // output: There are 3 toilets available console.log( chinese.toilets ); // output: undefined console.log( chinese.private_stuff() ); // output: undefined // and throws: TypeError: Object #<Restaurant> has no method 'private_stuff' |
私有函数无法使用模块模式访问公共变量
别那么冗长。它是javascript。使用命名约定。
在ES6课程中工作了多年之后,我最近开始了ES5项目的工作(使用已经非常冗长的RequireJS)。我已经反复讨论过这里提到的所有策略,基本上都归结为使用命名约定:
MY-ToLTIPS.JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | define([ 'tooltip' ], function( tooltip ){ function MyTooltip() { // Later, if needed, we can remove the underscore on some // of these (make public) and allow clients of our class // to set them. this._selector ="#my-tooltip" this._template = 'Hello from inside my tooltip!'; this._initTooltip(); } MyTooltip.prototype = { constructor: MyTooltip, _initTooltip: function () { new tooltip.tooltip(this._selector, { content: this._template, closeOnClick: true, closeButton: true }); } } return { init: function init() { new MyTooltip(); // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation. } // You could instead return a new instantiation, // if later you do more with this class. /* create: function create() { return new MyTooltip(); } */ } }); |
既然每个人都在这里发布自己的代码,我也会这么做…
我喜欢Crockford,因为他在JavaScript中引入了真正的面向对象模式。但他也提出了一个新的误会,"那个"误会。
那他为什么用"那个=这个"?它完全与私有功能无关。它与内部功能有关!
因为根据Crockford的说法,这是车码:
1 2 3 4 5 6 | Function Foo( ) { this.bar = 0; var foobar=function( ) { alert(this.bar); } } |
所以他建议这样做:
1 2 3 4 5 6 7 | Function Foo( ) { this.bar = 0; that = this; var foobar=function( ) { alert(that.bar); } } |
所以,正如我所说的,我很确定克罗克福德是错的,他对这个和这个的解释是错误的(但他的代码肯定是正确的)。或者他只是在愚弄javascript世界,想知道谁在复制他的代码?我不知道……我不是浏览器怪人;D
编辑
啊,这就是为什么:在javascript中,"var that=this";是什么意思?
所以克罗基的解释是错的……但他的代码是对的,所以他仍然是一个伟大的人。:)
一般来说,我将私有对象临时添加到对象中。您必须在方法的"Power构造函数"中公开隐私。如果从原型调用该方法,您将能够覆盖原型方法
在"power constructor"中使公共方法可访问:(ctx是对象上下文)
1ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object现在我有了这个开放的隐私:
1
2
3
4
5
6
7
8GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
return function() {
ctx._ = _;
var res = clss[func].apply(ctx, arguments);
ctx._ = null;
return res;
};
};
您必须在实际的构造函数函数周围放置一个闭包,在那里您可以定义您的私有方法。要通过这些私有方法更改实例的数据,您必须将这些实例作为函数参数或通过使用.apply调用此函数来"this"(this):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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__); |
我创建了一个新的工具,允许您在原型上使用真正的私有方法https://github.com/tremaynechrist/protectjs
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var MyObject = (function () { // Create the object function MyObject() {} // Add methods to the prototype MyObject.prototype = { // This is our public method public: function () { console.log('PUBLIC method has been called'); }, // This is our private method, using (_) _private: function () { console.log('PRIVATE method has been called'); } } return protect(MyObject); })(); // Create an instance of the object var mo = new MyObject(); // Call its methods mo.public(); // Pass mo._private(); // Fail |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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/jclass
我知道有点晚了,但是这个怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13 | var obj = function(){ var pr ="private"; var prt = Object.getPrototypeOf(this); if(!prt.hasOwnProperty("showPrivate")){ prt.showPrivate = function(){ console.log(pr); } } } var i = new obj(); i.showPrivate(); console.log(i.hasOwnProperty("pr")); |