在使用JSON.stringify()方法将js对象转为字符串时,如果有循环引用,那么会报错,这个的解决。

JSON.stringify虽然比较常用,但是还有某些细节是我们不知道的,参见MDN文档

引用对象的解法:

  1. const cache = []
  2. JSON.stringify(stat, (key, value) => {
  3. if (cache.indexOf(value) !== -1) {
  4. return;
  5. }
  6. cache.push(value);
  7. })

对比eval与new Function

eval是一个普通的函数,主要作用是动态解析和执行字符串,通过它可以将String变成可以执行的代码,与这个类似的有 new FunctionsetTimeout、setInterval

对比

  • window.eval和new Function都是全局作用域的,即他们只能调用**全局变量**;
  • eval是局部函数,即他可以调用其**父函数的局部变量**。

**

特点Function

  • 注意由于new Function内访问全局作用域的变量,对于浏览器环境在当前文件的最外层就是全局作用域,但是对于node.js环境就会有问题,nodejs里面的new Function访问的全局作用域global,而文件内最外层的是输入当前模块的,这里需要额外注意一下。
  • new Function() 与 Function()是等价的。

示例

  1. var a = 10;
  2. var b = 20;
  3. var test = function () {
  4. var b = 30;
  5. return function (){
  6. return a + b + c
  7. }
  8. }
  1. var a = 1;
  2. var b = 10;
  3. var test = function () {
  4. var b = 30;
  5. return Function("", "return a + b")
  6. }
  7. var d = test()
  8. d()
  9. // 11
  10. // node下运行会报错,a 未定义
  1. var a = 1;
  2. var b = 10;
  3. var test = function () {
  4. var b = 30;
  5. eval("!function _ (c){ console.log(a + b +c)}(40)") //71
  6. Function("c", "console.log(a + b +c)")(40) // 51
  7. }
  8. test()
  1. // eval
  2. var a = 0;
  3. console.log(eval("var a = 10; a")) //10
  4. console.log(a) //10
  5. // new Function()
  6. var b = 0;
  7. console.log((new Function("var b = 10;return b"))()) // 10
  8. console.log(b) // 0
  9. // eval可以访问全局作用域的局部作用域
  10. var c = 2;
  11. function func1 (){
  12. var b = 1;
  13. return eval("c + b")
  14. }
  15. console.log(func1()) //3
  16. // window.eval 只可以访问全局作用域
  17. var c = 2;
  18. function func1 (){
  19. var b = 1;
  20. return window.eval("c + b")
  21. }
  22. console.log(func1()) // ReferenceError: b is not defined
  23. // new Function 只能访问全局作用域的变量
  24. var d = 2;
  25. function func1 (){
  26. var e = 1;
  27. return (new Function("return d + e"))()
  28. }
  29. console.log(func1()) // Uncaught ReferenceError: e is not defined
  30. // eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行
  31. // code 1
  32. var foo = 1;
  33. function test() {
  34. var foo = 2;
  35. eval('foo = 3');
  36. return foo;
  37. }
  38. test(); // 3
  39. foo; // 1
  40. // code 2
  41. var foo = 1;
  42. function test() {
  43. var foo = 2;
  44. var bar = eval;
  45. bar('foo = 3');
  46. return foo;
  47. }
  48. test(); // 2
  49. foo; // 3
  50. // 与code 2等价
  51. var foo = 1;
  52. function test() {
  53. var foo = 2;
  54. window.foo = 3;
  55. return foo;
  56. }
  57. test(); // 2
  58. foo; // 3
  59. // 与code2 等价
  60. var foo = 1;
  61. function test() {
  62. var foo = 2;
  63. eval.call(window, 'foo = 3');
  64. return foo;
  65. }
  66. test(); // 2
  67. foo; // 3
  • 在实际的开发过程中,基本不会使用到这两个函数,除非必须要将某段字符串作为JavaScript代码执行。

    不建议使用的主要原因

  1. new Function 定义函数相比于其他的定义方式,执行速度慢。
  2. eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行。
  3. eval可以执行传递给他的任意代码,如果代码未知,或者存在隐患时,所以可能会存在安全隐患。XSS
  4. 无法打断点进行调试
  5. 代码压缩混淆时不友好,会报错。
  6. 可读性差
  7. 浏览器有快编译和慢编译,快编译用于编译稳定的和可预测的代码,对于eval这样的,明显是不可预测的,所以速度会慢。
  8. 对使用者要求较高

    相关资料:

  • 关于eval与new Function
  • JavaScript 为什么不推荐使用 eval?

    作用

  • 在 use strict 模式下函数作用域内获得全局this对象(window)

  • 在开发一些类库的时候可能会用到,比如webpack等之类的工具
  • babel在进行代码转换时,将其编译成es5时会用到

    1. var _globals = (function(){ return this || (0,eval)("this"); }());

    JavaScript取整数的方法

  • Math.floor

  • Math.ceil
  • ~~ 与 Math.floor效果相同

函数怎么判断是否是new调用

  1. function People() {
  2. if (this instanceof People) {
  3. console.log("new 调用")
  4. } else {
  5. console.log("function 调用")
  6. }
  7. }