经常有朋友邮件过来咨询技术问题,本人不才经常不是忘记回复就是回复的比较迟。原因是一来本人比较懒(或者可以托词为忙),二来是怕「误人子弟」。
当回复这位仁兄的邮件时,不觉得就发现回复的字数越来越长,于是就将其整理为篇 Blog。我的意图是不仅仅帮忙解决问题,而且能提供个解决类似问题的思路。
邮件原文
来自: Captain
时间: 2010-02-28 20:41
话题: 新手虚心求教
你好,我是刚刚入门学习Javascript的新手。我想向你请教一下我在学习过程中所
遇到的一个问题。恕我愚昧,但是我一直无法理解,恳请赐教。
我在学习中碰到过一条这样的声明: var !myVariable != variableValue, 因为在
以前的学习中知道双重否定等于可定,那这则声明是否可以理解成 var myVariable =
variableValue ?
若非如此解释,恳求正解。冒昧打扰请多多包涵。
我的回复
不好意思,收到你的来信到现在才回复。第一眼看见您提供的代码,个人觉得它不合乎语法规则
var !myVariable != variableValue
根据 ECMA 相关的文档,var 关键字的定义在 12.2 章节(我看的是第五版),它的语法定义是:
var VariableDeclarationList ;
而 VariableDeclarationList 包括
VariableDeclarationList , VariableDeclaration
上述两个定义又包含多种情况,说起来有些复杂,所以我画了张草图(可能不准确,以文档为准):
所以,上面的表达式不符合 var 语句的定义要求,因此 Javascript 解析器会报语法错误。
如果是非赋值定义语句,也就是
!myVariable != variableValue
那么就是个条件判断语句,其中有两个条件判断操作符「非(!)」以及「不等于(!=)」,那么我们就要了解它们的结合优先级。
根据相关的参考文档 ,我们可以得知「非」操作符的优先级比「不等于」要高,因此语句先计算 !myVariable 这块,然后再计算「不等于」后的值。
至于能否改成其他等同的逻辑情况,这里还有个问题就是 值取「非」的时候会有多种情况 ,这里有个讨论:
明城:
问: !a != b 是否等于 b == !!a
崇厚:
这个还要看数据类型吧?
比较运算符的优先级是最低的
渔隐:
照这样推理就是a == b 了
崇厚:
a = ''
b = 0
console.log(!a != b)
console.log(b == !!a)
true true
明城:
关键还有个「非」操作符,所以 B 始终是和布尔值对比的
崇厚:
我试出来三个结果
t t
t f
f f
痴灵:
var a = 0;
console.log(!a);console.log(typeof(!a),typeof(a));
true boolean number
类型发生了变化了
渔隐:
用!== 和===吧
明城:
不纠结了,以后记得逻辑表达式里千万不要加一元操作符
或者加括号
沉鱼:
有个比较有效的做法,不太记得操作符的优先级时,我都
加(),这样虽然比较挫,不过保险
崇厚:
不管记得不记得优先级,表达式比较复杂时最好都加括号
这样看起来清晰一些
举一反三,以后如果再碰到类似的问题,我们可以:
- 查文档。 ECMAScript 规范 、 MDC 中的文档 、甚至 Google 都是我们的好帮手
- 如果还是无法理解,可以「偷懒」先看运行结果,然后逆向推断
- 团队的力量胜过一个人闭门造车
-- EOF --