我目前正在研究一种保护JavaScript函数的方法 private ,如果调用者无效,则会抛出异常。那么我在这里遇到一个问题:如果在一个有效的调用者中定义了一个闭包,它是一种从内部闭包中获取有效调用者的方法吗?
例如:
function validCaller() {
var self = this;
self.privateFunction1();
$.each([/*...*/], function (key, val) {
self.privateFunction2();
});
}
当然,privateFunction1
会正确地获得调用者validCaller
,但privateFunction2
会将匿名函数作为调用者,因此访问将被拒绝。
如果我通过表达式caller.caller.caller
从调用堆栈中获取validCaller,这不是正确的方法,因为我无法确定应追溯到多少级别,并且在某些特殊情况下,匿名函数需要在validCaller
之外调用。
也许我以复杂的方式提出问题,简单的方法是:
如何捕获函数的作用域链?
答案 0 :(得分:1)
function MyObject(a, b, c)
{
this.a = a;
this.b = b;
this.c = c;
// Note: NOT using this.private1 = function() { ... }
function private1()
{
...
}
function private2()
{
...
}
// Public methods
this.public1 = function()
{
...
private1(); // Note; not using "this." in the call
...
private2();
}
}
使用这种方法,除了MyObject
的方法之外,没有人能够调用private1
和private2
......但其他人甚至无法找到这些名称和不存在意外名称冲突的风险。
您可以对私有数据成员使用相同的方法。只需在构造函数中将它们声明为简单的局部变量var x;
,并且不要使用this.x
语法来访问它们,而只是x
。至于方法,任何人都无法访问它们,也不会有无意覆盖的风险。
如果您确实需要运行时检查以防止未经授权的函数调用您的方法,则可以使用某种“安全令牌”。
function MyObject()
{
var authorization = []; // An empty array will do
this.private_method = function(auth) {
if (auth !== authorization) throw "Unauthorized call";
...
};
this.public_method = function() {
...
this.private_method(authorization);
...
};
}
使用这种方法,您甚至可以确定哪个实例正在调用私有方法。
如果你想要任何实例的这种能力,那么使构造函数成为一个闭包本身,从封闭的范围中捕获授权令牌。
PS:我不知道你为什么要这么做的背景,但听起来很奇怪。