本文探讨 JavaScript 中同名函数的行为机制。与 Java 不同,JS 不支持基于参数类型的函数重载。当定义多个同名函数时,后定义的函数会完全覆盖先前的定义。文章通过具体代码示例展示了函数定义顺序对最终执行结果的决定性影响,并澄清了局部作用域内函数声明的提升特性。
JavaScript 函数覆盖机制概述
熟悉 Java 开发的开发者对函数的覆盖(Override)和重载(Overload)概念应当十分熟悉。
在 Java 等强类型语言中,重载指的是函数名相同,但参数类型、顺序、数量或返回值存在差异的情况。
覆盖则是指子类重新定义父类中参数类型、顺序、数量及返回值完全相同的函数。
那么,JavaScript 是否具备类似的语言特性呢?
答案是否定的。在 JavaScript 中,如果存在多个同名函数,引擎只会保留最后一个定义的函数,前面的定义会被直接覆盖。
同名函数定义顺序的测试验证
为了直观展示这一机制,我们首先观察以下代码示例。
代码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
//展现结果
function showResult(result) {
var showDiv = document.getElementById('result');
showDiv.innerHTML = '';
showDiv.innerHTML = result;
};
//展现结果2
function showResult2(result) {
var showDiv = document.getElementById('result2');
showDiv.innerHTML = '';
showDiv.innerHTML = result;
};
//展现结果3
function showResult3(result) {
var showDiv = document.getElementById('result3');
showDiv.innerHTML = '';
showDiv.innerHTML = result;
};
//测试同名方法
function testFun() {
showResult('this is a function named \'testFun\' with no arguments.');
};
function testFun(arg) {
showResult('this is a function named \'testFun\' with one argument,the argument is '+arg);
};
//2th测试,交换两个函数的顺序
//测试同名方法
function testFun2(arg) {
showResult2('this is a function named \'testFun2\' with one argument,the argument is '+arg);
};
function testFun2() {
showResult2('this is a function named \'testFun2\' with no arguments.');
};
//3th测试,测试覆盖,同名同参数
function testFun3() {
showResult3('this is a function named \'testFun3\' first.');
};
function testFun3() {
showResult3('this is a function named \'testFun3\' second.');
};
//-->
</SCRIPT>
<BODY>
<div>
<input type='button' onclick='testFun();' value='function with no arguments'/></br>
<input type='button' onclick="testFun('test');" value='function with one argument test'/>
</div>
<div id="result"></div>
<hr>2th test <hr>
<div>
<input type='button' onclick='testFun2();' value='function with no arguments'/></br>
<input type='button' onclick="testFun2('test');" value='function with one argument test'/>
</div>
<div id="result2"></div>
<hr>3th test <hr>
<div>
<input type='button' onclick='testFun3();' value='test function share the same name and arguments.'/></br>
</div>
<div id="result3"></div>
</BODY>
</HTML>首先点击名为 'function with no arguments' 的按钮。
页面显示的结果为:this is a function named 'testFun' with one argument,the argument is undefined。
接着点击名为 'function with one argument test' 的按钮。
页面显示的结果为:this is a function named 'testFun' with one argument,the argument is test。
再次点击名为 'function with no arguments' 的按钮。
页面显示的结果为:this is a function named 'testFun2' with no arguments.。
随后点击名为 'function with one argument test' 的按钮。
页面显示的结果为:this is a function named 'testFun2' with no arguments.。
通过上述测试可以发现,仅仅交换了两个同名函数的定义顺序,最终执行的结果便截然不同。
从上面的测试中我们可以得出结论:在 JavaScript 中,只要函数定义在下方,它就会覆盖上方的同名函数定义。
接下来我们继续观察覆盖的情况。
点击名为 'test function share the same name and arguments.' 的按钮。
页面显示的结果为:this is a function named 'testFun3' second.。
测试结果十分明显,其结论与前述情况一致。
结论:最后定义的函数生效
最终,我们得出以下结论:
当方法重名时,JavaScript 会以最后定义的函数作为实际的函数体。需要注意的是,这并不包括 JavaScript 继承机制中的覆盖行为。
欢迎拍砖