带有私有/公共方法的Javascript模块模式
我被要求制作一个Javascript模块,作为浏览器事件的计数器,并且不可能修改实际计数的事件(私有方法)带有私有/公共方法的Javascript模块模式,javascript,jquery,Javascript,Jquery,我被要求制作一个Javascript模块,作为浏览器事件的计数器,并且不可能修改实际计数的事件(私有方法) var CountingLogger=(函数(){ var secret={}; var-uid=0; 函数计数记录器(事件){ secret[this.id=uid++]={}; //将私人物品存放在秘密容器中 //而不是“这个”。 secret[this.id].events=events | | 0; } CountingLogger.prototype.log=函数(eventNa
var CountingLogger=(函数(){
var secret={};
var-uid=0;
函数计数记录器(事件){
secret[this.id=uid++]={};
//将私人物品存放在秘密容器中
//而不是“这个”。
secret[this.id].events=events | | 0;
}
CountingLogger.prototype.log=函数(eventName){
警报(机密[this.id].events[eventName]);
if(机密的类型[this.id].events[eventName]=“未定义”){
机密[this.id]。事件[eventName]=0;
}
secret[this.id].events[eventName]++;
var count=secret[this.id]。事件[eventName];
$(“#logContents”).append(“”+eventName+”:“+count+” ”);
};
返回计数记录器;
}());
在main.js中,我定义:
var logger=new CountingLogger()代码>
然后打电话
logger.log('EventName')代码>
并且应该显示为回调计数器“EventName”+计数器,因此EventName:1,SecondEvent:4。。。
但日志中始终显示未定义的“WhateverEvent”。
谁能想出一个办法来解决这个问题?
javascript中的私有方法只能用于特定目的。
不可能阻止某人在javascript中操纵任何方法
用户只需在您的私有方法上放置一个调试点,就可以开始操作您的私有逻辑。javascript中的私有方法应仅用于特定目的。
不可能阻止某人在javascript中操纵任何方法
用户只需在您的私有方法上放置一个调试点,就可以开始操作您的私有逻辑。您不需要您拥有的机密。因为,这是内存泄漏
(注意:当我在下面说“真正私有”时,请记住,如果有人在使用调试器,没有任何东西是真正私有的。下面的“真正私有”只是让任何人都无法编写代码,使用对对象的引用来获取或修改私有数据。)
ES7将拥有真正的私有财产。在此之前,您基本上有三种选择:
真正私有的数据,在调用构造函数时通过闭包保存
通过属性命名约定“请勿插手”属性
非常难以使用的属性,虽然不是私有的,但很难针对这些属性编写代码
真正私有的数据
如果您希望每个实例都有真正的私有信息,标准方法是在构造函数中使用变量,并在构造函数中定义需要该私有数据的方法:
function Foo() {
var secret = Math.floor(Math.random() * 100);
this.iWillTellYouASecret = function() {
console.log("The secret is " + secret);
};
}
Foo.prototype.iDoNotKnowTheSecret = function() {
console.log("I don't know the secret");
};
是的,这意味着会为每个实例创建一个新的iWillTellYouASecret
函数,但当该实例从内存中删除时,它(以及秘密)也会被回收,一个体面的JavaScript引擎可以跨这些函数对象重用函数的代码
“把手拿开”酒店
但大多数情况下,你并不需要真正的私人信息,只需要写着“把手从我身上拿开”的信息。JavaScript中的惯例是以\uuu
开头的属性。是的,这意味着具有实例访问权限的代码可以使用或更改该属性的值,但在大多数具有“真正私有”属性的语言(如Java)中,这实际上也是通过反射实现的
很难使用的属性
如果你想让试图使用你的私人数据的人生活更艰难,你可以使用*(这是在ES6将通过Name
对象实现真正的隐私时写的;从那时起,Name
变成了Symbol
,不再用于隐私):
首先,创建一个Name
psuedo类:
var Name = function() {
var used = {};
function Name() {
var length, str;
do {
length = 5 + Math.floor(Math.random() * 10);
str = "_";
while (length--) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
}
while (used[str]);
used[str] = true;
return new String(str); // Since this is called via `new`, we have to return an object to override the default
}
return Name;
}();
然后将此模式用于私有实例属性:
// Nearly-private properties
var Foo = (function() {
// Create a random string as our private property key
var nifty = new Name();
// Our constructor
function Foo() {
// We can just assign here as normal
this[nifty] = 42;
}
// ***On ES5, make the property non-enumerable
// (that's the default for properties created with
// Object.defineProperty)
if (Object.defineProperty) { // Only needed for ES3-compatibility
Object.defineProperty(Foo.prototype, nifty, {
writable: true
});
}
// ***End change
// Methods shared by all Foo instances
Foo.prototype.method1 = function() {
// This method has access to `nifty`, because it
// closes over the private key
console.log("Truly private nifty info: " + this[nifty]);
};
Foo.prototype.method2 = function() {
// Also has access, for the same reason
console.log("Truly private nifty info: " + this[nifty]);
};
return Foo;
})();
var f = new Foo();
f.method1(); // Can use nifty!
f.method2(); // Can too! :-)
// Both `method1` and `method2` are *reused* by all `Foo` objects
现在,每次代码运行时,私有属性的名称都是不同的
这仍然不是私有的。它只是更难找到。你不想要你拥有的秘密。因为,这是内存泄漏
(注意:当我在下面说“真正私有”时,请记住,如果有人在使用调试器,没有任何东西是真正私有的。下面的“真正私有”只是让任何人都无法编写代码,使用对对象的引用来获取或修改私有数据。)
ES7将拥有真正的私有财产。在此之前,您基本上有三种选择:
真正私有的数据,在调用构造函数时通过闭包保存
通过属性命名约定“请勿插手”属性
非常难以使用的属性,虽然不是私有的,但很难针对这些属性编写代码
真正私有的数据
如果您希望每个实例都有真正的私有信息,标准方法是在构造函数中使用变量,并在构造函数中定义需要该私有数据的方法:
function Foo() {
var secret = Math.floor(Math.random() * 100);
this.iWillTellYouASecret = function() {
console.log("The secret is " + secret);
};
}
Foo.prototype.iDoNotKnowTheSecret = function() {
console.log("I don't know the secret");
};
是的,这意味着会为每个实例创建一个新的iWillTellYouASecret
函数,但当该实例从内存中删除时,它(以及秘密)也会被回收,一个体面的JavaScript引擎可以跨这些函数对象重用函数的代码
“把手拿开”酒店
但大多数情况下,你并不需要真正的私人信息,只需要写着“把手从我身上拿开”的信息。JavaScript中的惯例是以\uuu
开头的属性。是的,这意味着具有实例访问权限的代码可以使用或更改该属性的值,但在大多数具有“真正私有”属性的语言(如Java)中,这实际上也是通过反射实现的
很难使用的属性
如果你想让那些试图使用你的私人数据的人生活更艰难,你可以使用这个技巧