一个常见的面试题,经常会遇到key没有引号或者使用的单引号的JSON字符串解析问题。
把下面字符串解析为对象。
var str = "{a: 1, 'b': 2}";
或者就是面试题的刁钻要求,不适用JSON.parse如何解析JSON字符串。
这个简单,eval呗,要是eval也不能用呢?或许有人还会想到new Function。然而,对于JS字符串解析运行是有N种方式的。下面为了方便运行查看我们直接解析"console.log('abc')"字符串。
这里就不再说eval和new Function了。
[native code].constructor
所谓[native code]是指那些不是通过JS封装的函数,例如数组的push,slice等等...
[].push.constructor('console.log("abc");')(); // abc
Math.max.constructor('console.log("abc");')(); // abc
但是这个和new Function一个意思。
[].push.constructor === Function // true
动态插入script标签
var script = document.createElement('script');
var txt = document.createTextNode('console.log("abc");');
script.appendChild(txt);
document.body.appendChild(script); // abc
当让,也可以通过把字符串转化为二进制然后通过window.URL.createObjectURL生成URL修改script的src。
var blob = new Blob(['console.log("abc");']);
var src = window.URL.createObjectURL(blob);
var script = document.createElement('script');
script.src = src;
document.body.appendChild(script); // abc
webWorker
上面已经生成了url,那么我们可以直接在worker中运行。
var blob = new Blob(['console.log("abc");']);
var src = window.URL.createObjectURL(blob);
new Worker(src); // abc
当然,这里只是在worker中运行的,如果是JSON解析结果还需要通过postMessage返回出来。
location.href=javascript:
javascript:都经常在a标签的href中或则onclick中用到,不过有人去研究过直接在浏览器地址栏输入运行没有。javascript:alert(),可以看到,页面会直接执行后面的字符串。而且页面不会发生跳转。
location.href='javascript:' + 'console.log("abc")'; // abc
当然,如果你有更好的方式欢迎留言。
小技巧
说到这里想到前面两天在知乎首页看到有人分享的UC面试题。其中有一道题不使用循环生成[1,2,3,4...]长度100的数组。
当然,解题方式很多,递归,setInterval,Array.from都可以办到。既然在这里提出来,就来说一个新奇的思路。
var str = 'var i = 0; var arr = [i++, i++, i++]';
eval(str);
console.log(arr); // [0,1,2]
看到这里不知道有人受到启发没有,我们可以生成这样一个字符串通过eval或则上面任意一种方式去解析。当然,为了更友好的显示,这里生成长度为5示例一下就OK了。
var str = new Array(6).join('i++,'); // 'i++,i++,i++,i++,i++,'
// var str = 'i++,'.repeat(5) 当然,这样写也OK
注意卫生么长度为5这里new Array要用6,join是在每两个item中间拼接,而对于稀疏数组来说,自生值为undefined就不会拼接上去。
和上面示例字符串比较,还差什么?i的声明以及数组的方括号。
var evalstr = 'var i = 0; var arr = [' + str + ']';
eval(evalstr);
console.log(arr); // [0, 1, 2, 3, 4, 5]