在JavaScript中使用inline函数的问题_javascript技巧

前段时间被IE和JavaScript脚本引擎的Memory Leak问题弄得郁闷坏了,不过幸好现在总算是柳暗花明了,并且找到了一些IE中使用脚本避免ML问题的方法。继续研究JavaScript的编写,有发现一些不算ML问题,但是可以节约IE内存使用的方法,在此和大家讨论讨论。

    我们在JavaScript中编写代码,对于定义函数的语句:

function foo()
{
    // TODO: . . .
    return x;
}

可以说是在熟悉不过了。当然除了这种定义函数的方法,我们还有另外几种方法也能定义函数:

var foo = function()
{
    // TODO: . . .
    return x;
}

var foo = new Function('{/*todo*/return x;}');

    后两种方法定义的JavaScript函数,在调用起来和第一种没有任何效果上的区别。

    不过由于JavaScript是解释性语言,当我们定义一个函数的时候,解析引擎生成一个Function对象实例,然后把函数内容保存下来。所以每执行一次函数定义语句,就会生成一个函数。而不像编译语言,一个函数编译一次后就被任何语句调用。啊?难道JavaScript不能调用定义好的函数?不是这个意思了,当我们在制作JavaScript控件时,如果动态输出DHTML来作为控件的内容,就容易出现这样的问题。比如我们在一个HTML对象生成过程中,使用了inline方式定义的函数,那么这个元素生成几次,那个函数也就要同时生成几次。

 function TestObject.prototype.Render(doc, id)
 {
    var span = doc.createElement('SPAN');
    span.Object = this;
    this.m_Element = span;

    if ( id == "NamedMethod" )
    {
        span.onclick = asdf;
    }
    else
    { 
        span.onclick = function()
        {
            var asdf01 = ['a', 's', 'd', 'f'];
            var asdf02 = ['a', 's', 'd', 'f'];
            var asdf03 = ['a', 's', 'd', 'f'];
            var asdf04 = ['a', 's', 'd', 'f'];
            var asdf05 = ['a', 's', 'd', 'f'];
            var asdf06 = ['a', 's', 'd', 'f'];
            var asdf07 = ['a', 's', 'd', 'f'];
            var asdf08 = ['a', 's', 'd', 'f'];
            var asdf09 = ['a', 's', 'd', 'f'];
            var asdf10 = ['a', 's', 'd', 'f'];
            var asdf11 = ['a', 's', 'd', 'f'];
            var asdf12 = ['a', 's', 'd', 'f'];
        };
    }
    span.Name = this.m_Description;
    span.innerText = this.m_Name;
    span.style.display = 'block';
    return span;
 }

    函数span.onclick = function()中的内容是用来占位置的,这样inline方式定义函数,每次Render()都就会生成一个新的函数对象。使用inline方式有什么不好呢?当对象实例多了的时候,会很明显的浪费内存空间呀,试验数据如下:

   

 Normal Method   Inline Method 
 Initialized  27.4 M 27.4 M
 Rendered  33.4 M 35.2 M

    // IE消耗的内存数量(PM+VM)

    单看绝对内存消耗差别不大,可是如果看相对内存消耗:(35.2-33.4)/(33.4-27.4) = 30% !!!,还是很可观的了,而且如果方法本省越大,inline时冗余数据就越多。

    附测试代码:

<html>
<head>
    <title>JScript Function Spending</title>
    <meta name="author" content="birdshome@博客园" /> 
</head>
<body onunload="ReleaseElements()">
    <button id="NamedMethod" onclick="GenerateObjects(this)">
        Append Normal Elements</button>
    <button id="AnonymousMethod" onclick="GenerateObjects(this)">
        Append Inline Elements</button>
    <div id="container">
    </div>
    <script language="Javascript">
function GenerateObjects(elmt)
{
    var room = document.getElementById('container');
    for ( var i=0 ; i < 1000 ; ++i )
    {
         var obj = new TestObject('__Object__' + i);
         room.appendChild(obj.Render(document, elmt.id));
    } 
}

function TestObject(name)
{
    this.m_Name = name;
    this.m_Description = '';
    this.m_Element = null;
         
    this.toString = function()
    {
         return '[class TestObject]'; 
    }
}

function TestObject.prototype.Render(doc, id)
{
    var span = doc.createElement('SPAN');
    span.Object = this;
    this.m_Element = span;

    if ( id == "NamedMethod" )
    {
         span.onclick = asdf;
    }
    else
    
         span.onclick = function()
         {
             var asdf01 = ['a', 's', 'd', 'f'];
             var asdf02 = ['a', 's', 'd', 'f'];
             var asdf03 = ['a', 's', 'd', 'f'];
             var asdf04 = ['a', 's', 'd', 'f'];
             var asdf05 = ['a', 's', 'd', 'f'];
             var asdf06 = ['a', 's', 'd', 'f'];
             var asdf07 = ['a', 's', 'd', 'f'];
             var asdf08 = ['a', 's', 'd', 'f'];
             var asdf09 = ['a', 's', 'd', 'f'];
             var asdf10 = ['a', 's', 'd', 'f'];
             var asdf11 = ['a', 's', 'd', 'f'];
             var asdf12 = ['a', 's', 'd', 'f'];
         };
    }
    span.Name = this.m_Description;
    span.innerText = this.m_Name;
    span.style.display = 'block';
    return span;
}

