You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB连接回调内给类属性赋值报Cannot set property of undefined错误

报错原因

你遇到的报错本质是普通函数的this指向问题:

  • 你给mongodb.connect()传入的是普通function类型的回调,这类回调的this不会继承外层constructor的作用域指向类实例,在严格模式下默认值为undefined,因此你尝试给this.dbo赋值时就会触发类型错误。
  • 你打印db.db('mydb')可以正常输出,是因为这个值是回调函数的入参衍生的结果,和this指向没有关联,自然不会受影响。

解决方法

下面给出3种常用的可行方案:

方案1:将回调替换为箭头函数(最简便)

箭头函数没有独立的this,会自动继承外层作用域的this指向,也就是类的实例对象,修改后代码如下:

class Database {
    constructor() {
        this.db_url = "mongodb://127.0.0.1:27017/";
        let mongodb = require("mongodb").MongoClient;
        // 把普通function改为箭头函数
        mongodb.connect(this.db_url, { useUnifiedTopology: true }, (err, db) => {
            if (err) throw err;
            this.dbo = db.db('mydb');
        })
    }
}

方案2:提前缓存this指向

在构造函数顶部提前把类实例的this存为一个临时变量,回调里直接用这个变量操作属性即可:

class Database {
    constructor() {
        // 提前缓存this指向
        const _this = this;
        this.db_url = "mongodb://127.0.0.1:27017/";
        let mongodb = require("mongodb").MongoClient;
        mongodb.connect(this.db_url, { useUnifiedTopology: true }, function(err, db) {
            if (err) throw err;
            // 用缓存的_this赋值
            _this.dbo = db.db('mydb');
        })
    }
}

方案3:用bind绑定this指向

通过Function.prototype.bind()手动把回调函数的this绑定为类实例:

class Database {
    constructor() {
        this.db_url = "mongodb://127.0.0.1:27017/";
        let mongodb = require("mongodb").MongoClient;
        mongodb.connect(this.db_url, { useUnifiedTopology: true }, function(err, db) {
            if (err) throw err;
            this.dbo = db.db('mydb');
        // 绑定this指向当前类实例
        }.bind(this))
    }
}

额外优化建议

目前mongodb官方的Node.js SDK已经支持Promise写法,你可以用async/await替代回调写法,逻辑更清晰也更容易维护,不过注意构造函数不能直接标记为async,你可以选择封装静态初始化方法来实现:

class Database {
    constructor() {
        this.db_url = "mongodb://127.0.0.1:27017/";
        this.mongodb = require("mongodb").MongoClient;
    }
    // 单独写异步初始化方法
    async init() {
        const db = await this.mongodb.connect(this.db_url, { useUnifiedTopology: true });
        this.dbo = db.db('mydb');
    }
}

// 使用示例
(async () => {
    const db = new Database();
    await db.init();
    // 后续就可以正常使用db.dbo操作数据库
})();

内容的提问来源于stack exchange,提问作者bshanky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 19:27:07