感觉是一个引擎问题,这个JS报错怎么解释?

const a = {}
a.b = 1;
// 这一行执行没有问题

// 判断一下a是否为空
a && a.c = 1
// 则会报错 SyntaxError: invalid assignment left-hand side
// 大家可以试一下,为什么 && 导致了左侧赋值无效?

a?.c = 1 // 也会报错 SyntaxError: invalid assignment left-hand side
// 这个怎么解释?
阅读 3k
10 个回答

搜一下 js运算符优先级 &&= 优先级高 ,实际为 (a && a.c) = 1

&&的优先级大于赋值=
所以a && a.c = 1先计算了a && a.c得到undefined
然后在将1赋值给undefined这一步时报错


补充
a?.c = 1是一样的问题
当a上存在c属性时?.返回a.c
当a上不存在c属性时?.返回undefined
他们不是变量、对象属性或数组元素,不能进行赋值操作

因为 && 优先级比 =
所以

a && ac.c = 1

会被解释为

false = 1

可以使用()

a && (a.c = 1)

都不用执行, VSCode就报错了:image.png
加上括号VScode不报错, 但执行回报你题目中的错误:
image.png

原因是以为计算顺序:
(a && a.c) = 1中的(a && a.c)根据你的代码得到的值是false
然后就是false = 1, false怎么能赋值呢, 然后就你题目中的错了

(a && a.c) = 1可以这样写 a && (a.c = 1), 这样就是在a不为null时给a添加属性

(js运算符优先级)[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refer...]
&& 比 = 的优先级高,实际上就是 (a && a.c) = 1
相当于给一个布尔值赋值1 就报错了

更新:
来自MDN文档:(可选链运算符)[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refer...]
可选链运算符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。
文档里给了一个例子:
以往我们要访问一个属性的属性,要在保证这个属性所属的属性存在:

let nestedProp = obj.first && obj.first.second;

否则会抛出一个异常
使用可选链运算符就可以解决这个问题了:

let nestedProp = obj.first?.second;

如果obj.first为null/undefined,那么nestedProp会被赋值为undefined而不会抛出异常
回到你的问题,可选链运算符是用来访问对象的属性的的,是不能与赋值操作符一起使用的
你是不是想要在对象 a 存在的情况下为其属性 c 赋值?

if (a) {
  a.c = 1;
}

或者

a && (a.c = 1);

都可以实现这种需求
另外个人强烈建议你遇到运算符或者操作符相关的问题的时候先上MDN文档网站查找一下它们的用法,一些虽然好用但是理解成本比较高的符号用法我认为还不如用最简单粗暴的方法替代,毕竟代码是给人看的。

没有括号的情况先,= 左边有 && 或者 && 右边有 = 都是非法的,语法错误。整个表达式无法被解析。

(a && a.c) = 1
这个里面,&& 的结果是一个值,不是一个可赋值的对象,所以也是错误的。

a && (a.c = 1)
这个倒是可以的。

&运算符优先级是比较高的,a && a.c = 1允许执行顺序为:(a && a.c) = 1, a && a.c 返回的值为undefined, 再接着执行undefined = 1 这一步要注意, undefined = 1进行了隐式转换,即为false = 1, 这时就会报错了;

不过可以执行:a && (a.c = 1)

补充更新:
a?.c对象可选链只能用于获取,不能进行复制. 在者A?.C返回的值是undefined

a && a.c = 1 为什么 && 导致了左侧赋值无效?

因为逻辑与运算符( && )的优先级高于赋值运算符( = ),所以 逻辑与运算符会先执行。

  1. 逻辑与的优先级为 5,赋值运算符的优先级为 2
  2. 逻辑与 &&:对操作数从左到右求值,遇到第一个假值时立即返回;如果所有操作数都是真值,就返回最后一个操作数的值。
  3. 关于真值假值:能够转化为 true 的值叫做真值,能够转化为 false 的值叫做假值。

从左到右运算:
a 真值, a.c 假值,返回 a.c, console.log(a && a.c) 结果是 undefined。

哪怕分步骤,执行 undefined = 1,也会报错,因为 undefined 是只读属性。
严格模式下,禁止给对象的只读属性赋值。

所以,赋值表达式中的左侧无效


更新:a?.c = 1 报错 SyntaxError: invalid assignment left-hand side // 这个怎么解释?

a?.c 返回 undefined,可选链运算符 ?. 的返回结果不能用来赋值

参考:可选链接在赋值的左侧无效 - MDN
推荐问题