eval函数是一种强大而简单的动态生成代码的方法,那么有什么注意事项呢?
当前回答
JavaScript引擎在编译阶段执行了许多性能优化。其中一些可以归结为能够在代码lexx时对其进行静态分析,并预先确定所有变量和函数声明的位置,以便在执行期间解析标识符时花费更少的精力。
但是,如果引擎在代码中发现了eval(..),它本质上必须假设它对标识符位置的所有感知都可能是无效的,因为它在lexlexation时无法确切地知道您可以传递给eval(..)来修改词法作用域的哪些代码,或者您可以传递给对象的内容来创建一个新的词法作用域以供参考。
换句话说,悲观地说,如果eval(..)存在,它所做的大多数优化都是毫无意义的,因此它根本不执行优化。
这就解释了一切。
参考:
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance
其他回答
需要记住的一件事是,您可以经常使用eval()在其他受限制的环境中执行代码——阻塞特定JavaScript函数的社交网站有时可以通过在eval块中分解它们来愚弄它们
eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');
因此,如果你想运行一些JavaScript代码,否则它可能是不允许的(Myspace,我看着你…),那么eval()可能是一个有用的技巧。
然而,由于上面提到的所有原因,你不应该在你自己的代码中使用它,在那里你有完全的控制权——这是没有必要的,最好把它归到“棘手的JavaScript hacks”架子上。
随着带有JavaScript编译器的下一代浏览器问世,这可能会成为一个更大的问题。通过Eval执行的代码在这些新浏览器上的表现可能不如JavaScript的其他部分。应该有人来做侧写。
我想到两点:
安全性(但只要您自己生成要计算的字符串,这可能就不是问题) 性能:除非要执行的代码是未知的,否则无法进行优化。(关于javascript和性能,当然是Steve Yegge的演示)
这是一篇谈论eval的好文章,以及它如何不是一种邪恶: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
I’m not saying you should go run out and start using eval() everywhere. In fact, there are very few good use cases for running eval() at all. There are definitely concerns with code clarity, debugability, and certainly performance that should not be overlooked. But you shouldn’t be afraid to use it when you have a case where eval() makes sense. Try not using it first, but don’t let anyone scare you into thinking your code is more fragile or less secure when eval() is used appropriately.
我不会试图反驳之前所说的任何事情,但我将提供eval()的这种用法,(据我所知)不能以任何其他方式完成。可能还有其他方法来编码,也可能有其他方法来优化它,但这是直接完成的,为了清晰起见,没有任何花哨的东西来说明eval的使用,这真的没有任何其他选择。也就是说:动态(或者更准确地说)编程创建的对象名称(相对于值)。
//Place this in a common/global JS lib:
var NS = function(namespace){
var namespaceParts = String(namespace).split(".");
var namespaceToTest = "";
for(var i = 0; i < namespaceParts.length; i++){
if(i === 0){
namespaceToTest = namespaceParts[i];
}
else{
namespaceToTest = namespaceToTest + "." + namespaceParts[i];
}
if(eval('typeof ' + namespaceToTest) === "undefined"){
eval(namespaceToTest + ' = {}');
}
}
return eval(namespace);
}
//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
//Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
//Code goes here
//this.MyOtherMethod("foo")); // => "foo"
return true;
}
//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);
编辑:顺便说一下,我不建议(出于之前指出的所有安全原因)根据用户输入来确定对象名称。但我想不出你有什么理由这么做。不过,我还是想指出这不是一个好主意:)