function asdf()
{
    var asdf01 = ['a', 's', 'd', 'f'];
    var asdf02 = ['a', 's', 'd', 'f'];
    var asdf03 = ['a', 's', 'd', 'f'];
    var asdf04 = ['a', 's', 'd', 'f'];
    var asdf05 = ['a', 's', 'd', 'f'];
    var asdf06 = ['a', 's', 'd', 'f'];
    var asdf07 = ['a', 's', 'd', 'f'];
    var asdf08 = ['a', 's', 'd', 'f'];
    var asdf09 = ['a', 's', 'd', 'f'];
    var asdf10 = ['a', 's', 'd', 'f'];
    var asdf11 = ['a', 's', 'd', 'f'];
    var asdf12 = ['a', 's', 'd', 'f'];
}
</script>
    <script language="javascript">
function ReleaseElements()
{
    var room = document.getElementById('container');
    var spans = room.all.tags('SPAN');
    for ( var i=0 ; i < spans.length ; ++i )
    {
         spans[i].Object = '';
    }

</script>
</body>
</html>

时间: 2024-12-03 06:13:07

在JavaScript中使用inline函数的问题_javascript技巧的相关文章

javascript中Array()数组函数详解_javascript技巧

在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. Array()是一个用来构建数组的内建构造器函数.数组主要由如下三种创建方式: array = new Array() array =

JavaScript中的ubound函数使用实例_javascript技巧

JavaScript中ubound函数方法是返回在 VBArray 的指定维中所使用的最大索引值.使用方法: 复制代码 代码如下: safeArray.ubound(dimension) 其中safeArray是必选项.是一个 VBArray 对象. dimension是可选项.要获知其索引上界的 VBArray 的维数.如果忽略,ubound 将该参数作为 1 进行处理. 如果 VBArray 为空,ubound 方法将返回 undefined.如果 dim 大于 VBArray 的维数或为负

JavaScript中的eval()函数使用介绍_javascript技巧

在JavaScript中,可以使用eval()函数来解析字符串中的JavaScript代码,并返回相应的代码执行结果: 复制代码 代码如下: console.log(eval("42 * 2"));//84 就本质而言,eval()是JavaScript全局对象的一个函数.比如,上述代码等价于: 复制代码 代码如下: console.log(this.eval("42 * 2"));//84 不过在使用eval()语句时,一般都采用上述第一种做法,也即忽略全局对象直

Javascript中的var_dump函数实现代码_javascript技巧

发现了一个非常好的JavaScript调试方法,目前看到的是可以打印Object/Array/Function/String四种类型,使用方法和PHP中的var_dump()一样,只要直接dump(变量名)即可. 复制代码 代码如下: dump(value, [showTypes]) @ param value (Any) value to dump @ param [showTypes] (Boolean) optional to display each key/value's type @

JavaScript中的作用域链和闭包_javascript技巧

作用域 全局作用域 局部作用域 作用域链 执行上下文 活动对象 闭包 闭包优化 JavaScript中出现了一个以前没学过的概念--闭包.何为闭包?从表面理解即封闭的包,与作用域有关.所以,说闭包以前先说说作用域. 作用域(scope) 通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突. 全局作用域(Global Scope) 在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情形拥有全局作

JavaScript中的闭包(Closure)详细介绍_javascript技巧

闭包是JavaScript中一个重要的特性,其最大的作用在于保存函数运行过程中的信息.在JavaScript中,闭包的诸多特性源自函数调用过程中的作用域链上.   函数调用对象与变量的作用域链   对于JavaScript中的每一次函数调用,JavaScript都会创建一个局部对象以储存在该函数中定义的局部变量:如果在该函数内部还有一个嵌套定义的函数(nested function),那么JavaScript会在已经定义的局部对象之上再定义一个嵌套局部对象.对于一个函数,其内部有多少层的嵌套函数

javascript中获取class的简单实现_javascript技巧

js中没有获取class的办法,找了一些封装好的方法,这里整理一下 (1)先进行封装 //封装getClass function getClass(tagName,className) //获得标签名为tagName,类名className的元素 { if(document.getElementsByClassName) //支持这个函数 { return document.getElementsByClassName(className); } else { var tags=document

javascript中的 object 和 function小结_javascript技巧

在学习过传统的面向对象语言后,如 java c++,转学 javascript 却有点不适应,特别是 javascript 中所谓的 object(对象) function(函数),有时候会被搞晕.于是乎简单整理了下面的一些概念性的东西,方便学习和理解,会结合一点 java面向对象的知识加以说明. 先了解几个概念: 1.首先 Object 在 ECMAScripe 中是指什么,在 ECMAScripe 中有5种简单数据类型:Undefined,Null,Boolean,Number,String

javascript中的正则表达式使用详解_javascript技巧

[1]定义:正则又叫规则或模式,是一个强大的字符串匹配工具,在javascript中是一个对象 [2]特性: [2.1]贪婪性,匹配最长的 [2.2]懒惰性,不设置/g,则只匹配第1个 [3]两种写法: [3.1]perl写法(使用字面量形式): var expression = /pattern/flags; e.g. var pattern = /a/i;//匹配字符串中所有'a'的实例 [3.1.1]三个标志flags [a]g:表示全局模式(global) [b]i:表示不区分大小写(i