跟我学Jscript的错误和内存管理

跟我学Jscript的错误和内存管理
1、错误的Jscript

IE的ECMAscript实现Jscript有严重混淆的命名函数表达式。现在很多人反对命名函数表达式,甚至目前的版本仍在使用(5.8版中使用IE8)仍存在以下问题。

这里我们以伊江让那些错误,说支一芝碧,争取实现一看。让我们看看以下示例:

示例1:函数表达式的指示符泄漏到外部范围
函数(g){ };
类型G; / / 功能
我们已经说过,有名函数表达式在外层作用域标识符无效,但Jscript显然是违反该规范的,在上面的例子中的标识符G解析为一个函数对象,这是错误的,许多错误是很难找到,因为这个原因

注:这似乎已经修复这个问题,IE9之后

示例2:使用命名函数表达式作为函数声明和函数表达式
类型G; / / 功能
函数(g){ };
在特性环境中,函数声明将优先于要解析的任何表达式。上述例子显示了Jscript,这实际上是命名函数表达式作为函数,因为它解析G实际报关前。

这个例子引出下一个例子。

示例3:命名函数表达式创建两个完全不同的函数对象!
函数(g){ };
F = G; / false
f.expando = 'foo;
g.expando; / /未定义
看到这里,每个人都会觉得问题是严重的,因为修改任何一个对象和另一个对象都是没有任何变化的,这是很糟糕的。通过这个例子,我们可以创建2个不同的对象。也就是说,如果想在f的属性保存一些信息,然后通过引用同一对象的同一名称属性来使用它,那么这是一个大问题,因为它根本不可能。使用G是不可能的。

看一个稍微复杂一些的例子。

示例4:只按顺序解析函数声明,忽略条件语句块
函数g(){
返回1;
};
如果(false){
f函数g(){
返回2;
};
}
g(2);
这个bug查找更加困难,但是bug的原因非常简单。首先,G被解析为函数声明。因为在Jscript函数声明不是由代码块限制条件,这非常糟糕如果分支,G作为另一个函数g(){ return 2 },即是宣布了。然后,所有正则表达式求值,此时F是一个引用到另一个新创建的对象。由于表达的价值评价,它永远不会进入这个邪恶的分支,因此将继续参照第一个函数,函数g(){ return 1 }。在这种情况下,问题是显而易见的:如果你不小心的话叫G F,你将调用一个无关的g函数对象。

你可能会问,不同的对象和arguments.callee之间的区别是什么让我们来看看。
函数g(){
返回{
arguments.callee = = F,
arguments.callee = = G
};
};
(f);true,false }
(g);false,真}
你可以看到,对arguments.callee参考总是调用的函数,这实际上是一件好事,这将稍后解释。

另一个有趣的例子是在赋值语句中使用命名函数表达式,该语句不包含声明:
(函数(){())
f =函数(f){ };
});
根据对代码的分析,我们本来想创建一个全局属性F(注:不可与一般的匿名函数,用于名字的声明,Jscript混淆)在这里。首先,表达式是语句的函数,因此f被声明为局部变量。(和一般的匿名函数语句,然后相同)当函数执行时,f已经被定义,函数的右边(f){被直接分配给局部变量F,所以F不是全局属性。

关于Jscript我们如此异常,及时预防这些问题,首先要防止泄漏和外部标识符的范围,其次,不应该被用来作为参考函数标识符名称;记得在G的较早的例子恼人的标识符如果我们不存在时,G是没有多少不必要的麻烦是可以避免的。因此,关键是总是指功能通过F或arguments.callee.if你使用命名函数表达式,你应该使用这个名字只有当你调试。最后,请记住,这是必要的清理过程中宣言的命名函数声明错误创建的函数。

2、Jscript的内存管理

知道不符合规范的代码,解析错误,如果我们使用它,我们会发现内存实际上是个问题。让我们举个例子。
函数(){()
如果(真){
返回函数(g){ };
}
返回函数(g){ };
});
我们知道这个匿名函数调用返回的函数(有一个标识符G函数)然后分配到外我们还知道命名函数表达式的函数对象产生过剩,这是不是返回的函数对象相同,所以多余的G函数死在返回功能关闭,所以记忆出现问题。这是因为函数在if语句和G在同一范围内声明。在这种情况下,它总是占用内存除非我们明确地断开G函数参考。
函数(){()
变量f;
如果(真){
f =函数(g){ };
}
{其他
f =函数(g){ };
}
将g设置为null后,它将不再用于内存。
g = null;
返回F;
});
通过设置g为null,垃圾回收器回收g所引用的隐式函数,为了验证我们的代码,我们将做一些测试以确保我们的内存被恢复

测试

测试很简单,也就是说,命名函数表达式创建10000个函数,然后将它们存储在一个数组中。稍等片刻,看看这些函数占用了多少内存。然后断开这些引用并重复这个过程:
功能createfn(){
返回(函数(){())
var f;
如果(真){
f =函数f(){
return'standard;
};
}
否则如果(false){
f =函数f(){
return'alternative;
};
}
{其他
f =函数f(){
return'fallback;
};
}
F = null / var;
返回F;
});
}

var arr = { };
对于(var i = 0;i < 10000;i + +){
ARR {我} = createfn();
}

通过运行在WindowsXP SP2中的任务管理器可以看到以下结果:
IE7:

没有`空`:7.6k -> 20.3k
与`空`:7.6k -> 18k

IE8:

没有`空`:14k -> 29.7k
与`空`:14k -> 27k

正如我们所期望的,显示引用可以释放内存,但是内存没有释放,10000个对象的功能在释放大约300万内存之前,这是什么对于一些小脚本,但是对于大型程序,还是长时间运行在低内存设备中的时间,这是非常必要的。

以上是关于所有介绍Jscript错误和内存管理,希望对你有帮助的学习
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部