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

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

js 复制代码
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规范,但对不起,我英语太差了,我就连在哪都没找到。

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

大概是这样的操作

js 复制代码
let a = xxx

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

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

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

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

相当于把一个语句拆开了

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

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

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

js 复制代码
    let index = Math.floor(Math.random() * i)[arr[i-1], arr[index]] = [arr[index], arr[i-1]]

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

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

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

最后附上修改后的代码

js 复制代码
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就报错,这是真的折磨哈哈哈哈哈哈

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

相关推荐
kyriewen6 天前
可选链 `?.`——再也不用写一长串 `&&` 了!
前端·javascript·ecmascript 6
前端那点事9 天前
23种Promise高效用法,彻底搞定前端异步痛点,新手也能秒上手
ecmascript 6
前端那点事10 天前
ES6模块化保姆级教程,彻底告别全局污染,新手也能秒上手
ecmascript 6
前端那点事10 天前
ES6 40个数组方法保姆级拆解
ecmascript 6
前端那点事10 天前
救命!ES6入门到精通,前端小白也能秒上手
ecmascript 6
kyriewen1 个月前
JavaScript 继承的七种姿势:从“原型链”到“class”的进化史
前端·javascript·ecmascript 6
kyriewen1 个月前
原型与原型链:JavaScript 的“家族关系”大揭秘
前端·javascript·ecmascript 6
kyriewen1 个月前
闭包:那个“赖着不走”的家伙,到底有什么用?
前端·javascript·ecmascript 6
kyriewen1 个月前
作用域与作用域链:JS 的“找东西”逻辑,闭包到底是个啥?
前端·javascript·ecmascript 6
kyriewen1 个月前
JavaScript 数据类型全家福:谁是大哥大,谁是小透明?
前端·javascript·ecmascript 6