Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript问题/知识点深入 #5

Closed
creeperyang opened this issue Aug 4, 2015 · 3 comments
Closed

JavaScript问题/知识点深入 #5

creeperyang opened this issue Aug 4, 2015 · 3 comments

Comments

@creeperyang
Copy link
Owner

本文是JavaScript问题集锦的姊妹篇,或者就是它的一部分。

至于为什么分开,一是防止篇幅过大,分开有利于更好的组织;二是本文仍然从某些问题开始,但会更深入更系统地阐述某些知识点,而不是局限于解决问题。

@creeperyang
Copy link
Owner Author

1. Is eval really evil?

“eval is Evil: The eval function is the most misused feature of JavaScript. Avoid it”
Douglas Crockford in JavaScript: The Good Parts

《JS语言精粹》认为 eval是JS最被误用的特性,要尽量避免使用。但无论同意或驳斥这个观点,首先认识下 eval

eval使用

The eval() method evaluates JavaScript code represented as a string.

语法

eval(string) // string 可以是JS表达式,语句,多语句。表达式可以引入变量或存在的对象的属性。

描述

eval是全局对象的函数属性,参数是字符串。它会解析字符串并执行。如果参数不是字符串,eval原样返回参数。

eval特性

共享caller的执行上下文

eval会共享caller的执行上下文。这意味着eval中声明的变量可以在当前作用域继续使用,也即影响当前作用域。

function evalLocal() {
    console.log(typeof hello);
    eval('var hello = \'this is hello.\'; noVar = 1; console.log(hello, noVar);');
    console.log(hello, noVar);
    console.log(window.hello, window.noVar);
}
// 输出:
// undefined
// this is hello. 1
// this is hello. 1
// undefined 1

有时候,如果想让eval执行在全局作用域,可以

function evalGlobal() {
    console.log(typeof hi);
    (0, eval)('var hi = \'this is hi.\'; console.log(hi);');
    console.log(hi);
    console.log(window.hi);
}
// 输出:
// undefined
// this is hi.
// this is hi.
// this is hi.

依赖JS解释器解析字符串

JavaScript问题集锦里讲过_对象字面值不能正确解析_,这是JS解释器的问题,所以eval也会有同样问题,可以用解析JSON的例子来看。

var str = '{"x": 1, "y": 2}';
eval(str); // Uncaught SyntaxError: Unexpected token :

// 解决方案
eval('(' + str + ')') // Object {x: 1, y: 2}

eval缺陷

好,步入重点,来谈谈eval是不是真的是邪恶的。

通常,我们可以列出下列缺点:

  1. 需要编译而更慢,此外eval会阻止优化编译器去优化代码(因为eval里的内容会使代码不可预测);
  2. eval恶意脚本的安全问题;
  3. 看起来很丑,可读性差;
  4. 继承执行上下文,绑定调用它的作用域。

这些看起来很有道理,但并不是绝对的。比如安全性,很多时候只是eval服务器响应的信息,此时源是可信的,并不会有很大问题。

结论

一句话,说eval邪恶太绝对,但仍然赞成能不用就不用。


参考

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
  2. https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/

@creeperyang
Copy link
Owner Author

creeperyang commented May 5, 2016

@creeperyang
Copy link
Owner Author

本issue关闭,相关内容并无必要单开一个issue。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant