Ext JS 4 类体系重构:命名规范、定义方式与调试实战
本文深入解析 Ext JS 4 对类体系的重构,涵盖从底层架构到实际编码的完整指南。重点介绍基于类的编程优势、严格的命名规范(类、方法、文件),以及使用 Ext.define 替代旧版 Ext.extend 的正确方式。通过配置系统(config)、静态成员定义及错误调试技巧,帮助开发者构建可扩展、易维护的 Ext JS 应用。
Ext JS 4 类体系重构概述
Ext JS 4 在底层对类体系进行了彻底重构,这是该框架历史上首次大规模调整。新架构已应用于几乎每个 Ext JS 4 类中,因此在开始编码前充分理解这一机制至关重要。
本手册面向希望创建新类或继承 Ext JS 4 现有类的开发人员,内容分为四个部分:
第一部分为“概述”,阐述构建健壮类体系的必要性。
第二部分为“命名规范”,探讨类、方法、属性、变量及文件命名的最佳实践。
第三部分为“实践”,提供详细的逐步代码示例。
第四部分为“错误处理和调试”,分享处理异常的实用技巧。
一. 概述
Ext JS 4 包含超过 300 个类,拥有超过 200,000 名来自全球不同编程背景的开发者。面对如此庞大的框架,我们面临着一项巨大挑战:提供一套通用的代码体系结构。
该体系结构需友好且易于学习。
同时需支持快速开发、易于调试和简单部署。
此外,代码必须组织良好,具备可扩展性和可维护性。
JavaScript 是一种无类型、基于原型的语言,其最大优势在于灵活性。通过不同编码风格和技巧,可以用多种方式完成同一任务。然而,这种灵活性若缺乏统一结构,会导致代码难以理解、维护和重用。
基于类的编程采用最流行的面向对象(OOP)模型。基于类的语言通常是强类型的,提供封装和标准编码约定。遵循统一的编码规则有助于生成可预测、可扩展和可延伸的代码,但代价是失去了 JavaScript 等语言的动态特性。
每种方法各有优劣,我们能否结合两者的优点并隐藏缺点?答案是肯定的,Ext JS 4 已实现这一解决方案。
二. 命名规范
命名规范详解
在代码中始终使用一致的基于类、命名空间和文件名的命名规范,有助于保持代码的组织性、结构化和可读性。
1) 类
类名仅可包含字母数字字符,数字在大多数情况下不被允许,除非属于技术术语。禁止使用下划线、连字符或其他非字母数字字符。例如:
MyCompany.useful_util.Debug_Toolbar 是不允许的。
MyCompany.util.Base64 是允许的。
类名应通过对象点表达式(.)属性放置到适当的命名空间中。至少,类名应包含一个唯一的顶层命名空间。例如:
MyCompany.data.CoolProxy
MyCompany.Application
顶层命名空间和类名应采用驼峰命名法,其余部分全部小写。例如:
MyCompany.form.action.AutoLoad
非 Sencha 发布的 Ext JS 类不得使用 Ext 作为顶层命名空间。
缩略词也应遵循上述驼峰命名规范。例如:
Ext.data.JsonProxy 优于 Ext.data.JSONProxy
MyCompany.util.HtmlParser 优于 MyCompary.parser.HTMLParser
MyCompany.server.Http 优于 MyCompany.server.HTTP
2) 源文件
类名直接映射到存储它们的文件路径,因此每个文件只能包含一个类。例如:
Ext.util.Observable 存储在 /to/src/Ext/util/Observable.js
Ext.form.action.Submit 存储在 /to/src/Ext/form/action/Submit.js
MyCompany.chart.axis.Numeric 存储在 /to/src/MyCompany/chart/axis/Numeric.js
路径 /to/src 是应用程序类的根目录,所有类都应放置在此共同根目录下。
3) 方法和变量
与类名类似,方法和变量名仅可包含字母数字字符,数字在大多数情况下不被允许,除非属于技术术语。禁止使用下划线、连字符或其他非字母数字字符。
方法和变量名应始终采用驼峰命名法,缩略词亦适用此规则。
示例:
可接受的方法名称:encodeUsingMd5()、getHtml()(优于 getHTML())、getJsonResponse()(优于 getJSONResponse())、parseXmlContent()(优于 parseXMLContent())。
可接受的变量名称:var isGoodName、var base64Encoder、var xmlReader、var httpServer。
4) 属性
类属性名完全遵循上述方法和变量的命名规范,静态常量除外。
静态类属性(即常量)应全部大写,例如:
Ext.MessageBox.YES = "Yes"
Ext.MessageBox.NO = "No"
MyCompany.alien.Math.PI = "4.13"
三. 实践
1. 声明
类定义实践:从旧方法到新语法
1.1) 老的方法
如果您使用过早期版本的 Ext JS,肯定熟悉使用 Ext.extend 创建类的方式:
var MyWindow = Ext.extend(Object, { ... });
这种方法易于创建继承自其他类的新类,但除了直接继承,我们缺乏创建类其他方面(如配置、静态配置和混入类)的良好 API,这些内容将在后文详细回顾。
让我们看另一个例子:
My.cool.Window = Ext.extend(Ext.Window, { ... });
在此示例中,我们希望创建一个新的命名空间类并继承 Ext.Window,这里有两个问题需要解决:
My.cool 必须是已存在的命名空间对象,以便我们将 Window 分配为其属性。
Ext.Window 必须存在且已加载,以便引用它。
第一点通常通过 Ext.namespace(别名 Ext.ns)解决,该方法递归创建不存在的对象。令人烦恼的是,您必须始终记得在 Ext.extend 之前添加它们:
Ext.ns('My.cool');My.cool.Window = Ext.extend(Ext.Window, { ... });
然而第二个问题较难解决,因为 Ext.Window 可能依赖许多其他类,它可能直接或间接继承自那些依赖类,而这些依赖类又依赖于其他类。因此,在 Ext JS 4 之前编写的应用程序通常会引入整个库文件 ext-all.js,尽管可能仅需其中很小一部分。
1.2) 新的方法
Ext JS 4 消除了所有这些缺点,您只需记住创建类的唯一方法是:Ext.define,其基本语法如下:
Ext.define(className, members, onClassCreated);
className:类名
members 是一个大对象,代表类成员的集合,由一系列键值对组成。
onClassCreated 是一个可选回调函数,当类的所有依赖项准备好且类完全创建时被调用。此回调函数在许多情况下很有用,我们将在第四部分深入讨论。
示例:
代码如下:
Ext.define('My.sample.Person',{
name: 'Unknown',
constructor: function(name) {
if (name) {
this.name = name;
}},
eat: function(foodType) {
alert(this.name + " is eating: " + foodType); }});
var aaron = Ext.create('My.sample.Person', 'Aaron');
aaron.eat("Salad"); // alert("Aaron is eating: Salad"); 注意,我们使用 Ext.create() 方法创建 My.sample.Person 的实例。当然也可以使用 new 关键字(new My.sample.Person()),但我们建议养成始终使用 Ext.create 的习惯,因为它可以利用动态加载功能。更多信息请参阅 Ext JS 4 入门指南。
2. 配置
配置系统与静态成员管理
在 Ext JS 4 中,我们引入了专用的 config 属性,它会在类创建前由强大的预处理器类 Ext.Class 处理,具有以下特性:
配置从其他类成员完全封装。
每个 config 属性的 getter 和 setter 方法会在类原型中自动生成,如果类中未定义这些方法。
同时,每个 config 属性也会生成一个 apply 方法,自动生成的 setter 方法会在内部设置值之前调用此 apply 方法。若要在设置值之前运行自定义逻辑,可覆盖此 apply 方法。如果 apply 没有返回值,setter 方法将不会设置值。让我们看看下面的 applyTitle 方法:
下面的例子定义了一个新类:
代码如下:
Ext.define('My.own.Window', { /** @readonly */
isWindow: true,
config: {
title: 'Title Here',
bottomBar: {
enabled: true,
height: 50,
resizable: false } },
constructor: function(config) {
this.initConfig(config); },
applyTitle: function(title) {
if (!Ext.isString(title) || title.length === 0) {
alert('Error: Title must be a valid non-empty string');
} else {
return title;
} },
applyBottomBar: function(bottomBar) {
if (bottomBar && bottomBar.enabled) {
if (!this.bottomBar) {
return Ext.create('My.own.WindowBottomBar', bottomBar);
} else {
this.bottomBar.setConfig(bottomBar);
}
}
}}); 下面是如何使用这个新类的例子:
代码如下:
var myWindow = Ext.create('My.own.Window', {
title: 'Hello World',
bottomBar: {
height: 60 }});
alert(myWindow.getTitle()); // alerts "Hello World"
myWindow.setTitle('Something New');
alert(myWindow.getTitle()); // alerts "Something New"
myWindow.setTitle(null); // alerts "Error: Title must be a valid non-empty string"
myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100 3. 静态配置
静态配置成员可以使用 statics 属性来定义:
代码如下:
Ext.define('Computer', {
statics: {
instanceCount: 0,
factory: function(brand) {
// 'this' in static methods refer to the class itself
return new this({brand: brand}); } },
config: {
brand: null},
constructor: function(config) {
this.initConfig(config);
// the 'self' property of an instance refers to its class
this.self.instanceCount ++; }});
var dellComputer = Computer.factory('Dell');var appleComputer = Computer.factory('Mac');
alert(appleComputer.getBrand());
// using the auto-generated getter to get the value of a config property. Alerts "Mac"
alert(Computer.instanceCount);
// Alerts "2" 四. 错误处理和调试
错误处理与调试技巧
Ext JS 4 包含了一些有用的特性,可以帮助你调试和错误处理:
你可以使用 Ext.getDisplayName() 方法来获取任何方法的显示名称,这在抛出错误时特别有用,可用于在错误描述中显示类名和方法名:
throw new Error('[' + Ext.getDisplayName(arguments.callee) + '] Some message here');
当错误从由 Ext.define() 定义的类的任何方法中抛出时,如果你使用的基于 WebKit 的浏览器(Chrome 或者 Safari)的话,你会在调用堆栈中看到方法名和类名。例如,下面是从 Chrome 中看到的堆栈信息:

JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
