与 encodeURI()和 encodeURIComponent()相对的是 decodeURI()和 decodeURIComponent()。 decodeURI()只对使用 encodeURI()编码过的字符解码。例如,%20 会被替换为空格,但%23 不会被 替换为井号(#),因为井号不是由 encodeURI()替换的。

类似地,decodeURIComponent()解码所有 被 encodeURIComponent()编码的字符,基本上就是解码所有特殊值。

let uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.js%23start";
// http%3A%2F%2Fwww.wrox.com%2Fillegal value.js%23start
console.log(decodeURI(uri));
// http:// www.wrox.com/illegal value.js#start
console.log(decodeURIComponent(uri));

uri 变量中包含一个使用 encodeURIComponent()编码过的字符串。首先输出的是使用 decodeURI()解码的结果,可以看到只用空格替换了%20。然后是使用 decodeURIComponent()解码的 结果,其中替换了所有特殊字符,并输出了没有包含任何转义的字符串。

最后一个方法可能是整个 ECMAScript 语言中最强大的了,它就是 eval()。这个方法就是一个完 整的 ECMAScript 解释器,它接收一个参数,即一个要执行的 ECMAScript(JavaScript)字符串。

eval("console.log('hi')");
上面这行代码的功能与下一行等价:
 console.log("hi");

当解释器发现 eval()调用时,会将参数解释为实际的 ECMAScript 语句,然后将其插入到该位置。 通过 eval()执行的代码属于该调用所在上下文,被执行的代码与该上下文拥有相同的作用域链。这意 味着定义在包含上下文中的变量可以在 eval()调用内部被引用,比如下面这个例子:

let msg = "hello world";
    eval("console.log(msg)");  // "hello world"

这里,变量 msg 是在 eval()调用的外部上下文中定义的,而 console.log()显示了文本"hello world"。这是因为第二行代码会被替换成一行真正的函数调用代码。类似地,可以在 eval()内部定义 一个函数或变量,然后在外部代码中引用,如下所示:

eval("function sayHi() { console.log('hi'); }");
    sayHi();

这里,函数 sayHi()是在 eval()内部定义的。因为该调用会被替换为真正的函数定义,所以才可 能在下一行代码中调用 sayHi()。对于变量也是一样的:

eval("let msg = 'hello world';");
    console.log(msg);  // Reference Error: msg is not defined

通过 eval()定义的任何变量和函数都不会被提升,这是因为在解析代码的时候,它们是被包含在 一个字符串中的。它们只是在 eval()执行的时候才会被创建。 在严格模式下,在 eval()内部创建的变量和函数无法被外部访问。换句话说,最后两个例子会报 错。同样,在严格模式下,赋值给 eval 也会导致错误:

"use strict";
eval = "hi"; // 导致错误