注册
web

关于解构赋值的一些意想不到的坑

今天群里有个人问了一个问题,问我们为什么报错,代码如下


var arr = [1,2,3,4,5,6,7,8,9,10]
for(let i = arr.length; i > 0; i--) {
let index = Math.floor(Math.random() * i)
// console.log(i, index);
[arr[i-1], arr[index]] = [arr[index], arr[i-1]]
// ReferenceError: Cannot access 'index' before initialization
}
console.log(arr)

我乍一看,这能报错?不应该啊,怎么能呢,于是我特意复制下来跑了一下,嘿,还真是


关于ReferenceError: Cannot access 'xxx' before initialization的报错,往往和暂时性死区有关,但我看了看顺序,是先定义的index啊,没有错。


抱着求知的心态,上网查了一些文章,都没有提到这种问题,于是只能去看ecma规范,但对不起,我英语太差了,我就连在哪都没找到。


后来我想起自己曾经遇到过类似的问题,只不过是在解构对象的时候遇到的


大概是这样的操作


let a = xxx

({
a: this.options.a,
b: this.options.b,
......
} = /*一个对象*/ ?? {})

当时也报了错,我就想起来了



js中是允许语句不使用;结尾的,许多小伙伴可能养成了这个习惯,虽然不写分号有时候确实很爽很轻松,也是一些企业的规范,但是等到流泪的时候可就知道惨了。



只需要将上述结构赋值的代码的前面一个语句加上分号,就可以解决这个问题


相当于把一个语句拆开了


什么?你问我怎么就成同一个语句了?


我没记错的话,js在执行的时候是会忽略换行符的吧,或者说这个换行符没那么重要,所以我们平时看到的很多库打包出来的min.js文件都是只有一行的然后通过分号分割语句。


如果把上述代码换行内容忽视掉,就变成了这个样子,只放了部分代码


    let index = Math.floor(Math.random() * i)[arr[i-1], arr[index]] = [arr[index], arr[i-1]]

这不报错谁报错啊,根据等号从右到左的运算顺序,不就是访问了暂时性死区嘛


所以加上分号,问题就引刃而解了。


想当年因为先学c++和java的缘故,总是养成写分号的习惯,在切图仔里面似乎成为了一个异类,现在知道了吧,养成写分号的好习惯啊,呜呜呜呜


最后附上修改后的代码


var arr = [1,2,3,4,5,6,7,8,9,10]
for(let i = arr.length; i > 0; i--) {
let index = Math.floor(Math.random() * i);
// console.log(i, index);
[arr[i-1], arr[index]] = [arr[index], arr[i-1]]
// ReferenceError: Cannot access 'index' before initialization
}
console.log(arr)

更好笑的是,这哥们明显是想通过console测试一下的,结果他发现console就不报错,不console就报错,这是真的折磨哈哈哈哈哈哈


养成语句加分号的好习惯!!
从你我做起!


作者:笑心
来源:juejin.cn/post/7311681326712995903

0 个评论

要回复文章请先登录注册