JS小知识-欺骗词法作用域

90 阅读2分钟

1. 词法作用域

在正常情况下,JavaScript的词法作用域是由代码中声明变量的位置所确定的。这种作用域链在代码编写阶段就已经确定,不会在运行时改变。这种静态作用域的特性使得我们能够更加可靠地预测变量的行为和作用范围。

2. 欺骗词法作用域的方法

如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时"修改"词法作用域呢?JavaScript中有两种机制来实现这个目的。大众普遍认为在代码中使用这两种机制并不是什么好主意。最重要的原因就是欺骗词法作用域会导致性能下降。

2.1 eval函数

eval 函数是一个强大而又危险的工具,它可以执行包含 JavaScript 代码的字符串。通过在 eval 中声明变量,我们可以在运行时修改词法作用域。

function createVariableWithEval() {
  eval("var localVar = 'I am inside eval';");
  console.log(localVar); // 输出: I am inside eval
}

createVariableWithEval();
console.log(localVar); // 输出: I am inside eval

2.2 with语句

with 语句允许我们在一个特定的对象中执行语句块,这个对象被视为作用域链的一部分。虽然 with 在严格模式下被禁用,但在非严格模式下,它可以用来欺骗词法作用域。

var obj = { prop: "I am inside with" };

with (obj) {
  console.log(prop); // 输出: I am inside with
}

console.log(prop); // 输出: I am inside with

3. 总结

eval()with()会在运行时修改或创建新的作用域,以此来欺骗其他在书写时就被定义的词法作用域。但是这两种机制的副作用使用这两种机制中的任意一种都会导致代码执行变慢。