JavaScript函数声明与函数表达式的区别及内存溢出分析

作者:小括号时间:2026-10-27 10:02:11浏览:116

本文详细解析JavaScript中两种函数定义方式的区别。通过对比函数声明与匿名函数赋值,揭示内部重定义导致的栈溢出机制。文章结合编译时与运行时的执行顺序,阐明变量提升对函数引用的影响,并给出保留原函数的推荐写法。

JavaScript函数定义方式概述

通常情况下,这两种定义方式的调用结果看似一致,但它们在底层机制上存在显著差异。


第一种方式:函数声明内部重定义

首先来看第一种定义方式。


具体代码实现如下:

 
function a(){
alert('old');
} 
var b=a;
function a(){
b();
alert('new');
} 
a();//浏览器就会出现内存溢出的情况

第二种方式:函数表达式覆盖

接下来分析第二种定义方式。


其代码结构如下:

 
function a(){
alert('old');
} 
var b=a;
var a=function(){
b();
alert('new');
} 
a();//浏览器就会按顺序alert出‘old'和‘new'

通过对比可以清晰看出两者的核心区别在于定义的顺序与执行时机。


在第一种方式中,初始并未重新定义函数 a,而是在内部直接调用了其自身,导致无限递归。


而在第二种方式中,执行到 var a=function() 时,变量 a 已被重新赋值为匿名函数,因此后续对 a 的调用指向新函数,重定义生效。


执行机制深入分析

补充说明一:


相关代码示例如下:

 
function a(){
alert('old');
} 
var b=a;
function a(){
b();
alert('new');
} 

编译时: 首先a被定义为alert("old"), 接着又被定义成b();alert("new");


运行时: b = function a(){b();alert("new");}, 此时b和a一样, 函数体中直接调用b, 无论从a调用还是从b调用结果都一样, 产生堆栈溢出


另一方面,


代码如下:

 
function a(){
alert('old');
} 
var b=a;
var a=function(){
b();
alert('new');
} 

编译时: a被定义为alert("old")


运行时: b=function a(){alert("old")}; a=function(){b();alert("new")}; 此时b的函数体中不包括ab中任何一个, a只调用b... 无论怎样都不会产生堆栈溢出...


最佳实践建议

补充说明二:


通常推荐使用第一种写法以避免全局代码污染,但若需保留原始函数引用,则应采用第二种写法。两种方法均符合 W3C 标准。


事实上,第一种写法是较晚出现的优化方案。

作者最新文章