【问题标题】:Typescript : How to display properties of a class with a default getterTypescript:如何使用默认 getter 显示类的属性
【发布时间】:2020-12-12 19:24:44
【问题描述】:

我有一个接口和一个类如下

export interface ISample {
  propA: string;
  propB: string;
}

export class Sample {
  
  private props = {} as ISample;

  public get propA(): string {
    return this.props.propA;
  }

  public set propA(propA: string) {
    this.props.propA = propA;
  }

  public get propB(): string {
    return this.props.propB;
  }

  public set propB(propB: string) {
    this.props.propB = propB;
  }

}

在我的代码中,我使用类来初始化对象,如下所示。

let sample = new Sample();
sample.propA = 'A';
sample.propB = 'B';

但是当我尝试使用console.log(sample) 打印对象时,我得到了

props: {propsA: "A", propsB: "B"}
propsA: (...)
propsB: (...)

当我使用console.log(sample) 时,如何让输出仅显示{propsA: "A", propsB: "B"}

PS:我正在使用typescript 3.8.3Angular 9

【问题讨论】:

    标签: javascript angular typescript getter-setter


    【解决方案1】:

    您的类Sample 有一个名为sample 的类属性,它继承ISample。那就是说很明显你得到了props: { propA: "A", propB: "B"}的日志。

    如果您希望propApropB 成为您的类的直接元素,您必须正确继承接口。这样做,您必须将propApropB 设置为Sample 的直接元素,这会导致您想要的日志。

    export class Sample implements ISample {
      propsA = '';
      propsB = '';
    }
    

    请记住,只要您使用 private 状态,就必须相应地调整您的 setter 和 getter。

    【讨论】:

      【解决方案2】:

      您可以覆盖 toString() 方法:

      export interface ISample {
        propA: string;
        propB: string;
      }
      
      export class Sample {
        
        props = {} as ISample;
      
        public get propA(): string {
          return this.props.propA;
        }
      
        public set propA(propA: string) {
          this.props.propA = propA;
        }
      
        public get propB(): string {
          return this.props.propB;
        }
      
        public set propB(propB: string) {
          this.props.propB = propB;
        }
      
        toString() {
          return this.props;
        }
      }
      
      let sample = new Sample();
      sample.propA = 'A';
      sample.propB = 'B';
      
      console.log(sample.props)
      

      【讨论】:

        【解决方案3】:

        看到您希望直接使用属性而不需要任何类对象实例,您可以完全跳过Sample 类。相反,您可以尝试直接使用ISample 接口。

        试试下面的

        export interface ISample {
          propA: string;
          propB: string;
        }
        
        export class AppComponent  {
          sample = {} as ISample;
        
          ngOnInit() {
            this.sample.propA = 'A';
            this.sample.propB = 'B';
        
            // prints {propA: "A", propB: "B"}
            console.log(this.sample);
          }
        }
        

        【讨论】:

        • 完美!我不知道为什么我以前从未想过这个问题。谢谢:)
        【解决方案4】:

        您几乎无法通过console.log 更改类的显示。此功能在浏览器中实现,几乎没有任何操作空间。例如implementation in FF

        function log(aThing) {
          if (aThing === null) {
            return "null\n";
          }
        
          if (aThing === undefined) {
            return "undefined\n";
          }
        
          if (typeof aThing == "object") {
            let reply = "";
            let type = getCtorName(aThing);
            if (type == "Map") {
              reply += "Map\n";
              for (let [key, value] of aThing) {
                reply += logProperty(key, value);
              }
            }
            else if (type == "Set") {
              let i = 0;
              reply += "Set\n";
              for (let value of aThing) {
                reply += logProperty('' + i, value);
                i++;
              }
            }
            else if (type.match("Error$") ||
                     (typeof aThing.name == "string" &&
                      aThing.name.match("NS_ERROR_"))) {
              reply += "  Message: " + aThing + "\n";
              if (aThing.stack) {
                reply += "  Stack:\n";
                var frame = aThing.stack;
                while (frame) {
                  reply += "    " + frame + "\n";
                  frame = frame.caller;
                }
              }
            }
            else if (aThing instanceof Components.interfaces.nsIDOMNode && aThing.tagName) {
              reply += "  " + debugElement(aThing) + "\n";
            }
            else {
              let keys = Object.getOwnPropertyNames(aThing);
              if (keys.length > 0) {
                reply += type + "\n";
                keys.forEach(function(aProp) {
                  reply += logProperty(aProp, aThing[aProp]);
                });
              }
              else {
                reply += type + "\n";
                let root = aThing;
                let logged = [];
                while (root != null) {
                  let properties = Object.keys(root);
                  properties.sort();
                  properties.forEach(function(property) {
                    if (!(property in logged)) {
                      logged[property] = property;
                      reply += logProperty(property, aThing[property]);
                    }
                  });
        
                  root = Object.getPrototypeOf(root);
                  if (root != null) {
                    reply += '  - prototype ' + getCtorName(root) + '\n';
                  }
                }
              }
            }
        
            return reply;
          }
        
          return "  " + aThing.toString() + "\n";
        }
        

        如您所见,对于类实例 (typeof aThing == "object"),它调用 Object.getOwnPropertyNames 并显示每个属性。

        请注意,toString 无济于事 - 它不用于对象(typeof aThing == "object")

        同样,V8ValueStringBuilder.append 在 Chrome 中

        if (value->IsObject() && !value->IsDate() && !value->IsFunction() &&
                !value->IsNativeError() && !value->IsRegExp()) {
            v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
            v8::Local<v8::String> stringValue;
            if (object->ObjectProtoToString(m_context).ToLocal(&stringValue))
                return append(stringValue);
        }
        
        /**
          * Call builtin Object.prototype.toString on this object.
          * This is different from Value::ToString() that may call
          * user-defined toString function. This one does not.
          */
         V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
             Local<Context> context);
        

        另见:Does console.log invokes toString method of an object?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-08-31
          • 2020-08-16
          • 1970-01-01
          • 2018-05-19
          • 1970-01-01
          • 1970-01-01
          • 2016-09-13
          • 2013-01-28
          相关资源
          最近更新 更多