JavaScript -- Item18 JScript Bug and memory management you don't know

Source: Internet
Author: User

JavaScript -- Item18 JScript Bug and memory management you don't know
1. JScript Bug

The ECMAScript of IE implements JScript to seriously confuse the naming function expressions. Many people have come out against the naming function expressions, in addition, the following problems still exist even if the first version is still in use (IE8 uses version 5.8.

Next, let's take a look at the mistakes that IE has made in implementation. As the saying goes, we know that we know what we are and what we can do. Let's take a look at 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 have mentioned earlier, the identifier of the name function expression is invalid in the external scope, but JScript obviously violates this specification. In the above example, the identifier g is parsed as a function object, this is messy, and many bugs that are hard to find are caused by this reason.

Note: IE9 may have fixed this issue.

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

typeof g; // functionvar f = function g(){};

In the feature environment, the function declaration takes precedence over the parsing of any expression. The preceding example shows that JScript uses the named function expression as the function declaration, because it resolves g before actual declaration.

This example introduces the next example.

Example 3: The name function expression creates two completely different function objects!

var f = function g(){};f === g; // falsef.expando = 'foo';g.expando; // undefined

Here, we will think the problem is serious, because it is too evil to modify any object and the other one has no changes. In this example, we can find that two different objects are created, that is, if you want to modify the attributes of f to save a certain information, then, if you reference the g attribute of the same object to use the attribute of the same name, the problem is big, because it is impossible.

Let's take a look at a slightly complex example:

Example 4: Only sequential parsing function declaration and ignore conditional statement Blocks

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

This bug is much more difficult to find, but the cause of the bug is very simple. First, g is parsed as a function declaration. Since function declaration in JScript is not restricted by conditional code blocks, in this very bad if branch, g is treated as another function g () {return 2} is declared again. Then, all "regular" expressions are evaluated, and f is assigned a reference to another newly created object. Since the expression value will never enter the "this hateful if branch", f will continue to reference the first function g () {return 1 }. After the analysis, the problem is very clear: if you call g in f, it will call an unrelated g function object.

You may ask, what is the difference between different objects and arguments. callee? Let's take a look:

var f = function g(){      return [        arguments.callee == f,        arguments.callee == g      ];};f(); // [true, false]g(); // [false, true]

As you can see, the reference of arguments. callee is always called function. In fact, this is also a good thing and will be explained later.

Another interesting example is to use a namefunction expression in a value assignment statement that does not contain a declaration:

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

According to code analysis, we originally wanted to create a global attribute f (Be sure not to confuse it with a general anonymous function, which uses a declaration with a name ), JScript makes a mess here. First, it resolves the expression as a function declaration, So f on the left is declared as a local variable (just like the Declaration in a general anonymous function ), then, when the function is executed, f is already defined, and function f () {} on the right is directly assigned to the local variable f, therefore, f is not a global attribute at all.

After learning about the abnormal nature of JScript, we need to prevent these problems in time. First, prevent identifier leakage with external scopes. Second, we should never reference the identifier used as the function name; do you still remember the annoying identifier g in the previous example? -- If g does not exist, we can avoid unnecessary troubles. Therefore, the key is to always reference a function through f or arguments. callee. If you use a name function expression, you should only use that name during debugging. Finally, remember to clean up the functions that are incorrectly created during the namefunction expression declaration.

2. JScript Memory Management

After learning about these non-conforming code parsing bugs, if we use them, we will find the memory is actually faulty. Let's look at 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 external f. We also know that naming a function expression will lead to the generation of redundant function objects, and this object is not the same as the returned function object. Therefore, this excess g function will die in the closure of the return function, so the memory problem will occur. This is because the function and g in the if statement are declared in the same scope. In this case, unless we explicitly disconnect the reference to the g function, it keeps occupying the memory.

Var f = (function () {var f, g; if (true) {f = function g () {};} else {f = function g (){};} // After g is set to null, it will no longer occupy the memory. g = null; return f ;})();

By setting g to null, the garbage collector recycles the implicit function referenced by g. to verify our code, we will perform some tests, to ensure that our memory is recycled.

Test

The test is simple, that is, the namefunction expression creates 10000 functions and saves them in an array. Wait a while and then check the memory occupied by these functions. Then, disconnect the references and repeat the process. The following 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 through the Task Manager running in Windows XP SP2:

IE7:  without `null`:   7.6K -> 20.3K  with `null`:      7.6K -> 18KIE8:  without `null`:   14K -> 29.7K  with `null`:      14K -> 27K

As expected, it is shown that disconnecting the reference can release the memory, but not a lot of memory is released. Only 10000 function objects can release about 3 MB of memory, which is nothing for some small scripts, however, it is necessary for large programs or devices that run in low memory for a long time.

 

Related Article

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.