简体   繁体   中英

How can I get console.log to output the getter result instead of the string "[Getter/Setter]"?

In this code:

function Cls() {
    this._id = 0;
    Object.defineProperty(this, 'id', {
        get: function() {
            return this._id;
        },
        set: function(id) {
            this._id = id;
        },
        enumerable: true
    });
};
var obj = new Cls();
obj.id = 123;
console.log(obj);
console.log(obj.id);

I would like to get { _id: 123, id: 123 } but instead I get { _id: 123, id: [Getter/Setter] }

Is there a way to have the getter value be used by the console.log function?

您可以使用console.log(Object.assign({}, obj));

使用console.log(JSON.stringify(obj));

You can define an inspect method on your object, and export the properties you are interested in. See docs here: https://nodejs.org/api/util.html#util_custom_inspection_functions_on_objects

I guess it would look something like:

function Cls() {
    this._id = 0;
    Object.defineProperty(this, 'id', {
        get: function() {
            return this._id;
        },
        set: function(id) {
            this._id = id;
        },
        enumerable: true
    });
};

Cls.prototype.inspect = function(depth, options) {
    return `{ 'id': ${this._id} }`
}

var obj = new Cls();
obj.id = 123;
console.log(obj);
console.log(obj.id);

Since Nodejs v11.5.0 you can set getters: true in the util.inspect options. See here for docs .

getters <boolean> | <string> If set to true, getters are inspected. If set to 'get', only getters without a corresponding setter are inspected. If set to 'set', only getters with a corresponding setter are inspected. This might cause side effects depending on the getter function. Default: false.

I needed a pretty printed object without the getters and setters yet plain JSON produced garbage. For me as the JSON string was just too long after feeding JSON.stringify() a particularly big and nested object. I wanted it to look like and behave like a plain stringified object in the console. So I just parsed it again:

JSON.parse(JSON.stringify(largeObject))

There. If you have a simpler method, let me know.

On Node.js, I suggest using util.inspect.custom , which will allow you to pretty print getters as values, while keeping other properties output unchanged.

It will apply to your specific object only and won't mess the general console.log output.

The main benefit vs Object.assign is that it happens on your object, so you keep the regular generic console.log(object) syntax. You don't have to wrap it with console.log(Object.assign({}, object)) .

Add the following method to your object:

[util.inspect.custom](depth, options) {
    const getters = Object.keys(this);
    /*
        for getters set on prototype, use instead:
        const prototype = Object.getPrototypeOf(this);
        const getters = Object.keys(prototype);
    */
    const properties = getters.map((getter) => [getter, this[getter]]);
    const defined = properties.filter(([, value]) => value !== undefined);
    const plain = Object.fromEntries(defined);
    const object = Object.create(this, Object.getOwnPropertyDescriptors(plain));
    // disable custom after the object has been processed once to avoid infinite looping
    Object.defineProperty(object, util.inspect.custom, {});
    return util.inspect(object, {
        ...options,
        depth: options.depth === null ? null : options.depth - 1,
    });
}

Here is a working example in your context:

const util = require('util');

function Cls() {
    this._id = 0;
    Object.defineProperty(this, 'id', {
        get: function() {
            return this._id;
        },
        set: function(id) {
            this._id = id;
        },
        enumerable: true
    });
    this[util.inspect.custom] = function(depth, options) {
    const getters = Object.keys(this);
    /*
        for getters set on prototype, use instead:
        const prototype = Object.getPrototypeOf(this);
        const getters = Object.keys(prototype);
    */
    const properties = getters.map((getter) => [getter, this[getter]]);
    const defined = properties.filter(([, value]) => value !== undefined);
    const plain = Object.fromEntries(defined);
    const object = Object.create(this, Object.getOwnPropertyDescriptors(plain));
    // disable custom after the object has been processed once to avoid infinite looping
    Object.defineProperty(object, util.inspect.custom, {});
    return util.inspect(object, {
        ...options,
        depth: options.depth === null ? null : options.depth - 1,
    });
}
};
var obj = new Cls();
obj.id = 123;
console.log(obj);
console.log(obj.id);

Output:

Cls { _id: 123, id: 123 }
123

Use spread operator console.log({... obj });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM