如何实现add[1][2][3] + 4 = 10?

110 阅读1分钟

问题

如何实现以下方法

add[1][2][3] + 4 = 10
add[10][20] + 70 = 100

实现

function addSum() {
  let sum = 0;

  //拦截器
  const handler = {
    get(target, propertry) {
      if (typeof propertry === "symbol") {
        if (propertry === Symbol.toPrimitive) {
          return () => sum;
        }
      }

      sum += Number(propertry);
      return new Proxy({}, handler);
    },
    valueOf() {
      return sum;
    },
  };

  return new Proxy({}, handler);
}

const add = addSum();
const r1 = add[1][2][3] + 4; // 10
console.log(r1);

疑问点

  1. typeof propertry === "symbol" 是为什么?
  2. propertry === Symbol.toPrimitive是为什么?

定义

在 JavaScript 中,当你对一个对象进行运算或尝试将其转换原始值(如字符串或数字)时,JavaScript 引擎会尝试调用该对象的 Symbol.toPrimitive 方法,以确定该对象应该如何被转换

  • 转换过程
    1. 检查是否有 Symbol.toPrimitive 方法:
      • 如果对象实现了 Symbol.toPrimitive 方法,JavaScript 会调用这个方法来获取原始值
    2. 如果没有 Symbol.toPrimitive,则调用 valueOf
      • 如果对象没有 Symbol.toPrimitive,JavaScript 会调用 valueOf 方法。如果 valueOf 返回一个原始值(例如数字或字符串),JavaScript 就使用这个值。
    3. 如果 valueOf 也没有返回原始值,则调用 toString
      • 如果 valueOf 返回的仍然是一个对象,那么 JavaScript 会尝试调用 toString 方法,将对象转换为字符串。

解析

执行顺序
// 第一轮 add[1]
//  property: 1
//  type property: number
//  sum: 1

// 第二轮 add[1][2]
// property: 1
// type property: number
// sum: 3

// 第三轮 add[1][2][3]
// property: 3
// type property: number
// sum: 6

// 第四轮 add[1][2][3] + 4
// 符合定义: 一个对象进行运算或尝试将其转换为原始值时,JavaScript 引擎会尝试调用该对象的 Symbol.toPrimitive 方法
// property: Symbol.toPrimitive
// type property: Symbol
// propertry === Symbol.toPrimitive 成立
// 返回sum: 6
// 执行加法运算
// 6 + 4 = 10