为何Node.js导出的构造函数需先赋值才能用new实例化对象?
为什么必须先赋值
require('rss')才能用new实例化? 这事儿核心在于npm包的导出方式,以及你可能碰到的CommonJS与ES模块的兼容坑,我给你拆解清楚:
情况1:包直接导出构造函数(理论上可以直接new)
如果rss包的内部代码是这么写的:
// rss包的核心文件 function RSS(options) { this.title = options.title; // 其他构造逻辑 } // 直接把构造函数作为模块导出 module.exports = RSS;
那你其实完全可以不用赋值,直接链式调用:
const feed = new require('rss')({ title: '我的博客' });
但你觉得不能直接用,大概率是碰到了第二种更常见的情况。
情况2:包导出的是包含构造函数的对象(ES模块转CommonJS的锅)
现在很多npm包用ES模块语法编写(比如export default RSS),然后通过打包工具转成CommonJS格式发布。这时候ES模块的默认导出会被转成module.exports.default = RSS,也就是说你require('rss')拿到的是一个对象,而不是构造函数本身:
// 转成CommonJS后的导出结构 module.exports = { default: RSS, // 可能还有其他导出的工具函数 };
这时候你直接new require('rss')()就相当于在new一个普通对象,自然会报错。这时候必须先把构造函数从对象里取出来——不管是先赋值给变量,还是直接链式访问:
// 更易读的写法(推荐) const RSS = require('rss').default; const feed = new RSS({ title: '我的博客' }); // 也可以直接链式调用(不推荐,可读性差) const feed = new require('rss').default({ title: '我的博客' });
为什么先赋值是更好的选择?
哪怕包直接导出构造函数,先赋值给变量(比如const RSS = require('rss'))也有两个好处:
- 可读性更强:一眼就能看出
RSS是个构造函数,new require('rss')()这种写法太生硬,后续维护的人得反应一下才懂。 - 兼容性更好:如果后续包的导出方式变了(比如从直接导出改成默认导出),你只需要改一行代码加个
.default,不用到处找链式调用的地方。
内容的提问来源于stack exchange,提问作者Thorsten
相关产品推荐
相关产品推荐

