为何eval中声明的函数未被后续同名函数声明覆盖?
为什么eval中的函数声明没有被后续的函数声明覆盖?
常规函数声明的覆盖行为
当重复声明同名函数时,后声明的函数会覆盖之前的,比如以下代码控制台会输出 this is a2:
function a () { console.log("this is a1"); } function a () { console.log("this is a2"); } a();
这是因为函数声明会被变量提升到当前作用域的最顶部,后声明的函数会在提升阶段覆盖先声明的。
含eval的特殊场景
但如果把其中一个函数声明放到eval中,结果就完全不同:
eval("function a (){console.log (\"this is a1\")}"); function a () { console.log("this is a2"); } a();
此时控制台输出的是 this is a1,后续的函数声明并没有覆盖eval里的函数。
原因解析
核心在于变量提升的时机和eval的执行时机差异:
- 常规的
function a() {}属于函数声明,会在代码执行前的编译阶段就被提升到作用域顶部,同时完成变量a的赋值,此时a指向输出this is a2的函数。 eval语句是在代码执行阶段才会被调用,它内部的函数声明会在这个阶段重新对作用域中的变量a赋值,把它改成指向输出this is a1的函数。- 当最后调用
a()时,变量a已经被eval修改过,所以执行的是eval里定义的函数。
简单来说:常规函数声明的赋值发生在编译阶段,而eval对变量的修改发生在执行阶段,后者时机更晚,所以最终覆盖了前者的赋值。
内容的提问来源于stack exchange,提问作者Joe.wang
相关产品推荐
相关产品推荐

