我如何从对象输出中删除函数
本文关键字:删除 函数 输出 对象 | 更新日期: 2023-09-27 17:54:35
我正在学习构造器模式。
为了练习我正在学习的东西,我正在构建一个受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
,当您将对象字符串化时,函数无论如何都会被剥离。