我正在尝试用JavaScript编写全自动单元测试,我正在寻找一种方法来读取各种JS函数中的一些私有变量。我想我回想起了一种方法,可以将特权成员注入一个函数/对象(并且发现了“在JS中没有像私有这样的东西”的压倒性事件)然而我找不到任何指示如何的资源。
我正在尝试阅读.prototype
的属性,但如果有办法,那么有人会知道在哪里指导我的速度比我自己找到的要快。
由于
特权是指可从对象外部使用的函数,可以读取“私有”变量(否则无法从外部读取的变量)。有关Crockford的解释,请参阅http://javascript.crockford.com/private.html。
我试图注入的函数示例是o2
,我需要验证x
的值(这是一个简化的例子,实际的代码做了一些转换并将它们发送到我计划单独测试的其他功能。)
var o2 = function() {
var x = 'me';
};
更新2: 感谢所有花时间回应的人。我看到这里压倒性的反应是,“私人是私人的”,尽管我在其他SA问题中看到的评论中,人们说“JS中没有任何东西是私密的”。我想这更像是修辞评论,而不是我希望能够洞察一些我还不知道的潜在漏洞。
答案 0 :(得分:3)
即使我们尽可能地帮助您,您问题的正确答案也很简单:
如果我们可以直接从闭包外部访问它们,那么闭包变量会有什么用呢?
如果你有一个带有私有变量的对象,它们将无法在函数闭包之外访问,这是构造函数。
var c = function() {
var priv = "private";
this.get = function() {
return priv;
};
}
var o = new c();
o.injected = function() {
return priv; // ERROR!!!!!! priv doesn't exist in function scope
};
当然,如果将整个事物封装在一个函数闭包中然后你就不会有对象私有,而是函数闭包 internals ,它将在这个中的所有原型之间共享,这当然是另一回事。闭合。
(function(){
var intrn = "internal";
// omit "var" to make it global
c = function() {
this.get = function() {
return intrn;
};
};
// omit "var" to make it global
o = new c();
o.injected = function() {
return intrn; // WORKS
};
})();
o.injected();
但这与对象私有不同......
答案 1 :(得分:1)
知道我参加聚会很晚,但是有可能。虽然AFAIK需要使用eval()
和辅助方法:
function foo(){
var a = 'a';
this.addMethod = function(prop, val){
this[prop] = eval('(' + val.toString() + ')');
}
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'
在这种情况下,您可以使用eval()
在闭包的上下文中重新定义函数。但是,使用eval()
是危险的,特别是eval()
任何用户输入都不是{EV}。但是,要在测试套件/脚本中使用它应该没问题。
答案 2 :(得分:0)
我建议您阅读Crockford's treatise,了解如何在javascript对象中实现特权和私有。
如果是特权,你的意思是在对象外部无法访问的方法,但是可以通过其他方法调用,并且实际上是对象上的方法,那么实际上没有任何方法可以做到这一点,因为你设置了一个方法对象,javascript让任何人都称之为。
如果你只是想添加一个只能通过方法调用的函数,你可以通过拥有一个私有成员变量(参见Crockford如何实现它)来做到这一点,你可以把方法放在那个对象上。然后,所有现有方法(以Crockford在构造函数中建议的方式实现访问私有成员数据)可以调用这些方法。它们在技术上可以是不同对象的成员,但如果需要,可以私有访问对象的实例数据。
这一切都很复杂,所以如果你描述了你真正试图解决的问题,你可能会得到一个更好的答案。
答案 3 :(得分:0)
我认为你不能这样做。请考虑以下代码:
function foo() {
var privateVar = 10;
this.privilegedMethod = function() {
return privateVar;
}
}
var obj = new foo();
此处,privilegedMethod
可以访问privateVar
,因为它是定义方法时创建的闭包的一部分。当然,您可以在实例化后始终将新方法附加到对象:
obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"
但是这种新方法无法访问privateVar
。