在使用JSON.stringify()方法将js对象转为字符串时,如果有循环引用,那么会报错,这个的解决。
JSON.stringify虽然比较常用,但是还有某些细节是我们不知道的,参见MDN文档
引用对象的解法:
const cache = []JSON.stringify(stat, (key, value) => {if (cache.indexOf(value) !== -1) {return;}cache.push(value);})
对比eval与new Function
eval是一个普通的函数,主要作用是动态解析和执行字符串,通过它可以将String变成可以执行的代码,与这个类似的有 new Function,setTimeout、setInterval
对比
- window.eval和new Function都是全局作用域的,即他们只能调用**全局变量**;
- eval是局部函数,即他可以调用其**父函数的局部变量**。
特点Function
- 注意由于new Function内访问全局作用域的变量,对于浏览器环境在当前文件的最外层就是全局作用域,但是对于node.js环境就会有问题,nodejs里面的new Function访问的全局作用域global,而文件内最外层的是输入当前模块的,这里需要额外注意一下。
- new Function() 与 Function()是等价的。
示例
var a = 10;var b = 20;var test = function () {var b = 30;return function (){return a + b + c}}
var a = 1;var b = 10;var test = function () {var b = 30;return Function("", "return a + b")}var d = test()d()// 11// node下运行会报错,a 未定义
var a = 1;var b = 10;var test = function () {var b = 30;eval("!function _ (c){ console.log(a + b +c)}(40)") //71Function("c", "console.log(a + b +c)")(40) // 51}test()
// evalvar a = 0;console.log(eval("var a = 10; a")) //10console.log(a) //10// new Function()var b = 0;console.log((new Function("var b = 10;return b"))()) // 10console.log(b) // 0// eval可以访问全局作用域的局部作用域var c = 2;function func1 (){var b = 1;return eval("c + b")}console.log(func1()) //3// window.eval 只可以访问全局作用域var c = 2;function func1 (){var b = 1;return window.eval("c + b")}console.log(func1()) // ReferenceError: b is not defined// new Function 只能访问全局作用域的变量var d = 2;function func1 (){var e = 1;return (new Function("return d + e"))()}console.log(func1()) // Uncaught ReferenceError: e is not defined// eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行// code 1var foo = 1;function test() {var foo = 2;eval('foo = 3');return foo;}test(); // 3foo; // 1// code 2var foo = 1;function test() {var foo = 2;var bar = eval;bar('foo = 3');return foo;}test(); // 2foo; // 3// 与code 2等价var foo = 1;function test() {var foo = 2;window.foo = 3;return foo;}test(); // 2foo; // 3// 与code2 等价var foo = 1;function test() {var foo = 2;eval.call(window, 'foo = 3');return foo;}test(); // 2foo; // 3
- new Function 定义函数相比于其他的定义方式,执行速度慢。
- eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行。
- eval可以执行传递给他的任意代码,如果代码未知,或者存在隐患时,所以可能会存在安全隐患。XSS
- 无法打断点进行调试
- 代码压缩混淆时不友好,会报错。
- 可读性差
- 浏览器有快编译和慢编译,快编译用于编译稳定的和可预测的代码,对于eval这样的,明显是不可预测的,所以速度会慢。
- 对使用者要求较高
相关资料:
- 关于eval与new Function
-
作用
在 use strict 模式下函数作用域内获得全局this对象(window)
- 在开发一些类库的时候可能会用到,比如webpack等之类的工具
babel在进行代码转换时,将其编译成es5时会用到
var _globals = (function(){ return this || (0,eval)("this"); }());
JavaScript取整数的方法
Math.floor
- Math.ceil
- ~~ 与 Math.floor效果相同
函数怎么判断是否是new调用
function People() {if (this instanceof People) {console.log("new 调用")} else {console.log("function 调用")}}
