Skip to content

运算符

大数运算

js
const START = 2 ^ 53
const END = START + 100

for (let i = START; i < END; i++) {
  console.log(i)
}

上述会循环多少次?

无法预测,或者不好计算

因为 JS 是使用的双精度浮点数存储数字的,其最大值就是 2 ^ 53 - 1, 如果超过这个就会产生精度丢失,从而不好判断究竟是多少

a == 1 && a == 2 && a == 3

如何使上述表达式成立

  1. 借助于 toString
js
const a = {
  n: 1,
  toString: function () {
    return a.n++
  },
}
if (a == 1 && a == 2 && a == 3) {
  console.log("true")
}

对象有 toString()valueOf()两个方法,

  • toString()将该对象的原始值以字符串的形式返回,
  • valueOf() 返回最适合该对象的原始值

这两个方法一般是交由 JS 去隐式调用,以满足不同的运算情况。

在数值运算里,会优先调用 valueOf(),在字符串运算里,会优先调用 toString()。

  1. 用运算符对对象进行转换的时候 valueOf()的优先级高于 toString()

  2. 对对象进行强字符串转换时会优先调用 toString()

  3. toString()方法不能对 null 和 undefined 进行字符串转换,可以用 String()方法代替

  4. 借助于 Symbol.toPrimitive

js
const a = {
  n: 1,
  [Symbol.toPrimitive]() {
    return this.n++
  },
}
if (a == 1 && a == 2 && a == 3) {
  console.log("true")
}

Symbol.toPrimitive 是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。

Symbol.toPrimitive 属性可以将对象转换为相应的原始值。很多内置操作都会尝试将值将对象转换为原始值,包括字符串、数值和未指定的原始类型。

  1. Symbol.toPrimitive 的优先级高于 toString
  2. 相似的还有 Symbol.iterator实现对象的遍历操作

对象属性名

js
const a = {}
const b = { key: 123 }
const c = { key: 456 }

a[b] = 123
a[c] = 456

console.log(a[b])

结果是什么

456

在 JS 中获取对象属性值的时候是默认转换成字符串类型的,所以上述问题 a[b] = 123的时候其实际结果为

a[ b.toString() ] = 啥

如果没有重写 b 的 toString()方法,那么其默认值就是 "[Object String]" 字符串 (这也是我们判断数据类型用的核心方法),所以对于上述问题其核心就是 a["[Object String]"] = 123 ; a["[Object String]"] = 123 ; console.log(a["[Object String]"]) ,结果就是a[c]覆盖了a[b]456

js
const a = {}
a["1"] = 123
a[1] = 456
console.log(a["1"]) //结果为 456