前言
在编程世界中,词法作用域是一个极具影响力的概念,它掌握着变量和函数在代码中被引用和解析的方式。然而,正如魔术师手中的幻术一样,词法作用域也可能隐藏着许多令人意想不到的欺骗和伎俩。本文将揭开编程中这场关于词法作用域的隐秘游戏,探讨其中的欺骗和迷惑,让我们一起深入探索编程世界中的这些“魔术”吧。
欺骗词法作用域
- eval()
我们先来看下面这段代码:
function foo(str, a){
console.log(a,b);
}
foo('',1)//1 undefined
在这个例子中,函数foo被调用时传入了两个参数,分别是一个空字符串和数字1。在函数内部,我们尝试打印变量a和b的值。然而,变量b并没有在函数内部声明或定义,因此它将被词法作用域解析为undefined。而变量a则被赋予了传入的值1。因此,当我们调用 foo('', 1) 时,控制台会输出 1 undefined。
接下来我们再加入eval()方法:
function foo(str, a){
eval(str)
console.log(a,b);
}
foo('',1)//1 undefined
foo('var b = 3',1)//eval将str变成语句 欺骗词法作用域
这个例子中,函数foo接收两个参数 str 和 a。在函数内部,我们使用了 eval 函数来执行传入的字符串 str,这实际上将 var b = 3 当做 JavaScript 代码来执行,从而创建了一个新的变量 b。因为 eval 可以动态改变词法作用域,所以在函数内部的作用域中创建了变量 b。
然后,我们尝试打印变量 a 和 b 的值。在这种情况下,由于 eval 动态地创建了变量 b,因此控制台会输出 1 3。这展示了在词法作用域中发生的一种欺骗行为,即通过 eval 来修改当前作用域的变量和定义。
- with{}
我们再来看第二种欺骗:with{}欺骗:
当with修改对象中不存在的属性时,会将该属性直接泄露到全局作用
function foo(obj){
with(obj){
a=2,
b=3,
c=4
}
}
var obj2 ={
b:1
}
foo(obj2)//b = 3
console.log(a);//2
我们可以看到,在全局作用域中我们并没有定义一个a,但在foo()方法中的with{}代码块中我们将obj的a修改为了2,并且在 obj2中也没有a这个key,但是我们仍然可以访问到a并且显示,这就是with{}把a给泄露到了全局作用域。
结尾
在编写 JavaScript 代码时,应当避免使用具有潜在风险的特性,如 eval() 和 with 语句。显式引用变量和属性,遵循词法作用域的原则,有助于提高代码质量和可维护性。牢记良好编程实践,将有助于避免意外行为的发生,确保代码的可靠性和稳定性。