el's blog

A noder, FEer. use express, vue...etc

ES6标准之逻辑与的规则
研读ES6标准,正好碰到写Java的同事对于 Js 中逻辑与的疑惑。

前言

最近看到了阮一峰的一篇(读懂 ECMAScript 规格](http://www.ruanyifeng.com/blog/2015/11/ecmascript-specification.html),颇受鼓舞,特此收录一些在ES标准中能给我解惑的知识点。

恰逢写RN的原生同事有下面的问题相问:

1
obj.subObj && obj.subObj.name // 如果subObj存在,则表达式会输出name而非输出一个布尔值,为何?

解答

ES6原版文档

ES6标准在线英文文档地址

12.12.3 Runtime Semantics: Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression

  1. Let lref be the result of evaluating LogicalANDExpression.
  2. Let lval be GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. ReturnIfAbrupt(lbool).
  5. If lbool is false, return lval.
  6. Let rref be the result of evaluating BitwiseORExpression.
  7. Return GetValue(rref).

翻译

  1. 令 lref 为解释执行 LogicalANDExpression 的结果。
  2. 令 lval 为 GetValue(lref)。
  3. 如果 ToBoolean(lval) 为 false,返回 lval。
  4. 令 rref 为解释执行 BitwiseORExpression 的结果。
  5. 返回 GetValue(rref)。

关键在第三部 ,如果 lref 左表达式执行得到的值 lval 不能被当作 false 的时候直接返回 lval,否则就要返回右表达式的执行值 rref 的具体value,而不是 bool 值。

ToBoolean

Argument Type Result
Completion Record If argument is an abrupt completion, return argument. Otherwise return ToBoolean(argument.[[value]])
Undefined Return false.
Null Return false.
Boolean Return argument.
Number Return false if argument is +0, −0, or NaN; otherwise return true.
String Return false if argument is the empty String (its length is zero); otherwise return true.
Symbol Return true.
Object Return true.

可知左表达式如果为 undefeindnullfalse0NaN空字符串 的时候被当作 false。反之为 true,则返回GetValue(rref)

GetValue

  1. ReturnIfAbrupt(V).
  2. If Type(V) is not Reference, return V.
  3. Let base be GetBase(V).
  4. If IsUnresolvableReference(V), throw a ReferenceError exception.
  5. If IsPropertyReference(V), then
    1. If HasPrimitiveBase(V) is true, then
      1. Assert: In this case, base will never be null or undefined.
      2. Let base be ToObject(base).
    2. Return base.[Get], GetThisValue(V)).
  6. Else base must be an Environment Record,
    1. Return base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)) (see 8.1.1).

NOTE: The object that may be created in step 5.a.ii is not accessible outside of the above abstract operation and the ordinary object [[Get]] internal method. An implementation might choose to avoid the actual creation of the object.

第二步谈到如果不是一个引用类型的变量则直接返回这个变量本身,所以 obj.subObj.name 返回的就是 name 属性。

扩展

那么逻辑或也是同理

LogicalORExpression : LogicalORExpression || LogicalANDExpression

  1. Let lref be the result of evaluating LogicalORExpression.
  2. Let lval be GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. ReturnIfAbrupt(lbool).
  5. If lbool is true, return lval.
  6. Let rref be the result of evaluating LogicalANDExpression.
  7. Return GetValue(rref).

只是判断 lval 能被当成 true 的时候则返回 lval 本身,否则返回 GetValue(rref).