【问题标题】:Is there a way to find out what key of an object is trying to be accessed?有没有办法找出试图访问对象的哪个键?
【发布时间】:2021-05-30 18:16:40
【问题描述】:

有没有办法设置一个对象来动态生成键值?比如我想obj.fooconsole.log("foo")obj.barconsole.log("bar")等等?我正在尝试制作一个自定义记录器

let logger = new CustomLogger();
logger.error("404"); // "[ERROR] - 404"
logger.info("user signed up"); // "[INFO] - user signed up"

它不必从一个类中实例化,如果它只是一个普通对象实际上会更好,因为我想为不同的项目导出它。

【问题讨论】:

  • 有没有办法设置一个对象来动态生成键值?”我不明白这与“我正在尝试制作一个自定义记录器,其中 [...]"。为什么记录器需要 dynamic 键?大概您只有少数日志级别(例如,跟踪、信息、警告、错误),所以我不确定动态键的来源。此外“如果它只是一个普通对象实际上会更好,因为我想要为不同的项目导出它。” - 我也不确定这有什么关系。一个简单的模块无论如何都会使其可重用。

标签: javascript node.js


【解决方案1】:

您似乎想要一个记录器,其中键确定(部分)记录的内容。这有点正常,但是这里的方法很糟糕,因为您失去了对 API 的控制。你可以有一个像logger.erro("500") 这样的错字,你的代码会工作,但你的日志现在会显示为[ERRO] - 500。这反过来又会打乱您可能进行的任何日志分析,其中最简单的就是搜索[ERROR]

相反,这里通常的方法是在记录器上设置一个方法,该方法可以获取消息的各个部分,然后统一记录它。在您的情况下,您似乎想要一个前缀和一条消息。然后,您可以使用预定义的前缀部分公开方法。

使用类语法

class CustomLogger {
  log(prefix, msg) {
    console.log(`[${prefix}] - ${msg}`)
  }
  
  trace(msg) {
    this.log("TRACE", msg);
  }
  
  info(msg) {
    this.log("INFO", msg);
  }
  
  warn(msg) {
    this.log("WARN", msg);
  }
  
  error(msg) {
    this.log("ERROR", msg);
  }
}

let logger = new CustomLogger();
logger.error("404"); // "[ERROR] - 404"
logger.info("user signed up"); // "[INFO] - user signed up"

使用对象字面量

let logger = {
  log(prefix, msg) {
    console.log(`[${prefix}] - ${msg}`)
  },
  
  trace(msg) {
    this.log("TRACE", msg);
  },
  
  info(msg) {
    this.log("INFO", msg);
  },
  
  warn(msg) {
    this.log("WARN", msg);
  },
  
  error(msg) {
    this.log("ERROR", msg);
  },
}

logger.error("404"); // "[ERROR] - 404"
logger.info("user signed up"); // "[INFO] - user signed up"

如果上面的代码看起来太多,那么考虑以下:

派生你的方法

使用currying 执行部分应用。

const log = prefix => msg => 
  console.log(`[${level}] - ${msg}`);
  
let logger = {
  trace: log("TRACE"),
  info : log("INFO"),
  warn : log("WARN"),
  error: log("ERROR"),
}

logger.error("404"); // "[ERROR] - 404"
logger.info("user signed up"); // "[INFO] - user signed up"

使用仅公开所需方法的方法可以在需要时更轻松地更改实现。消费代码不需要意识到这一点。考虑您是否真的想要拥有不同的日志级别以及前缀和消息部分。如果你有完全动态的方法,那么你很难做到这一点。当logger.infologger.error 都调用相同的代码时,你将如何区分它们?你可以尝试做一个大的条件链,但你最终要做的是在一个地方实现所有可能的方法。

上面的代码可以这样改变:

const log = level => prefix => msg =>    //take `level`
  console[level](`[${prefix}] - ${msg}`); //use `level`
  
let logger = {
  trace: log("info")("TRACE"),
  info : log("info")("INFO"),
  warn : log("warn")("WARN"),
  error: log("error")("ERROR")
}

logger.error("404"); // "[ERROR] - 404"
logger.info("user signed up"); // "[INFO] - user signed up"

消费代码记录器本身的最小更改。

【讨论】:

    【解决方案2】:

    如果你想从对象中获取密钥,你可以循环如下

    const obj={
      foo:"value for foo",
      bar:"value for bar"
    }
    
    for (const key in obj) {
      console.log(key);
    }

    【讨论】:

      【解决方案3】:

      你可以像这样轻松地做到这一点

      const logger = {
        log: (type, val) => console.log(`[${type}] - ${val}`)
      }
      
      logger.log("Error", "Foo");
      logger.log("Info", "Bar");

      【讨论】:

        【解决方案4】:

        您可以用Proxy 包装对象并打印移交的属性。

        const
            object = { foo: "hello", bar: "everyone" },
            handler = {
                get: function(target, prop, receiver) {
                    console.log(prop, target[prop]);
                    return target[prop];
                }
            },
            proxy = new Proxy(object, handler);
        
        console.log(proxy.foo);

        【讨论】:

          猜你喜欢
          • 2016-03-31
          • 2018-11-08
          • 1970-01-01
          • 1970-01-01
          • 2014-09-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多