不加分号可能会使代码错误执行
故事背景
今天在刷leetcode46. 全排列的时候,出现了一个令人费解的问题
var permute = function (nums) {
const res = []
const backtrack = (first = 0) => {
if (first === nums.length) {
res.push([...nums])
return
}
for (let i = first; i < nums.length; i++) {
[nums[first], nums[i]] = [nums[i], nums[first]]
backtrack(first + 1);
[nums[first], nums[i]] = [nums[i], nums[first]]
// ^
// TypeError: Cannot set properties of undefined (setting '3')
}
}
backtrack()
return res
};
脑子过了一遍好像,for中没有能取到3的时候,于是打log看看在什么情况下i的取值会到3,于是便有下面不同的报错
var permute = function (nums) {
const res = []
const backtrack = (first = 0) => {
if (first === nums.length) {
res.push([...nums])
return
}
console.log('---')
for (let i = first; i < nums.length; i++) {
console.log(first, i)
[nums[first], nums[i]] = [nums[i], nums[first]]
// ^
// TypeError: Cannot set properties of undefined (setting '1')
backtrack(first + 1)
[nums[first], nums[i]] = [nums[i], nums[first]]
}
}
backtrack()
return res
};
先说解决方法:给backtrack()
加上分号,即backtrack();
分析原因:
有2个前置知识点要先了解,假设有const arr = ['a', 'b', 'c']
- 当你在数组后面的方括号[中使用逗号分隔的多个索引时,它实际上会返回最后一个索引对应的元素。
arr[1,2] => arr[2] => 'c'
- 解构赋值的语法将数组中的值交换位置时,整个表达式返回交换之后的结果
[arr[1], arr[2]] = [arr[2], arr[1]] => ['c', 'b']
因此第一个错误中,有如下执行过程
backtrack(first + 1)
[nums[first], nums[i]] = [nums[i], nums[first]]
// 等价于下面的代码
backtrack(first + 1)[nums[first], nums[i]] = [nums[i], nums[first]]
// 当first = 2,执行代码变成这样
backtrack(3)[3,3]
=> backtrack(3)[3]
=> undefined[3]
因此便有了,TypeError: Cannot set properties of undefined (setting '3')
结论
JavaScript引擎会使用一个叫做自动分号插入(Automatic Semicolon Insertion,ASI)的机制,在代码解析时在某些地方自动插入分号。 JavaScript引擎试图在这两行代码之间插入一个分号,但是由于数组解构赋值的语法,它误解了这两行代码,导致了TypeError。
参考资料:
-
JavaScript 不会将每个换行符都视为分号:通常仅当无法解析没有分号的代码时,它才会将换行符视为分号。 因此以 "("、"["、"/"、"+"、"-" 开始的语句,那么它极有可能和前一条语句合在一起解释。 ——《JavaScript:权威指南》第 6 版(David Flanagan,O'Reilly,2011)
-
尤雨溪在JavaScript语句后应该加分号么?中的回答: 至于说 “很难总结什么时候加不加”,其实真的很简单。 真正会导致上下行解析出问题的 token 有 5 个:括号,方括号,正则开头的斜杠,加号,减号。 我还从没见过实际代码中用正则、加号、减号作为行首的情况, 所以总结下来就是一句话:一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。其实即使是这两种情况,在实际代码中也颇为少见。
转载自:https://juejin.cn/post/7375864123950219279