你所不知道的eval

作者: 相遇一头猪 | 来源:发表于2019-08-11 00:17 被阅读35次

    首先,eval是什么?MDN对eval的解释是:

    eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。

    如今JSON格式的数据流行于服务端与浏览器之间,有些人喜欢把服务器端传过来的数据在浏览器通过eval转换成可以直接使用的对象。或者拼接字符串,然后把得到的字符串扔进eval方法中执行。这也是eval唯一的优点,就是方便。

    eval('1+1') //2, 这应该是唯一的办法,如果用JSON.parse会报错
    eval("alert(2)");  //弹出2
    

    当我在eval里面声明一个函数时,发生了什么?

    eval("function f() {console.log(2)}");
    

    eval把字符串变成可执行代码(运行了一遍编译器),然后执行。你以为完了吗?

    上面代码执行完毕后,window上多出一个变量,就是f。

    首先,eval没执行前,全局没有f函数:

    image.png

    执行eval之后,window上多次一个f函数:

    image.png

    也就是说,在eval使用新声明函数都会绑定到window上。而window上的属性如果没有手动delete或者设置window.xxx = null,这些变量会一直占据内存空间常驻内存直到页面被销毁才释放。

    上面所说皆属于显示调用eval,下面来看看隐式调用eval的情况。

    隐式调用eval

    Function构造器与eval具有相同的字符串参数特性,应该避免使用它。

    Function构造函数语法:

      var func = new Function(arg1, arg2, ..., functionBody);
    

    例:

      var add = new Function('a', 'b', 'return a+b;');
      console.log( add(2, 3) );    // 5
    

    第二种隐式调用是,当传递字符串参数给setTimeoutsetInterval函数时,会像eval那样去处理。

      function f() {
        console.log(1);
      }
      //推荐写法
      setTimeout(f, 0)
    
    image.png
      //隐式调用eval
      setTimeout("f()", 0)
    
    image.png

    注意,隐式调用需要自己执行。

    缺点

    • 使用eval形式的代码可读性差(其实我觉得差不到哪去)。
    • 代码性能显著降低,需要先运行编译器编译字符串为js代码,然后在执行,如果js代码有误,eval也是会报错的。
    • 可能无意中定义了全局变量,占用内存空间。
    • 减弱了Web应用的安全性,因为eval赋予了将要执行的字符串太多的权限,可能会引起XSS,会不会引起看你对自己代码的把握。

    相关文章

      网友评论

        本文标题:你所不知道的eval

        本文链接:https://www.haomeiwen.com/subject/hfwdjctx.html