Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js —— 关系运算符(我只列出instanceof和in)和相等运算符 #75

Open
lizhongzhen11 opened this issue Feb 24, 2020 · 0 comments
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Feb 24, 2020

关系运算符(我只列出instanceof和in)相等运算符

instanceof

  1. 定义 lref关系表达式 求值结果
  2. 定义 lval? GetValue(lref)
  3. 定义 rref移位表达式 求值结果
  4. 定义 rval? GetValue(rref)
  5. 返回 ? InstanceofOperators(lval, rval)

本质上是检测 rval 原型链上的原型对象是否在 lval 原型链上。

in

  1. 定义 lref关系表达式 求值结果
  2. 定义 lval? GetValue(lref)
  3. 定义 rref移位表达式 求值结果
  4. 定义 rval? GetValue(rref)
  5. 如果 rval 的类型不是 Object,抛 TypeError 异常
  6. 返回 ? HasProperty(rval, ? ToPropertyKey(lval))

ToPropertyKey 只是为了拿对象的键名,键名要么是Symbol,要么是string类型。

HasProperty 内部会调用 [[HasProperty]] 内置方法,该内置方法会继续调用 OrdinaryHasProperty 内部算法,该算法会查找 原型链 上是否存在该键名。

InstanceofOperator( V, target )

该抽象操作 InstanceofOperator实现了一种通用的算法,该方法通过咨询目标的 @@hasinstance 方法来判断ECMAScript值 V 是对象 target 的实例,如果 目标的 @@hasinstance 存在,判断 target"prototype" 属性值是否在 V 的原型链上。

  1. 如果 target 类型不是对象,抛 TypeError 异常
  2. 定义 instOfHandler? GetMethod(target, @@hasInstance)
  3. 如果 instOfHandler 不是 undefined
    1. 返回 ! ToBoolean(? Call(instOfHandler, target, <<V>>) )
  4. 如果 target 不可调用,抛 TypeError 异常
  5. 返回 ? OrdinaryHasInstance(target, V)

第4和第5步,步骤4和5提供了与ECMAScript以前版本的兼容性,以前版本未使用 @@hasInstance 方法来定义 instanceof 运算符语义。如果对象没有定义或继承 @@hasInstance,那么其将使用默认的 instanceof 语义

==

  1. 定义 lref相等表达式 求值结果
  2. 定义 lval? GetValue(lref)
  3. 定义 rref关系表达式 求值结果
  4. 定义 rval? GetValue(rref)
  5. 返回执行 抽象相等比较 rval == lval 的结果

!=

  1. 前四步与 == 运算符一样
  2. 第5步,定义 r 为执行 抽象相等比较 rval == lval 的结果
  3. 第6步,ReturnIfAbrupt(r)
  4. 第7步,如果 rtrue,返回 false。否则返回 true

===

  1. 前四步与 == 运算符一样
  2. 返回执行 严格相等比较 rval === lval 的结果

!==

  1. 前四步与 == 运算符一样
  2. 第5步,定义 r 为执行 严格相等比较 rval === lval 的结果
  3. 第6步,断言:r 是一个 normal completion
  4. 如果 r.[[Value]]true,返回 false。否则返回 true

注意

  • 字符串比较可以通过:
    `${a}` == `${b}`
  • 数值比较可以通过:+a == +b
  • 布尔比较可以通过:!a == !b
  • A != B 等同于 !(A == B)
  • A == B 等同于 B == A,但按A和B的顺序计算除外。
  • 等式运算符并不总是可传递的。可能有两个不同的 String 对象,两个都有相同的字符串值;每个 String 对象使用 == 运算符时被认为和字符串值相同,但是这两个 String 对象并不等于对方,例如:
    new String("a") == "a" // true
    "a" == new String("a") // true
    // 根据 == 算法,两边类型一致时会返回 === 的结果,所以这里是false
    new String("a") == new String("a") // false

字符串比较对代码单元值的序列使用简单的相等性测试。没有尝试使用更复杂的,面向语义的字符或字符串相等性定义以及Unicode规范中定义的顺序。因此,根据Unicode标准规范定义的相等的字符串值可以测试为不相等。实际上,该算法假定两个字符串都已经处于规范化形式。

2020-07-22 补充

昨晚临近下班时突然想手动实现下 instanceof,毕竟一直在调用人家的API,但是js基础貌似又不熟了,果然,尼玛,写错了,借助浏览器打印的背景下还要18分钟才写出来,真菜!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant