从isEmpty()方法深入理解javascript运算符优先级

前言

在平时的开发中,咱们常常会遇到多种运算符在同一个表达式中出现的状况,尤为是在三元条件判断运算符中。javascript

三元条件判断运算符虽然可让咱们避免写过多的if...else条件判断,但多层三元运算符嵌套,其中又包含其余不一样优先级的运算符时,对于阅读咱们代码的人来讲,简直就是噩梦。java

今天咱们就结合一个现实中常常用到的工具函数 isEmpty() 的实现,来说解一下如何解读复杂的运算符嵌套jquery

isEmpty

isEmpty 是 著名的 loadsh 库提供的一个工具方法,被应用于断定一个javascript 对象是否为空对象。segmentfault

空对象

对于空对象,loadsh 是这么解释的:数组

若是【对象没有本身的可枚举字符串键控属性】,则认为它们是空的,
若是参数、对象、缓冲区、字符串或相似于jquery的集合等【相似数组的值的长度为0】,则认为它们为空。
相似地,若是【映射和集合的大小为0】,则认为它们是空的

isEmpty的实现

isEmpty = function (val) {
    return !(!!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length : true : false);
}

解读

运算符优先级

javascript 的运算符优先级能够参考MDN上的说明,以下图:框架

运算过程解读

咱们再看内部实现代码,其中val为要判断是否为空对象的值:函数

return !(!!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length : true : false);

如今根据运算符优先级一步一步解读运算过程工具

  1. 咱们知道 return 后面应该是一个表达式的值,咱们假定这个值为X,则整个表达式能够看作:
var X = !(...);
return X;
  1. 那么接下来就要先对赋值符号(=)右边的表达式求值,即:
!(...)
  1. 能够看到,这个表达式有两个运算符——逻辑非和括号,按照优先级,括号的优先级高于逻辑非,因此这里逻辑非要等到括号内的内容运算出一个结果,而后才能对这个结果进行逻辑非运算,咱们假定括号内的内容最终运算的结果为Y,则能够写做:
X = !Y
  1. 如今来看一下Y表达式的内容:
Y = !!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length :true :false
  1. 接下来就有点复杂了,按照优先级,按照这些运算符里优先级最高的应该是成员属性访问(.),那应该第一步运算结果是这样:
Y = !!val ? typeof val === 'object' ? (true/false) ? !!(0/1/2/.../N) : !!(0/1/2/.../N) :true :false

​ 由于咱们这里对val的值不必定,因此这里对 Array.isArray(val)Object.keys(val).length 最终的计算结果有多种可能,我用/号隔开了各类可能值,而且将他们放入同一个括号内,若是是正式的计算,咱们传入的val是一个肯定的值,那么这些运算结果也会是一个肯定值,而且也不会有括号。spa

  1. 接下来,逻辑非和typeof运算符的优先级都是16,是剩余运算符中最高的,因此对这两种进行运算,结果以下:
Y = (true/false) ? (string/object/boolean/null/undefined)==='object' ? (true/false) ? (true/false) : (true/false) : true :false

这个地方比较绕,由于!! 会将后面的值强制转换为布尔值,因此最后的结果几乎都是由 truefalse 组成的了。code

  1. 接下来,整个表达式就只剩全等运算符(===)和三元条件运算符(... ? ... : ...)了, 从上表可知,全等运算符的优先级要高一点,因此结果以下:
Y = (true/false) ?(true/false) ? (true/false) ? (true/false) : (true/false) : true :false
  1. 如今,咱们的表达式里就只剩三元条件运算符和布尔值了,问题是这里有多个三元运算符嵌套,咱们该从哪一个开始计算呢? 如今就能够看 结合性 了,咱们发现条件运算符的结合性是从右至左,那么咱们的表达式就变成了:
Y = (true/false) ? ... : false

咱们回溯如下这里面的 (true/false) 其实就是原始表达式中 !!val的运算结果,然而这里还没法运算出整个表达式的结果,由于 ... 所表明的那部分还不是一个最终值,还须要运算,记得最开始的作作法吗?对于!(...)这个表达式,咱们将括号内的表达式用Y 来代替了,一样地,咱们把这里 ... 所表明的表达式部分用一个字母M 来表明,即:

M = (true/false) ? (true/false) ? (true/false) : (true/false) : true;
Y = (true/false) ? M : false;
  1. 到这里,计算机就开始判断了:

    • 若是!!val 的值为false ,则直接返回 false (即括号后面的值),后面的M中的表达式就再也不运算了。那么此时 Y=false, 而 !Y 至关于取反,X = !Y 的值就等于true 。咱们这个方法是用来判断是否为空对象的,返回结果为true,就说明这个val 是空对象。
    • 咱们能够延伸一下,符合 !!val === falseval 都有哪些呢? 0""false ,nullundefined 符合这个特征,咱们发发现,它们都是javascript中的‘假值’。
    • 那么若是!!val 的值为 true呢,则须要返回M表达式的结果,咱们就须要继续计算M表达式的值了。
  2. 如今咱们再看M表达式的运算过程,依葫芦画瓢,咱们能够获得:
M = (true/fasle) ? ... : true

经过回溯,咱们能够知道,这里的(true/false) 其实就是原始表达式中的typeof val === 'object' 的最终运算结果。

一样的,咱们将 ... 内的内容使用字母 N 代替,结果以下:

N = (true/fasle) ? (true/fasle) : (true/false)
M = (true/false) ? N : true;
  1. 到这里,计算机又开始判断:

    • 若是typeof val === 'object' 的值为false , 即说明val不是对象类型,则直接返回true(冒号后面的值),不须要再运算N表达式的结果。此时 Y = true, 则 X= !Y=false, 最终值为false ,说明val 不是空对象。
    • 若是typeof val === 'object' 的值为 true 则须要返回N表达式的值做为结果,计算机须要计算运算N表达式的值。
  2. 对于N表达式,其中有三个布尔值,经过回溯,咱们也能够知道他们的原始表达式分别是:
  • Array.isArray(val)
  • !!val.length
  • !!Object.keys(val).length

那么咱们知道,这一步当val 为对象类型时,则须要判断它是数组仍是非数组:

  • 若是是数组,则拿到数组的长度值,对长度值作!!操做

    • 若是长度为0 ,则操做结果为false, 返回后,Y=false,X=!Y=true,说明 长度为0的数组为空对象
    • 其它长度结果为 true,将结果返回后,Y=true, X=!Y=false,说明长度大于0的数组不属于空对象
  • 若是不是数组,则取它的可枚举属性的长度(Object.keys(val).length),并对长度作!! 操做

    • 若是长度为0 ,则操做结果为false, 返回后,Y=false,X=!Y=true,说明 可枚举属性长度(个数)为0的对象为空对象
    • 其它长度结果为 true,将结果返回后,Y=true, X=!Y=false,说明可枚举属性长度大于0的对象不属于空对象

总结

至此,咱们按照程序执行的顺序步进似的完成了整个运算过程的模拟,咱们学到了如下几点:

  • 代换法。当表达式很是复杂时,能够按照运算符优先级,使用变量代换法代换优先级比较低的运算,先将注意力集中到优先级比较高的运算上。
  • 回溯法。步进代换和运算到最后,再无可代换运算时,就要开始回溯,对应到原始表达式,一步步求解。
  • 结合性。之前咱们偏重运算符优先级的分析,从这个例子的条件运算符三层嵌套的应用,咱们看到,在复杂表达式的分析中,运算符的结合性也是很是重要的分辨运算顺序的参照标准。

理解运算过程对咱们理解整个程序的实现逻辑和做者的思惟方式相当重要,但愿以上分析过程能够在你们阅读知名框架中大神级代码时对你们有所帮助。

本文由博客一文多发平台 OpenWrite 发布!
相关文章
相关标签/搜索