盘点那些面试题中的糟粕(一)连续赋值

我们先看题目,求以下代码运行结果:

JavaScript 复制代码
var a = {n:1}; 
var o = a;
a.x = a = {n:2};
console.log(o, a);

连续赋值是C系语言特有的小魔术,多数情况下它无伤大雅,因为每段赋值之间并不互相干涉。

但是一个语句中包含多个副作用,并且让代码结果依赖其执行顺序,这可以说是公认糟糕到不能更糟糕的一种实践了。在古典的C/C++中,标准将它们解释为"未定义行为"。所以在C++社区,研究此类问题往往遭到群体唾弃,毕竟研究未定义行为已经不是在研究语言了。然而很不幸,作为C系语言的小老弟,JavaScript标准大部分写成了伪代码形式,所以确实规定了这类行为的结果。也就是说,这些离谱的行为都切切实实属于JavaScript语言的一部分。

崇拜偏、难、怪,热衷于收集和构造语言难题,并不是一种罕见的现象,甚至可以说是一种人之常情。若这些偏、难、怪语言特性背后包含了思考和权衡,那研究它们自然是一件有意义的事情,若这些特性只是未经设计无意识获得、甚至属于设计失误,那研究它们就不适合作为正式的学习内容了。对这个连续赋值来说,显然属于后者。

如今的JavaScript,语言标准已经近千页,打印出来厚度跟辞典差不多,这样的体量已经远超过大部分人个人学习能力的极限,普通工程师把精力全部放在学习语言特性,甚至是边角特性,是得不偿失的。聚焦于提升用语言特性构筑一个的解决方案的能力,才是工程师提升自己的正确道路。

故此问题的结论是毫无疑问的糟粕。但是若要认真研究这个问题,其研究过程还是有一定意义的。造成这个问题难以理解的本质是运行阶段和语法分析阶段的行为分裂。

大部分同学会下意识地认为,连续赋值a.x = a = {n:2}可以等效于以下结构:

JavaScript 复制代码
a = {n:2}
a.x = a;

或者等效于反过来:

JavaScript 复制代码
a.x = a;
a = {n:2}

但实际上,这两个等效的结论都不对。我们无法把a.x = a = {n:2}拆开成两个语句来得到完全相同的运行结果。这是非常违反直觉的。

要想真正解释这个问题的运行结果,就需要对编译原理有基本的概念和理解。

对于具备编译原理基础的同学,我们可以用两句话来解释JavaScript中的连续赋值现象:

在语法分析阶段,JavaScript的=是一个右结合的运算符。

在运行时,JavaScript始终遵循从左到右计算的规则。

语法上的右结合,意味着 a = {n:2} 是一个整体,它的计算结果会被赋值给 a.x

而运行时从左到右,意味着 a.x 首先被计算,此时 a 仍然是原本的对象,所以赋值发生在原本的 a 对象的 x属性上。

我们回到面试题的话题,讨论一下为什么我认为这样的题目为什么不适合作为面试题?

我认为有以下原因

  1. 与实际工作脱节,绝大多数工程师一生都不会遇到类似代码
  2. 导向错误,以不良实践代码作为考点,诱导候选人工作中追求偏怪代码
  3. 没有区分度,只有会或者不会,没有中间结果,也没有讨论空间,甚至没办法引导候选人思考
  4. 传播广泛,背题者众多,绝大多数能答对的应聘人,都不是靠分析而是靠背答案答对

这些语言的边边角角不失为一种茶余饭后消遣或者有趣的谈资,但若是以此作为面试问题来考核应聘人,则是一种对工作的失责。更严重的,若真把这些代码用于实际开发,那这样的程序员应该遭到立刻辞退。

相关推荐
你怎么知道我是队长3 分钟前
JavaScript的函数介绍
开发语言·前端·javascript
weedsfly7 分钟前
观察者模式 vs 发布-订阅模式:从概念到实战,一次讲清楚
前端·javascript·面试
暗不需求8 分钟前
手写 AJAX:从 XMLHttpRequest 到封装一个简易 axios
前端·面试
嘟嘟071722 分钟前
从零理解远程 MCP:串联三个 MCP Server 打造 AI 自动化工作流
面试
不负岁月无痕25 分钟前
STL -- C++ 红黑树封装 Map 和 Set
java·c语言·开发语言·c++·面试
miss25 分钟前
海康威视 IoT 平台前端实战:视频流、海量设备与实时数据可视化
前端·javascript·物联网
mONESY26 分钟前
MCP 协议实战博客:跨进程、跨语言可复用 AI 工具标准化方案
javascript
糖墨夕1 小时前
第一章:为什么你要学 AI Agent?—— 从"切图仔"到全栈的进化之路
前端·javascript·vue.js
自律懒人1 小时前
ChatGPT Work 上线当天实测:GPT-5.6 Sol 把 Codex 塞进桌面应用,跨应用自动做报表和 PPT,一个指令干 3 小时的活
javascript·开源
不听话坏11 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript