为什么当 AST 已经知道值时此代码返回 undefined

问题描述

@EnableAspectJAutoproxy
@Aspect
@Component
public class Logger {

@pointcut("execution(* asss.pj.projekat_bioskop.controller.*.*(..))")
public void allRESTMethods(){};


@Around("allRESTMethods()")
public void blabla(ProceedingJoinPoint pjp) {
    //@Before
    String methodName = pjp.getSignature().getName();
    String before = "*** Attempting " + methodName + " method ***";
    writeLog(before);

    try {
        //@AfterReturning
        pjp.proceed();

        String success = "\n*** Method " + methodName + " has succeeded";
        writeLog(success);
    } catch (Throwable throwable){
        //@AfterThrowing
        String Failed = "\n*** Method " + methodName
                + " has Failed. " + throwable.getMessage() + " .***";
        writeLog(Failed);
    }

    //@After
    String after = "\n";
    writeLog(after);
}


public void writeLog(String log){

    File file = new File("filmovi_izvestaj.txt");
    try (Writer wr = new FileWriter(file,true)){
        wr.write(log);
    } catch(FileNotFoundException fe){
        fe.printstacktrace();
    } catch(IOException ioe){
        ioe.printstacktrace();
    }
}

当我把这段代码放到 AST 资源管理器中并运行它时。我实际上看到在执行代码之前,名称已经分配给变量“Lydia”。我知道 AST 是在代码运行之前创建的。但是当代码被执行时,它返回 undefined。我对此很困惑,请您帮帮我

解决方法

该代码段中有两个同名的变量 (name)。如果您仔细查看生成的 AST,您会看到两个声明。

AST 没有显示两个声明的范围,这是一个重要方面。变量的作用域是程序中变量名称​​可见的区域;也就是说,与变量相关联。两个变量同名是完全合法的;如果它们有重叠的作用域,则内部作用域将覆盖外部作用域。

所有这些对于大多数编程语言来说都是通用的,但是 ECMAScript 的范围规则比一般规则要复杂得多(这在一定程度上就是为什么 AST 工具显示范围会很有用)。 ECMAScript 具有两组不同的范围规则,一组用于使用 var 声明的变量,另一组用于使用 letconst 声明的变量。

虽然这个简单的例子没有显示所有的差异,但它确实显示了一个重要的差异:虽然内部 var 声明的 name 可以在初始化之前使用,导致值undefined,在初始化之前不能使用let声明的age,导致抛出错误。 (let 声明的变量在初始化之前处于所谓的“临时死区”中。)

本示例中未显示的区别在于函数 sayHi 内声明的变量范围的边界。 var 声明的变量的范围是声明它的最里面的函数体(包括在同一范围内声明的任何函数,除非它们具有相同名称的覆盖声明)。另一方面,let 声明的变量的范围仅限于最内部的封闭块。但在本例中,内部 var namelet age 的最内部封闭块是函数 sayHi 的主体。

在 ECMAScript 中,变量的作用域始终是整个块。这与 C 等语言形成对比,在 C 语言中,变量的范围仅从变量的声明扩展到封闭块的结尾。这在这种情况下会有所不同:在 C 范围规则下,name 中的 console.log(name) 将引用外部声明,因为内部声明在代码中更靠后,因此其作用域尚未开始然而。而 age 中的 console.log(age) 是非法的,因为没有声明 age 的封闭作用域。但是在 ECMAScript 中,声明被“提升”以包含整个块,从而创造了临时死区的可能性。

虽然这可能已经是太多信息了,但我应该注意,我并没有真正涵盖 ECMAScript 或 C 中范围界定的所有奇怪问题,而且其他语言有其他细微不同的范围界定规则。