11

javascript 中的函数通过保持与其封闭范围的(隐藏)链接来形成闭包。

当我们拥有函数(作为变量值)时,是否可以通过编程方式访问它?

真正的目标是理论上的,但演示可能是列出闭包的属性。

var x = (function(){
   var y = 5;
   return function() {
       alert(y);
   };
})();

//access y here with x somehow
4

4 回答 4

4

这是关闭的(一个)目的 - 保持信息的私密性。由于该函数已经被执行,它的作用域变量不再可以从外部获得(并且从来没有)——只有在它的作用域中执行的函数(仍然)可以访问。

但是,您可以通过 getter/setter 授予访问权限。

你可能想看看Stuart Langridge关于闭包的讨论。Douglas Crockfords Explanations 也非常值得推荐。你可以用闭包做很多花哨的东西;)

编辑:您有几个选项来检查闭包:在 webdeveloper 控制台中观察对象,或者(就像我经常做的那样)返回一个调试函数,它将所有私有变量转储到控制台。

于 2012-06-25T16:04:09.773 回答
3

不,除非你公开它:

var x = function(){
        var y = 5;

        return {             
           getY: function(){
              return y;
          },
          setY: function(newY){
             y = newY;
          }    
       }
   }


    x.setY(4);
于 2012-06-25T16:06:32.860 回答
2

您可以编辑警报功能:

var x = (function(){
   var y = 5;
   return function() {
       alert(y);
   };
})();

var oldAlert = alert;

alert = function (x) {
    oldAlert(x);
    window.y = x;
}

x();

console.log(y); // 5

或者,如果您拥有代码,则可以使用标准的 getter 和 setter。

于 2012-06-25T16:08:58.867 回答
2

如果您在前端环境中,并且可以在先前的脚本标签中执行自己的 Javascript,则可以选择附加 MutationObserver,等待您要监视的脚本标签插入到文档中,并在插入时立即更改其代码,以便公开您要检查或更改的功能。这是一个例子:

<script>
new MutationObserver((mutations, observer) => {
  // Find whether the script tag you want to tamper with exists
  // If you can't predictably identify its location,
  // you may have to iterate through the mutations' addedNodes
  const tamperTarget = document.querySelector('script + script');
  if (!tamperTarget) {
    return;
  }
  observer.disconnect();
  console.log('Target script getting tampered with');
  tamperTarget.textContent = tamperTarget.textContent.replace(
    'return function',
    'window.y = y; return function'
  );
  setTimeout(() => {
    console.log("Hacked into tamper target's script and found a y of", y);
    console.log('Could also have replaced the local y with another value');
  });
})
  .observe(document.body, { childList: true });

</script>

<script>
console.log('Tamper target script running');
var x = (function(){
   var y = 5;
   return function() {
       alert(y);
   };
})();
</script>

这可能不是您的想法,但这种方法是侵入闭包的极少数方法之一,当页面运行您无法更改的代码时,这是一种有用的技术。

如果另一个脚本有一个src而不是内联代码,那会有点困难。当<script>MutationObserver 看到标签时,调整它或用新的脚本标签替换它,该标签textContent是原始脚本内容加上您的修改。为了获得原始内容,<script>在进行所需的替换和插入补丁代码。(或者,如果你有一个服务器,你可以让服务器进行文本替换 - 然后,你需要做的就是src将插入的脚本标记更改为指向你的服务器而不是默认位置。)

于 2019-12-20T11:09:06.737 回答