阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      JavaScript 全局函数 eval() 详解

      功能

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

      例子

      console.log(eval('2 + 2'));//4
      
      console.log(eval('(2 + 2)===4'));//true
      console.log(eval('2 + 2') === eval('4'));//true
      

      注意

      很多人被一些教程和培训老师恐吓的,提到eval就像提到魔鬼一样,其实大可不必;

      eval只是因为功能太过变态,权限很高;我们尽量不要用这个方法处理用户传入的数据,在编程的时候,后端永远不要相信前端的数据,前端永远不好相信用户的数据,因为我们永远不能相信用户传入的时候,所以 eval 可能会带来未知的隐患,这方面确实要注意。

      永远不要相信用户传入的数据,永远不要把 eval 用于处理用户传入的数据

      但是因为它的功能很好,还有一些不错的用法,可以用在实际项目中;

      eval 在实际项目中的使用

      如果符合某条件,import对应的文件

      下面是 jquery 项目的,一段代码

      https://github.com/jquery/jquery/blob/437f389a24a6bef213d4df507909e7e69062300b/test/jquery.js

      // 如果符合某个条件
      if ( config.esmodules && QUnit ) {
          // Support: IE 11+, Edge 12 - 18+
          // IE/Edge don't support the dynamic import syntax so they'd crash
          // with a SyntaxError here.
          dynamicImportSource = "" +
              "import( `${ parentUrl }src/jquery.js` )\n" +
              "	.then( ( { default: jQuery } ) => {\n" +
              "		window.jQuery = jQuery;\n" +
              "		if ( typeof loadTests === \"function\" ) {\n" +
              "			// Include tests if specified\n" +
              "			loadTests();\n" +
              "		}\n" +
              "	} )\n" +
              "	.catch( error => {\n" +
              "		console.error( error );\n" +
              "		QUnit.done();\n" +
              "	} );";
      
          eval( dynamicImportSource );
      
      // Apply similar treatment for AMD modules
      } else if ( config.amd && QUnit ) {
          require.config( {
              baseUrl: parentUrl
          } );
          src = "amd/jquery";
      
          // Include tests if specified
          if ( typeof loadTests !== "undefined" ) {
              require( [ src ], loadTests );
          } else {
              require( [ src ] );
          }
      
      // Otherwise, load synchronously
      } else {
          document.write( "<script id='jquery-js' nonce='jquery+hardcoded+nonce' src='" + parentUrl + src + "'><\x2Fscript>" );
      }
      

      赋值时候的简便写法

      (() => {
          function formatDate() {
              console.log('formatDate');
          }
      
          function formatThousands() {
              console.log('formatThousands');
          }
      
          function formatTest() {
              console.log('formatTest');
          }
          ["formatDate", "formatThousands", "formatTest"].forEach(item => {
              String.prototype[item] = eval(item);
          })
      })()
      

      上面只是介绍用法可以有的思路,这类写法是不优雅的;

      真实项目中,可以下面这样子写,巧妙的借助对象的特性来解决字符串的问题;

      (() => {
          let Utility = {
              formatDate: function() {
                  console.log('formatDate');
              },
              formatThousands: function() {
                  console.log('formatThousands');
              },
              formatTest: function() {
                  console.log('formatTest');
              }
          }
          Object.keys(Utility).forEach(item => {
              String.prototype[item] = Utility[item]
          })
      })()
      

      函数的拷贝

      const foo = x => x + 1
      console.log(eval(foo.toString())(1));
      

      深度拷贝(引申)

      下面是深度拷贝的一个引申,可以作为参考

      const log = console.log;
      
      function test() {
          'use strict';
          let obj1 = { a: 0, b: { c: 0 } };
          let obj2 = JSON.parse(JSON.stringify(obj1));
          log(JSON.stringify(obj2), '\n'); // { a: 0, b: { c: 0}}
      
          obj2.a = 2;
          obj2.b.c = 3;
          log(JSON.stringify(obj1)); // {"a":0,"b":{"c":3}}
          log(JSON.stringify(obj2), '\n'); //{ a: 2, b: { c: 3}}  注意obj2.b.c的值
      }
      test();
      
      目录
      目录