如何扩展Node.js的Field类添加自定义静态字段?
扩展第三方库静态嵌套类添加自定义字段的问题
现有代码结构
第三方库中的Field类
class Field { apiName; /** * Creates an instance of Field with the given parameters * @param {String} apiName A String representing the apiName */ constructor(apiName){ if((apiName != null) && (!(Object.prototype.toString.call(apiName) == "[object String]"))) { throw new SDKException(Constants.DATA_TYPE_ERROR, "KEY: apiName EXPECTED TYPE: String", null, null); } this.apiName = apiName; } /** * The method to get the apiName * @returns {String} A String representing the apiName */ getAPIName() { return this.apiName; } static Contacts = class { static FIRST_NAME = new Field("First_Name"); static LAST_NAME = new Field("Last_Name"); static LEAD_SOURCE = new Field("Lead_Source"); static EMAIL = new Field("Email"); // ... 其他标准字段 } } module.exports = { MasterModel : Field, Field : Field }
业务代码中的使用方式
const RecordField = require(`${SDK_API}/record/field`).Field; const ZCRMRecord = require(`${SDK_API}/record/record`).MasterModel; const updateRecord = async(query) => { const record = new ZCRMRecord(); let Field = RecordField.Contacts; record.addFieldValue(Field.FIRST_NAME, query.firstname); record.addFieldValue(Field.LAST_NAME, query.lastname); // ... 其他字段赋值 record.addKeyValue(`Email`, query.email); // 后续处理逻辑 }
问题说明
第三方库仅提供标准字段的定义,但数据库中存在大量自定义字段。直接修改node_modules里的Contacts静态类添加自定义字段(如下)可以正常使用,但这种方式不可持续:
// 自定义字段示例 static APP_EMAIL = new Field("App_Email"); static MOBILE_SESSIONS = new Field("Mobile_Sessions");
添加后就能在业务代码中正常调用:
if (query.mobilesessions) { record.addFieldValue(Field.MOBILE_SESSIONS, query.mobilesessions); }
尝试通过扩展类实现自定义字段时,编写了如下代码:
const { SDK_API } = require(`../../config`); const ProductField = require(`${SDK_API}/record/field`).Field; let Field = RecordField.Contacts; // 此处RecordField未定义,是错误根源之一 class MyProductField extends ProductField.Contacts { static NUMBER_OF_GROUPS = new Field("Number_of_Groups"); } module.exports = { MyProductField };
运行时抛出错误:Uncaught ReferenceError ReferenceError: Field is not defined,需要理论性的解决方案。
理论性解决方案
方案1:直接扩展静态类的属性
不需要继承嵌套类,直接在原有Contacts类上添加静态属性,这是最简单的实现方式:
const RecordField = require(`${SDK_API}/record/field`).Field; // 给Contacts类添加自定义静态字段 RecordField.Contacts.APP_EMAIL = new RecordField("App_Email"); RecordField.Contacts.MOBILE_SESSIONS = new RecordField("Mobile_Sessions"); RecordField.Contacts.NUMBER_OF_GROUPS = new RecordField("Number_of_Groups"); // 业务代码中直接使用 const updateRecord = async(query) => { const record = new ZCRMRecord(); let Field = RecordField.Contacts; // 既可以用标准字段,也可以用自定义字段 if (query.mobilesessions) { record.addFieldValue(Field.MOBILE_SESSIONS, query.mobilesessions); } }
原理:JavaScript中静态类的属性是可修改的,直接给RecordField.Contacts添加静态属性,相当于在原有类上扩展,避免了类继承带来的作用域问题。
方案2:创建包含自定义字段的新对象,合并原有字段
如果不想修改原类结构,可以创建新对象,合并原有Contacts的字段和自定义字段:
const RecordField = require(`${SDK_API}/record/field`).Field; // 自定义字段集合 const CustomContactsFields = { APP_EMAIL: new RecordField("App_Email"), MOBILE_SESSIONS: new RecordField("Mobile_Sessions"), NUMBER_OF_GROUPS: new RecordField("Number_of_Groups") }; // 合并原有字段和自定义字段 const ExtendedContacts = { ...RecordField.Contacts, ...CustomContactsFields }; // 业务代码中使用ExtendedContacts const updateRecord = async(query) => { const record = new ZCRMRecord(); record.addFieldValue(ExtendedContacts.FIRST_NAME, query.firstname); if (query.mobilesessions) { record.addFieldValue(ExtendedContacts.MOBILE_SESSIONS, query.mobilesessions); } }
原理:利用对象展开运算符,将原有静态字段和自定义字段合并成新对象,既保留原有功能,又添加自定义字段,同时不会修改原类。
方案3:正确继承嵌套类(修复原错误)
如果一定要用类继承的方式,需要修正原代码中的作用域问题:
const { SDK_API } = require(`../../config`); const RecordField = require(`${SDK_API}/record/field`).Field; class MyContacts extends RecordField.Contacts { // 使用外层的RecordField(原始Field类)创建实例,而非未定义的Field变量 static NUMBER_OF_GROUPS = new RecordField("Number_of_Groups"); static APP_EMAIL = new RecordField("App_Email"); } module.exports = { MyContacts };
原理:原错误是因为Field变量未正确定义,且静态属性中需要使用外层的RecordField来创建新的Field实例。继承后,MyContacts会自动包含父类RecordField.Contacts的所有静态字段,同时添加自定义静态字段。
方案对比
- 方案1:最简单直接,适合大多数场景,无需额外封装,直接扩展原类。
- 方案2:不修改原类,适合需要保持原类纯净的场景,通过合并对象实现。
- 方案3:适合需要严格类结构的场景,通过继承实现,但需注意作用域问题。
内容的提问来源于stack exchange,提问作者monkey
相关产品推荐
相关产品推荐

