function hereDoc(f) {
return f.toString().replace(/^.+\s/,"").replace(/.+$/,"");
}
var string = hereDoc(function () {/*
我
你
他
*/});
console.log(string)
我
你
他
3.原始值字面量的运算会在编译时进行.
这算是一种优化方式,《高性能JavaScript》提到过:
反编译的弊端
由于新技术的出现(比如严格模式)以及在修改其他相关bug的时候,反编译器这部分的实现经常需要更改,更改就有可能产生新的bug,我自己就亲身遇到过一个bug.大概是在Firefox10左右的时候,具体问题记不大清了,反正是关于反编译时小括号是否要保留的问题,大概是这样的:
复制代码 代码如下:
>(function (a,b,c){return (a+b)+c}).toString()
"function (a, b, c) {
return a + b + c;
}"
在反编译时,(a+b)中的小括号被省略了,由于加法结合律从左到右,所以这没关系.但我遇到的bug是这样的:
复制代码 代码如下:
>(function (a,b,c){return a+(b+c)}).toString()
"function (a, b, c) {
return a + b + c;
}"
这就就不行了,a+b+c不等于a+(b+c),比如在a=1,b=2,c="3"的情况下,a+b+c等于"33",而a+(b+c)等于"123".
关于反编译器,Mozilla工程师Luke Wagner指出,反编译器对他们实现一些新功能的阻碍很大,而且经常会出现一些bug:
Not to pile on, but I too have felt an immense drag from the decompiler in the last year. Testing coverage is also poor and any non-trivial change inevitably produces fuzz bugs.The sooner we remove this drag the sooner we start reaping the benefits. In particular,I think now is a much better time to remove it than after doing significant frontend/bytecode hacking for new language features.
Brendan Eich也表示,反编译器的确有很多不理想:
I have no love for the decompiler, it has been hacked over for 17 years. 存储函数源码
从Firefox17之后,SpiderMonkey改成了第二种实现方法,其他浏览器也应该是这样实现的吧.函数序列化得到的字符串完全和源码一致,包括空白符,注释等等.这样的话,大部分问题就应该没有了吧.不过,貌似我又想到个问题.还是关于严格模式的.
比如:
复制代码 代码如下:
(function A() {
"use strict";
alert("A");
}) + ""
当然,返回的源码中也应该有"use strict",所有浏览器都是这么实现的:
复制代码 代码如下:
function A() {
"use strict";
alert("A");
}
但如果是这样呢:
复制代码 代码如下:
(function A() {
"use strict";
return function B() {
alert("B")
}
})() + ""
内部函数B也处于严格模式中,输出B的函数源码应不应该加上"use strict"呢.试验一下:
上面说了,Firefox17之前Firefox4之后的版本是通过判断当前函数是否处于严格模式来决定输出不输出"use strict"的,函数B继承了函数A的严格模式,所以会有"use strict".
同时函数源码是缩进严格的,因为在反编译的时候,SpiderMonkey会给反编译出的源码进行格式化,即使之前的源码完全没有缩进也没关系:
复制代码 代码如下:
function B() {
"use strict";
alert("B");
}
Firefox17之后的版本会不会带有"use strict"呢?因为是直接把函数源码保存下来的,而且函数B中的确没有"use strict"字样.试验结果是:会添加上"use strict",只是缩进有点问题,因为没有格式化这一步了.
复制代码 代码如下:
function B() {
"use strict";
alert("B")
}
SpiderMonkey最新版的jsfun.cpp源码中有对应的注释
// 如果一个函数的某个上层函数中拥有"use strict",那么这个函数就继承了上层函数的严格模式.
// 我们也会在这个内部函数的函数体内插入"use strict".
// 这就确保了,如果这个函数的toString方法的返回值被重新求值时,
// 重新生成的函数会和原函数有着相同的语义.
而不同的是,其他浏览器都是不带"use strict"的:
复制代码 代码如下:
function B() {
alert("B")
}
虽然这不会有什么太大影响,但我觉的Firefox的实现是更合理的.
您可能感兴趣的文章: