为何JavaScript的splice(0)与splice(0, undefined)执行结果不同?
这是个非常细致且有意思的问题!你的推测方向其实很接近本质,让我们一步步拆解背后的逻辑:
1. splice参数的核心规则
首先回忆一下Array.prototype.splice()的定义:它的第二个参数deleteCount是可选参数,作用是指定要删除的元素数量。但这里的“可选”有两个关键场景,引擎对它们的处理逻辑完全不同:
- 场景1:完全不传递第二个参数
- 场景2:显式传递
undefined作为第二个参数
2. 场景1:不传第二个参数的处理逻辑
当你调用['a','b','c'].splice(0)时,由于没有传递第二个参数,引擎会自动将deleteCount设置为从起始索引到数组末尾的所有元素数量,也就是array.length - start(这里就是3-0=3)。所以splice会删除从索引0开始的全部3个元素,返回['a','b','c'],和你预期的一致。
3. 场景2:传递undefined作为第二个参数的处理逻辑
当你显式传入undefined作为第二个参数时,引擎会先尝试将这个参数转换为数字:
undefined转换为数字的结果是NaN- 根据ECMAScript规范,如果
deleteCount是NaN或者小于0,会被强制设置为0
这时候splice会执行“删除0个元素”的操作,所以返回空数组[],原数组保持不变。
4. 关于你推测的arguments.length
你的思路完全正确!函数内部确实是通过判断参数是否被实际传递来区分这两种场景,而不是单纯看参数值是否为undefined。在早期JavaScript实现中,很多内置函数会通过arguments.length来检查参数的传递数量;现代规范里则通过参数的“存在性”(是否被调用者传入)来处理,本质和你的推测一致——显式传undefined会让参数“存在但值为undefined”,和完全不传是两个不同的状态。
举个简单的例子验证这个区别:
function test(a, b) { console.log('arguments.length:', arguments.length); console.log('b is undefined:', b === undefined); } test(0); // arguments.length: 1; b is undefined: true test(0, undefined); // arguments.length: 2; b is undefined: true
你看,两种情况下b都是undefined,但arguments.length不同,这就是splice处理逻辑的关键差异点。
内容的提问来源于stack exchange,提问作者ZephDavies

