编程骗术:揭秘词法作用域的欺骗游戏

153 阅读3分钟

前言

在编程世界中,词法作用域是一个极具影响力的概念,它掌握着变量和函数在代码中被引用和解析的方式。然而,正如魔术师手中的幻术一样,词法作用域也可能隐藏着许多令人意想不到的欺骗和伎俩。本文将揭开编程中这场关于词法作用域的隐秘游戏,探讨其中的欺骗和迷惑,让我们一起深入探索编程世界中的这些“魔术”吧。

欺骗词法作用域

  • eval()

我们先来看下面这段代码:

function foo(str, a){
    console.log(a,b);
}
foo('',1)//1 undefined

在这个例子中,函数foo被调用时传入了两个参数,分别是一个空字符串和数字1。在函数内部,我们尝试打印变量ab的值。然而,变量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接收两个参数 stra。在函数内部,我们使用了 eval 函数来执行传入的字符串 str,这实际上将 var b = 3 当做 JavaScript 代码来执行,从而创建了一个新的变量 b。因为 eval 可以动态改变词法作用域,所以在函数内部的作用域中创建了变量 b

然后,我们尝试打印变量 ab 的值。在这种情况下,由于 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 语句。显式引用变量和属性,遵循词法作用域的原则,有助于提高代码质量和可维护性。牢记良好编程实践,将有助于避免意外行为的发生,确保代码的可靠性和稳定性。