类 vs 对象字面量:字段不可变性、属性只读实现及选型疑问
对象字面量属性设为不可变的方法及Cypress页面对象的类替代疑问解答
一、如何将对象字面量的属性设置为不可变/只读
有几种常用方法可以实现需求:
1. 使用Object.freeze()
这是最直接的方式,它会冻结整个对象,禁止修改、添加、删除属性,同时也会禁止修改对象的原型。需要注意的是这是浅冻结,如果对象包含嵌套对象,嵌套部分仍可修改。
示例代码:
export const Page = Object.freeze({ email: 'input[type=email]', password: 'input[type=password]', fillLoginCredentials() { cy.get(this.email).type('email'); cy.get(this.password).type('password'); } }); // 尝试修改会失败(严格模式下抛出错误,非严格模式下静默失败) Page.email = 'new-selector'; // 无效
2. 使用Object.defineProperty()逐个配置属性
可以针对单个属性设置writable: false和configurable: false,让属性无法被修改或重新定义。这种方式可以更精细地控制哪些属性不可变。
示例代码:
export const Page = {}; Object.defineProperty(Page, 'email', { value: 'input[type=email]', writable: false, configurable: false, enumerable: true // 保证属性能被遍历到 }); Object.defineProperty(Page, 'password', { value: 'input[type=password]', writable: false, configurable: false, enumerable: true }); Page.fillLoginCredentials = function() { cy.get(this.email).type('email'); cy.get(this.password).type('password'); }; // 尝试修改email会失败 Page.email = 'new-selector'; // 无效
3. 使用Proxy拦截修改操作
通过Proxy可以拦截对象的属性赋值操作,实现自定义的不可变逻辑(比如抛出错误提示),灵活性更高。
示例代码:
const basePage = { email: 'input[type=email]', password: 'input[type=password]', fillLoginCredentials() { cy.get(this.email).type('email'); cy.get(this.password).type('password'); } }; export const Page = new Proxy(basePage, { set(target, prop, value) { throw new Error(`无法修改只读属性 ${prop}`); }, deleteProperty(target, prop) { throw new Error(`无法删除只读属性 ${prop}`); } }); // 尝试修改会抛出错误 Page.email = 'new-selector'; // Uncaught Error: 无法修改只读属性 email
二、是否必须使用类实现Cypress页面对象?
没有必须使用类的理由,完全可以用对象字面量满足需求,具体选择取决于你的场景:
对象字面量的优势:
- 语法更简洁,不需要通过
new关键字实例化,直接导出单例对象即可,符合Cypress页面对象通常作为单例使用的场景。 - 你提到的“带有简单静态方法”的需求完全可以满足,对象中的方法直接通过
Page.fillLoginCredentials()调用,和类的静态方法用法一致。 - 配合上述不可变处理方法,能轻松实现属性只读的需求。
- 语法更简洁,不需要通过
适合用类的场景:
- 如果你需要创建多个不同实例的页面对象(比如多环境差异化的页面),类的实例化能力更方便。
- 如果你需要通过继承扩展页面对象(比如基础页面类包含通用方法,子页面类继承并添加专属方法),类的继承机制会更合适。
但对于大多数Cypress测试场景,单例的对象字面量已经足够简洁高效,不需要强制使用类。
内容的提问来源于stack exchange,提问作者arena
相关产品推荐
相关产品推荐

