我如何从对象输出中删除函数

How do I remove functions from object output?

本文关键字:删除 函数 输出 对象      更新时间:2023-09-26

我正在学习构造器模式

为了练习我正在学习的东西,我正在构建一个受Mongoose API启发的名为Book的内存模型:

var assert = require("assert");
var Book = (function() {
    var books = [];
    var constructor = function(title, author, genre) {
        assert.ok(title, "title cannot be undefined");
        assert.ok(author, "author cannot be undefined");
        assert.ok(genre, "genre cannot be undefined");
        this.title = title;
        this.author = author;
        this.genre = genre;
        this.save = function() {
            books.push(this);
        };
        this.description = this.title + "is a " + this.genre + " by " + this.author;
    };
    constructor.find = function() {
        return books;
    };
    return constructor;
}());

使用这个模型,我可以创建Book实例并将它们save到内存中存储:

var book = new Book("The Great Gatsby", "F. Scott Fitzgerald", "Novel");
book.save();
var books = Book.find();
console.log(books);
// [ { title: 'The Great Gatsby',
//    author: 'F. Scott Fitzgerald',
//    genre: 'Novel',
//    save: [Function],
//    description: 'The Great Gatsbyis a Novel by F. Scott Fitzgerald' } ]

我如何从输出中删除函数属性"保存"?我只想显示属性。

我需要知道,因为我想使用Express将book发送到客户端,并且我不想将响应与函数相混淆。

(我来自c#背景,在c#中,我会覆盖System.Object基类中名为ToString的函数,该函数 console.log在内部使用。))

是的,可以重写默认的toString输出:

var Book = (function() {
    var books = [];
    var constructor = function(title, author, genre) {
        assert.ok(title, "title cannot be undefined");
        assert.ok(author, "author cannot be undefined");
        assert.ok(genre, "genre cannot be undefined");
        this.title = title;
        this.author = author;
        this.genre = genre;
        this.save = function() {
            books.push(this);
        };
        this.description = this.title + "is a " + this.genre + " by " + this.author;
    };
    constructor.find = function() {
        return books;
    };
    constructor.prototype.toString = function() {
        return JSON.stringify(this);
    };
    return constructor;
}());

在原型上定义函数:

var Book = (function() {
    var books = [];
    function Book (title, author, genre) {
        assert.ok(title, "title cannot be undefined");
        assert.ok(author, "author cannot be undefined");
        assert.ok(genre, "genre cannot be undefined");
        this.title = title;
        this.author = author;
        this.genre = genre;
        this.description = this.title + "is a " + this.genre + " by " + this.author;
    }
    Book.prototype.save = function () {
        books.push(this);
    };
    Book.find = function () {
        return books;
    };
    return Book;
}());

如果可以的话,我想把这种行为封装在Book构造函数中。

这听起来像是一个奇怪的要求,但如果您确实需要(无论出于什么原因),您可以使用Object.defineProperty来定义函数,而不使其成为可枚举的:

var Book = (function() {
    var books = [];
    function Book (title, author, genre) {
        assert.ok(title, "title cannot be undefined");
        assert.ok(author, "author cannot be undefined");
        assert.ok(genre, "genre cannot be undefined");
        this.title = title;
        this.author = author;
        this.genre = genre;
        this.description = this.title + "is a " + this.genre + " by " + this.author;
        Object.defineProperty(this, 'save', {
            value: function () {
                books.push(this);
            }
        });
    }
    Book.find = function () {
        return books;
    };
    return Book;
}());

简写:

books = JSON.parse(JSON.stringify(books));
console.log(books);

注意:当您使用res.json(book)通过express向客户端传递对象时,JSON.stringify会发生。如果你想要的只是发送对象到客户端,那么你不需要做任何事情,只需要将你的对象传递给res.json([obj|array])

封装对象本身的行为。

var Book = (function() {
    var books = [];
    var constructor = function(title, author, genre) {
        assert.ok(title, "title cannot be undefined");
        assert.ok(author, "author cannot be undefined");
        assert.ok(genre, "genre cannot be undefined");
        this.title = title;
        this.author = author;
        this.genre = genre;
        this.save = function() {
            books.push(this);
        };
        this.description = this.title + "is a " + this.genre + " by " + this.author;
        this.stripFunctions = function () {
          var item = this;
          Object.keys(item).forEach(function (key) {
            if (item.hasOwnProperty(key) && typeof item[key] === 'function') {
              delete item[key];
            }
          });
          return item;
        };
    };
    constructor.find = function() {
        return books;
    };
    return constructor;
}());
books = books.map(function (book) { return book.stripFunctions(); });
console.log(books);

请注意,上面的方法将从对象实例中删除所有函数,这意味着在此之后您将无法再调用它们。

PS -这不是你问题的一部分,但你应该考虑为你的构造函数的原型添加方法,这样你就不会每次创建Book的实例时都创建新的函数。

另外,我要重申一下,如果您使用res.json从express发送对象,那么它会为您调用JSON.stringify,当您将对象字符串化时,函数无论如何都会被剥离。