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

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

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就报错,这是真的折磨哈哈哈哈哈哈

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

相关推荐
卡布鲁1 个月前
Promise深入理解:探索相关高级用法
javascript·ecmascript 6
小Bk4 个月前
“键值对大逃亡:Object.entries如何带领它们奔向数组自由”
前端·vue.js·ecmascript 6
要多努力才算好啊4 个月前
ES6标准入门 - Reflect
前端·ecmascript 6
睡着学5 个月前
ES6数据结构深度解析:Set, Map, WeakSet 和 WeakMap
前端·javascript·ecmascript 6
coding消烦员5 个月前
面试官:你知道 ES6 的 生成器 Generator 吗?小明:说起 Generator,还得从我上次去餐馆点餐开始说起
前端·javascript·ecmascript 6
睡着学6 个月前
干货满满:数据类型判断(4种方法)、call的底层逻辑和Object.prototype调用toString方法时的步骤
前端·javascript·ecmascript 6
eiko莉6 个月前
this指向谁,只需记住这几条绑定规则
javascript·面试·ecmascript 6
笨笨狗吞噬者7 个月前
前端实现千位分隔符并保留指定小数位
javascript·typescript·ecmascript 6
大家的林语冰7 个月前
Promise 可视化:幕后机制和执行过程
前端·javascript·ecmascript 6
小帅不太帅8 个月前
面试官:说说call、apply、bind是如何改变this的
javascript·面试·ecmascript 6