1

本文章记录本人在学习 JavaScript 中看书理解到的一些东西,加深记忆和并且整理记录下来,方便之后的复习。

小白使用 eval()

如果在代码中使用了eval(),请记住一句话:“eval()是一个魔鬼”。该函数可以将任意的字符串当做一个js代码来执行。当需要讨论的代码是预先编译好了(不是在动态运行时候决定),是没有理由使用eval()的。例如,如果你知道点表示法,但是不知道下表表示法的情况(下面一个栗子)。

eval("myValue = myObject." + myKey + ";");

而不是这样写(下面一个栗子)。

myValue = MyObject[myKey];

安全隐患

使用eval()是有一些安全隐患的,因为这样做有可能执行被篡改过的代码(例如来自网络的代码)。这是在处理来自一个Ajax请求的JSON响应时候常见的反模式。在那些情景下,最好是使用浏览器内置的方法来解析JSON请求,以确保安全性和有效性。

还有eval()函数还减弱了应用程序的安全性,因为他给被请求的文本赋予了太多的权力,而且就像with语句执行的方式一样,它降低了语言的性能。

定时器

在编写js特效的时候,会常用setTimeout、setInterval()方法。要牢记使用这些构造函数来传递参数,在大部分情况下,会导致类似eval()的隐患,因此应该也尽量避免使用这些函数。(下面一个栗子)

// bad
setTimeout("myFunc()", 1000);
setInterval("myFunc(1, 2, 3)", 1000);

// good
setTimeout(myFunc, 1000);
setInerval(function(){
    myFunc(1, 2, 3);
}, 1000);

new Function()

使用new Function()构造函数和eval()是比较类似的,因此该函数的使用也需要十分小心。该函数是一个功能强大的函数,但是通常容易被误用。如果一定要使用eval()的话,可以考虑是new Function()来代替eval()。这样做的一个潜在的好处就是由于在new Function()中的代码将在局部变量函数空间中运行,因此代码中任何采用var定义的变量不会自动成为全局变量(下面一个栗子)。

console.log(typeof un); // undefined
console.log(typeof deux); // undefined
console.log(typeof trois); // undefined

var jsstring = "var un = 1; console.log(un);"
eval(jsstring); // 1

jsstring = "var deux = 2; console.log(deux);"
eval(jsstring); // 2

jsstring = "var deux = 2; console.log(deux);"
(function(){
    eval(jsstring);
}()); // 3

console.log(typeof un); // number
console.log(typeof deux); // undefined
console.log(typeof trois); // undefined

还有就是eval()是会影响到作用域链的,而Function更像一个沙盒。无论在那里执行Function,它都仅仅能看到全局作用域。因此对局部变量的影响比较小(下面一个栗子)。

(function(){
    var local = 1;
    eval("local = 3; console.log(local)");
    console.log(local); // 3
}());

(function(){
    var local = 1;
    Function("console.log(typeof local);")(); // undefined
}());

严格模式下的 eval()

来自MDN:在严格模式下 eval 仅仅为被运行的代码创建变量, 所以 eval 不会影响到名称映射到外部变量或者其他局部变量(下面一个栗子)。

var x = 17;
var evalX = eval("'use strict'; var x = 42; x");
assert(x === 17);
assert(evalX === 42);

更多的详细内容:严格模式 MDN

最后,如果文章有什么错误和疑问的地方,请指出。与sf各位共勉!


_我已经从中二毕业了
7.9k 声望235 粉丝

不搞前端会死星人。