学习Sequelize时关于user对象dataValues属性来源的技术问询
关于Sequelize中
dataValues属性的疑问解答 先来看你提到的这段代码:
const { Strategy } = require('passport-local'); const boom = require('@hapi/boom'); const bcrypt = require('bcrypt'); const UserService = require('./../../../services/user.service'); const service = new UserService(); const LocalStrategy = new Strategy({ usernameField: 'email', passwordField: 'password' }, async (email, password, done) => { try { const user = await service.findByEmail(email); if (!user) { done(boom.unauthorized(), false); } const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) { done(boom.unauthorized(), false); } delete user.dataValues.password; done(null, user); } catch (error) { done(error, false); } } ); module.exports = LocalStrategy;
你的疑问:
我的疑问是:在进行密码对比时使用
bcrypt.compare(password, user.password)即可访问用户密码,但删除密码字段时却需要使用delete user.dataValues.password,请问dataValues属性是从哪里来的?我当前使用的是Sequelize框架。
这是个非常典型的Sequelize模型实例特性问题,我来给你拆解清楚:
dataValues是Sequelize为查询返回的模型实例自动添加的内部属性,它专门用来存储从数据库查询到的原始数据。
为什么会出现你看到的这种访问差异:
- 当你直接访问
user.password时,其实是调用了Sequelize模型实例内置的getter方法。这个getter会自动从dataValues里取出对应的属性值返回给你,所以你不需要显式写dataValues也能拿到密码。 - 但如果直接尝试
delete user.password,是无法真正移除这个字段的——因为模型实例的封装机制会阻止你直接操作实例本身的属性。只有直接操作dataValues这个存储原始数据的对象,才能真正把密码字段从实例的数据源中删除,这样后续把实例传递出去时就不会携带密码了。
另外给你提个更优雅的替代方案:你可以使用Sequelize实例的toJSON()方法,它会自动返回一个剔除了所有Sequelize内部属性的纯JSON对象。如果你的User模型里把password字段设置为隐藏(比如在模型定义时配置{ attributes: { exclude: ['password'] } }),它还会自动过滤掉密码字段,这样就不用手动去删除dataValues里的内容了:
// 替换原来的delete操作 const safeUser = user.toJSON(); done(null, safeUser);
内容的提问来源于stack exchange,提问作者franklin
相关产品推荐
相关产品推荐

