动态代码执行
JavaScript 动态代码执行
我们写的
动态执行代码普遍存在两个缺点,一是安全性问题,传递的函数体字符串如果包含非法代码也会被执行。二是执行性能,动态执行时会解析代码,存在一定的时间消耗。
new Function
var a = -100;
(function () {
var a = 1;
// 函数执行时的父作用域时全局作用域
new Function("console.log(a)")(); // -100
// 内部的 this 是 window
var nfunc = new Function("return this");
console.log(nfunc()); // Window
// 作为对象的方法时, this 是当前对象
var obj = { nfunc: nfunc };
console.log(obj.nfunc()); // {nfunc: ƒ}
})();
eval
(function () {
// eval 没有自己的作用域,使用当前作用域。
var a = 100;
eval("console.log(a)"); // 100
// 初始化语句会添加变量到当前作用域上,也就是会污染当前作用域。这是 v8 引擎没法优化这段代码的原因,也是性能差的原因。
eval("var b = 20");
console.log(b); // 20
})();
(function () {
"use strict";
// 严格模式下,eval 有自己的作用域,父作用域是当前作用域。
var a = 100;
eval("console.log(a)"); // 100 当前作用域上的 a
// 严格模式下,eval 有自己的作用域,初始化语句将变量添加到自己的作用域内。执行完后当前作用域被销毁
eval("var b = 20");
console.log(b); // 1 全局作用域上的 b
// 返回 eval 代码段产生的闭包
var innerb = eval("var b = 20; (function () { return b })")();
console.log("innerb", innerb); // innerb 20
})();
值得注意的是,
var a = 0;
(function () {
var a = 100;
var fn = eval;
// 非 direct call 的调用方式
fn("console.log(a)"); // 0
})();
setTimeout
var a = -100;
(function () {
var a = 0;
// setTimeout 执行的代码段,没有自己的作用域,运行在全局作用域中
var dynameicCode = "console.log(a)";
setTimeout(dynameicCode, 10); // -100
// setTimeout 执行的代码段,初始化语句会添加变量到 window 上
var dynameicCode = "var b = 200;";
setTimeout(dynameicCode, 10);
setTimeout(function () {
console.log("window.b", window.b); // window.b 200
}, 20);
})();
script.textContent
动态创建
(function () {
var a = 1;
var s = document.createElement("script");
s.textContent = "console.log(a)";
document.documentElement.append(s);
})();
onclick=“xxx”
<script>
var a = -100;
var b = 2;
</script>
<!-- 点击按钮输出 -100 200 -->
<button onclick="var b = 200; console.log(a, b);">click me</button>
<!-- 执行成功后,在控制台检查,全局作用域内并没有变量 b -->