Learn from me. JScript Bug and memory management _javascript tips

Source: Internet
Author: User
Tags anonymous

1. JScript bugs

IE's ECMAScript implementation JScript severely confuses the named function expression, making many people come out against a named function expression, and even the version that is currently in use (version 5.8 in IE8) still has the following problems.

Let's take a look at IE in the implementation of the mistakes made, as the saying goes, known to win. Let's take a look at some of the following examples:

Example 1: The identifier of the function expression is leaked to the external scope

var f = function g () {};
typeof G; "Function"

As we said before, the identifier for a named function expression is not valid in the external scope, but JScript obviously violates this specification, and the identifier G in the example above is parsed into a function object, which is a mess, and many of the bugs that are difficult to find are caused by this.

Note: IE9 seems to have fixed the problem later

Example 2: Use a named function expression as both a function declaration and a function expression

typeof G; "function"
var f = function g () {};

In an attribute environment, a function declaration takes precedence over any expression, and the example above shows that JScript actually declares a named function expression as a function because it parses g before the actual declaration.

This example leads to the next example.

Example 3: A named function expression creates two distinct function objects!

var f = function g () {};
f = = g; False
F.expando = ' foo ';
G.expando; Undefined

See here, people will feel the problem is serious, because the modification of any object, the other one does not change, this is too bad. In this example, you can find that creating 2 different objects, that is, if you want to modify the attributes of F to hold a certain information, and then take it for granted by referencing the same attribute of G of the same object, the problem is large, because it is impossible.

Let's look at a slightly more complicated example:

Example 4: Just parse the function declaration sequentially and ignore the conditional statement block

var f = function g () {return
  1;
};
if (false) {
 F = function g () {return
 2;}
 ;
} g (); 2

This bug lookup is much more difficult, but the cause of the bug is very simple. First, G is resolved as a function declaration, and because the function declaration in JScript is not bound by a conditional code block, in this very bad if branch, G is treated as another function g () {return 2}, which is declared again. All "regular" expressions are then evaluated, while F is given a reference to another newly created object. As the expression is evaluated, it will never go into "This hateful if branch, so F will continue to refer to the first function g () {return 1}. In this case, the question is clear: if you are not careful enough to call G in F, then an irrelevant G function object will be invoked.

You might ask, what is the difference between a different object and a Arguments.callee? Let's take a look at:

var f = function g () {return
  [
  Arguments.callee = f,
  Arguments.callee = = g
  ];
};
f (); [True, False]
g ();//[False, True]

As you can see, Arguments.callee's references are always called functions, which is actually a good thing to explain later.

An interesting example is the use of a named function expression in an assignment statement that does not contain a declaration:

(function () {
 F = function f () {};
}) ();

According to the analysis of the code, we originally wanted to create a global attribute F (be careful not to confuse the general anonymous function with a name declaration), where JScript made a mess of it, and first he parsed the expression as a function declaration, So the F on the left is declared as a local variable (like the declaration in a general anonymous function), then, when the function executes, f is already defined, and function f () {} on the right is assigned directly to the local variable F, so f is not a global property at all.

Knowing that JScript is so sick, we need to prevent these problems in time, first to guard against the external scope of the identifier leak, and secondly, to never refer to identifiers that are used as function names; remember that annoying identifier g in the previous example? --if we can do that if G doesn't exist, we can avoid a lot of unnecessary trouble. Therefore, the key is always to refer to the function through F or arguments.callee. If you use a named function expression, you should only use that name when debugging. Finally, keep in mind that you must clean up the functions created incorrectly during a named function expression declaration.

2. Memory management of JScript

Knowing that these nonstandard code resolves bugs, if we use it, we'll find that the memory aspect is actually problematic, to see an example:

var f = (function () {
 if (true) {return
 function g () {};
 }
 return function g () {};
}) ();

We know that this anonymous function calls the returned function (a function with the identifier g), and then assigns the value to the outer F. We also know that a named function expression causes an extra function object that is not the same as the returned function object. So the extra G function dies in the closure of the return function, so the memory problem arises. This is because the function inside the IF statement is declared in the same scope as G. In this case, unless we explicitly disconnect the reference to the G function, it is still occupied with memory.

var f = (function () {
 var f, G;
 if (true) {
 f = function g () {};
 }
 else {
 F = function g () {};
 }
 If you set G to null, it will no longer take up memory.
 g = null;
 return f;
}) ();

By setting G to null, the garbage collector reclaims the implicit function that G refers to, in order to verify our code, we do some testing to make sure that our memory is recycled.

Test

The test is simply that a named function expression creates 10,000 functions and then saves them in an array. Wait a little while to see how much memory these functions actually occupy. Then, disconnect the references and repeat the process. Here is the test code:

function Createfn () {return
 (function () {
 var F;
 if (true) {
  F = function f () {return
  ' standard ';
 }} else if (false) {
  F = function f () {return
  ' alternative ';
  };
 } else {
  F = function f () {return
  ' fallback ';}
  ;
 } var F = null;
 return f;
 }) ();
}

var arr = [];
for (Var i=0 i < 10000 i++) {
 Arr[i] = Createfn ();
}

You can see the following results by running Task Manager in Windows XP SP2:

IE7:

 without ' null ': 7.6K-> 20.3K with
 ' null ':  7.6K-> 18K

IE8:

 without ' null ': 14K- > 29.7K with
 ' null ':  14K-> 27K

As we have expected, showing a disconnect reference frees up memory, but frees up not a lot of memory, and 10,000 function objects release about 3M of memory, which is not much of a small script, but is necessary for large programs, or for long periods of time running in low memory devices.

The above is about JScript bug and memory management of all the introduction, I hope to help you learn.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.