为什么onevent属性被视为内存快照中的闭包?

huangapple go评论136阅读模式
英文:

Why the onevent properties are being treated as closure in memory snapshot?

问题

当我在触发largeClosures()stopAndClear()点击事件处理程序之后,拍摄内存快照,我可以看到(closure)行包含这些事件处理程序。

这些事件处理程序通过使用onevent属性绑定到DOM元素。

例如:

  1. <!-- begin snippet: js hide: false console: true babel: false -->
  2. <!-- language: lang-html -->
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. <title>Document</title>
  9. </head>
  10. <body>
  11. <p>Analyze the impact of closures on memory</p>
  12. <p>
  13. <button onclick="largeClosures()">
  14. Closures maintain hold on large string
  15. </button>
  16. </p>
  17. <p>
  18. <button onclick="smallClosures()">
  19. Closures maintain hold only on small strings
  20. </button>
  21. </p>
  22. <p>
  23. <button onclick="evalClosures()">Closures with <code>eval</code></button>
  24. </p>
  25. <button onclick="stopAndClear()">Stop and clear</button>
  26. <script>
  27. var closures = [];
  28. function createLargeClosure() {
  29. var largeStr = new Array(1000000).join("x");
  30. return function lC() {
  31. return largeStr;
  32. };
  33. }
  34. function createSmallClosure() {
  35. var smallStr = "x";
  36. var largeStr = new Array(1000000).join("x");
  37. return function sC() {
  38. return smallStr;
  39. };
  40. }
  41. function createEvalClosure() {
  42. var smallStr = "x";
  43. var largeStr = new Array(1000000).join("x");
  44. return function eC() {
  45. eval("");
  46. return smallStr;
  47. };
  48. }
  49. function largeClosures() {
  50. closures.push(createLargeClosure());
  51. }
  52. function smallClosures() {
  53. closures.push(createSmallClosure());
  54. }
  55. function evalClosures() {
  56. closures.push(createEvalClosure());
  57. }
  58. function clear() {
  59. closures.length = 0;
  60. }
  61. function stopAndClear() {
  62. clear();
  63. }
  64. </script>
  65. </body>
  66. </html>
  67. <!-- end snippet -->

内存快照(使用Microsoft Edge Developer Tool - Memory):

为什么onevent属性被视为内存快照中的闭包?

正如你所见,(closure)包含这两个点击事件处理程序。它们每个都分配了32字节的内存。为什么它们被视为闭包?传统的闭包应该像lCsCeC函数一样。

英文:

When I take a memory snapshot after triggering the largeClosures() and stopAndClear() click event handler. I can see the (closure) row contains these event handlers.

These event handlers are bound to the DOM element by Using onevent properties.

For example:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

  1. &lt;!DOCTYPE html&gt;
  2. &lt;html lang=&quot;en&quot;&gt;
  3. &lt;head&gt;
  4. &lt;meta charset=&quot;UTF-8&quot;&gt;
  5. &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  6. &lt;title&gt;Document&lt;/title&gt;
  7. &lt;/head&gt;
  8. &lt;body&gt;
  9. &lt;p&gt;Analyze the impact of closures on memory&lt;/p&gt;
  10. &lt;p&gt;
  11. &lt;button onclick=&quot;largeClosures()&quot;&gt;
  12. Closures maintain hold on large string
  13. &lt;/button&gt;
  14. &lt;/p&gt;
  15. &lt;p&gt;
  16. &lt;button onclick=&quot;smallClosures()&quot;&gt;
  17. Closures maintain hold only on small strings
  18. &lt;/button&gt;
  19. &lt;/p&gt;
  20. &lt;p&gt;
  21. &lt;button onclick=&quot;evalClosures()&quot;&gt;Closures with &lt;code&gt;eval&lt;/code&gt;&lt;/button&gt;
  22. &lt;/p&gt;
  23. &lt;button onclick=&quot;stopAndClear()&quot;&gt;Stop and clear&lt;/button&gt;
  24. &lt;script&gt;
  25. var closures = [];
  26. function createLargeClosure() {
  27. var largeStr = new Array(1000000).join(&quot;x&quot;);
  28. return function lC() {
  29. return largeStr;
  30. };
  31. }
  32. function createSmallClosure() {
  33. var smallStr = &quot;x&quot;;
  34. var largeStr = new Array(1000000).join(&quot;x&quot;);
  35. return function sC() {
  36. return smallStr;
  37. };
  38. }
  39. function createEvalClosure() {
  40. var smallStr = &quot;x&quot;;
  41. var largeStr = new Array(1000000).join(&quot;x&quot;);
  42. return function eC() {
  43. eval(&quot;&quot;);
  44. return smallStr;
  45. };
  46. }
  47. function largeClosures() {
  48. closures.push(createLargeClosure());
  49. }
  50. function smallClosures() {
  51. closures.push(createSmallClosure());
  52. }
  53. function evalClosures() {
  54. closures.push(createEvalClosure());
  55. }
  56. function clear() {
  57. closures.length = 0;
  58. }
  59. function stopAndClear() {
  60. clear();
  61. }
  62. &lt;/script&gt;
  63. &lt;/body&gt;
  64. &lt;/html&gt;

<!-- end snippet -->

Memory snapshot(using Microsoft Edge Developer Tool - Memory):

为什么onevent属性被视为内存快照中的闭包?

As you can see, the (closure) contains these two click event handlers. Each of them has 32 bytes of memory allocated. Why they are being treated as a closure? The traditional closure should be like lC, sC, and eC functions.

答案1

得分: 0

事件处理程序 捕获它们创建时的周围上下文,形成一个 闭包 来保持对在定义它们时处于范围内的变量和函数的访问。

在您的 HTML 代码 中,当您为按钮定义一个 onclick 属性,比如 button onclick="largeClosures()",实际上是创建了一个包含整个函数定义所在范围的函数(闭包),其中包括闭包数组和在 :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定