JavaScript:如何从外部访问匿名函数内的变量

25

假设我有这个匿名函数:

(function(window){

 var private = 'private msg';

 function sayit() {
   alert(private) // works
 }

 document.body.onclick = sayit; // works

})(window);

// private shouldn't be accessible here

这是JavaScript应该表现的方式吗?

也就是说,没有任何方法可以从匿名函数之外的任何地方访问“private”吗?

如果是这样,那么有可能找到某种黑客方法从外部访问“private”,同时保留代码不变吗?


不可以在不更改代码的情况下进行。 - Blender
私有变量是为了保持私有性...你为什么想要从外部访问私有变量呢? - rexcfnghk
@rexcfnghk - 这并不是很重要。这只是那种“因为它就是这样工作”的时刻之一。 - Brandt Solovij
为什么你需要这样做呢?只是为了好玩吗? - Damask
1
@Damask - 有人可能想知道是否可以采取措施来防止错误地假设它无法完成。 - Martin Bramwell
5个回答

14

是的,这就是JavaScript如何让您拥有“私有”变量(隐藏在函数作用域中)。

没有可用的黑客来访问诸如 private 之类的变量,而不需要重新编写代码。

在函数内部定义的使用 var 定义的变量,只能从该函数内部访问。


10

好的,我明白了。

(function(window){
    var alert_original = window.alert;
    window.alert = function(data) {
        window.extracted = data;
        alert_original(data);
    };
})(window);

(function(window){
    var private = 'private msg';
    function sayit() {
    alert(private) // works
 }
 document.body.onclick = sayit; // works
})(window);

点击body后,您可以从extracted中获得“private msg”


1
聪明。只有读取private的值,你无法更改它,因此你只能获得只读的“访问权限”。 - Faiz

2
他们并不是“私有”变量;这只是闭包的工作原理。你可以在Perl和Python中做同样的事情,至少还有许多其他具有闭包和词法作用域的语言。
像Firebug或Chrome Inspector这样的调试器仍然可以在任何时候显示整个堆栈(包括封闭的变量),但除此之外,在不改变原始代码的情况下,我认为你没有机会。
也许如果你告诉我们你真正的问题... :)

闭包是否等同于匿名函数? - steve
1
@barjonah - 它们是相关的,但并不相同。使用匿名函数声明很容易形成闭包。当一个匿名函数(甚至是嵌套或常规命名函数)引用其父作用域中的变量时,就会形成闭包。因此,匿名函数是创建闭包的一种方式。 - Faiz
我忍不住感觉我以前已经回答过这个问题了 :) 但是Faiz是正确的,是的。 - Eevee

0

这就是拥有作用域和私有变量的全部意义。

要么

将私有值设置为全局变量?

要么

在外部声明变量。


-3
你需要做类似于这样的事情:
var Test = (function(window){
 var private = 'private msg';
 var api = {};

 function sayit(){
   alert(private) // works
 }
 document.body.onclick = sayit; // works

api.sayit = sayit;
return api;
})(window);

Test.sayit(); //this would alert 'private msg'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接