为什么不用 @ccclass 注解不会成为 cc 对象
核心原因: __ctors__ 属性标识
Cocos Creator 通过 __ctors__ 属性来识别一个类是否是 CCClass。关键代码在 CCClass.js 第 1034-1037 行:
CCClass._isCCClass = function (constructor) {
return constructor &&
constructor.hasOwnProperty('__ctors__'); // is not inherited __ctors__
};
@ccclass 的作用流程
-
@ccclass 装饰器调用 cc.Class()
当使用 @ccclass 装饰器时,它会调用 cc.Class(proto) ( CCClassDecorator.js 第 283 行):
var ccclass = checkCtorArgument(function (ctor, name) {
var base = js.getSuper(ctor);
var proto = {
name,
extends: base,
ctor,
__ES6__: true,
};
// ...
var res = cc.Class(proto); // <-- 这里
return res;
});
-
cc.Class() 给类添加 __ctors__ 属性
在 CCClass.js 第 283 行:
js.value(fireClass, '__ctors__', ctors.length > 0 ? ctors : null, true);
这个 __ctors__ 属性是 CCClass 的身份标识。
不使用 @ccclass 的后果
如果没有 @ccclass ,类就不会被 cc.Class() 处理,因此不会有 __ctors__ 属性。这会导致引擎在多个关键位置将其视为普通对象而非 CCClass:
1. 实例化 ( instantiate.js 第 190 行)
function enumerateObject (obj, clone, parent) {
var klass = obj.constructor;
if (cc.Class._isCCClass(klass)) {
enumerateCCClass(klass, obj, clone, parent); // 只复制 __values__ 定义的属性
}
else {
// 当作普通对象处理,遍历所有 own properties
for (var key in obj) {
if (!obj.hasOwnProperty(key) || ...) {
continue;
}
// 复制属性...
}
}
}
影响:如果没有 @ccclass ,实例化时会遍历所有 hasOwnProperty 属性,可能复制不必要的内部属性,且不会正确处理 CCClass 的属性初始化逻辑。
2. 对象销毁后的属性重置 ( CCObject.js 第 370 行)
if (cc.Class._isCCClass(ctor)) {
var attrs = cc.Class.Attr.getClassAttrs(ctor);
var propList = ctor.__props__;
for (var i = 0; i < propList.length; i++) {
// 根据 __props__ 重置属性为默认值
}
}
影响:没有 @ccclass ,对象池复用对象时无法正确重置属性。
3. 反序列化 ( deserialize-compiled.ts )
反序列化时需要根据类定义创建对象并设置属性。如果类不是 CCClass,引擎无法正确识别和处理其属性定义。
4. 编辑器识别
编辑器中的组件面板、属性检查器等都依赖 _isCCClass 来判断一个类是否是有效的组件类。_
总结
| 特性 |
有 @ccclass
|
无 @ccclass
|
__ctors__ 属性 |
有 |
无 |
_isCCClass() 返回 |
true_ |
false |
| 序列化/反序列化 |
正常 |
失败 |
cc.instantiate_ |
正确复制 |
可能异常 |
| 编辑器识别 |
正常 |
无法识别 |
| 属性默认值重置 |
正常 |
失效_ |
结论: @ccclass 是 Cocos Creator 识别和管理类的"身份证"。没有它,引擎无法将类识别为 CCClass,导致序列化、实例化、属性管理等核心功能无法正常工作。