findOne检索到的对象实例没有任何方法



每当我从mongo数据库检索对象时,它没有任何方法,我试图找出(1)原因和(2)解决方案。

综上所述,以下内容概括了这个问题:

(1)我可以创建一个对象和它的方法工作:

const newUser = new User(email, hashedPassword);
console.log(newUser.test); // correct - it’s not undefined

(2)我可以将实例(及其方法)插入数据库(通过saveToDb):

const insertedUser = await collection.insertOne(this);

(3)我可以从数据库(通过findByEmail)检索它:

const user = await collection.findOne({ email });

(4)但是它不再有任何方法了:

if (!user) return; // temporary code
console.log(user); // correctly displays object keys and values
console.log('user.test', user.test); // undefined - why?

为什么会发生这种情况?我读过其他一些关于它的帖子,但他们似乎都使用了mongoose,我没有在我的应用中使用它(也许我应该使用它?)这篇文章没有得到回复,我认为这是一个类似的问题。

如有任何见解,我将不胜感激,谢谢。

如果需要看,这是类:

export class User {
email: string;
hashedPassword: any;
dateCreated: Date;
constructor(email: string, hashedPassword: any) {
this.email = email; // make email.toLowerCase(); 
this.hashedPassword = hashedPassword; 
this.dateCreated = new Date();
}
async saveToDb() {
try {
const collection = getCollection(USERS_COLLECTION_NAME);
const sanitisedEmail = this.email.toLowerCase();
const insertedUser = await collection.insertOne(this);
console.log('THIS HAS BEEN INSERTED TO DB:', this);
console.log('this.test:', this.test); // works
this.test();
const token = jwt.sign(insertedUser, sanitisedEmail, {
expiresIn: 60 * 24,
});
return token;
} catch (err) {
throw err;
}
}
test() {
console.log('test() within class Fn');
return 5;
}
static staticTest() {
console.log('staticTest() within class Fn');
return 6;
}
signToken() {
const token = jwt.sign(this, this.email, {
expiresIn: 60 * 24,
});
return token;
}
static async fetchAll() {
try {
const collection = getCollection(USERS_COLLECTION_NAME);
const users = await collection.find().toArray();  
return users;
} catch (err) {
throw err;
}
}
static async findByEmail(email: string) {
try {
const collection = getCollection(USERS_COLLECTION_NAME);
const user = await collection.findOne({ email });
if (!user) return; // temporary code
console.log('FOUND THIS USER: ', user); // works
console.log('user.test', user.test); // undefined - key problem lies here...
return user;
} catch (err) {
throw err;
}
}
}

通过查询方法(如findOne)返回的对象将是普通对象。它们不是类的实例,因为这些对象被发送并以JSON形式保存在数据库中,并且不包括类信息、原型和方法。

你能做的是,改变你得到的对象的原型。或者更好的做法是,用Object.create创建一个类的新实例,并用Object.assign注入属性:

const user = Object.assign(
Object.create(User.prototype), 
await collection.findOne({ email })
);

现在您的user对象将再次访问原型方法。

为了完整起见,我还将提到另一个选项:

const user = await collection.findOne({ email });
Object.setPrototypeOf(user, User.prototype);

但是请阅读Mozilla贡献者在setPrototypeOf:

上提供的免责声明

改变对象的[[Prototype]],根据现代JavaScript引擎优化属性访问的本质,目前在每个浏览器和JavaScript引擎中都是非常缓慢的操作。此外,改变继承的影响是微妙和广泛的,不仅限于在Object.setPrototypeOf(...)语句中花费的时间,而且可能扩展到可以访问[[Prototype]]被改变的任何对象的任何代码。

相关内容

最新更新