【六】CocosCreator-CCObject.js源码分析

PS:只是看源码学习过程中把认为重要的内容以笔记的形式记录下来。       

        本来是想写CCNode的,结果发现CCNode继承BaseNode,BaseNode再继承CCObject,那么,就先来看CCObject吧~

        在CCObject类中,他是通过给原型方法赋值来实现类似成员函数相关的功能,如:prototype.destroy = function () {}。

【1】destroy():销毁对象。【因为这个方法很重要,所以我每步都插入关键的核心代码】
1.把需要销毁的对象加到销毁队列objectsToDestroy中。(不会立马销毁)

prototype.destroy = function () {
    // 省略上下文
    objectsToDestroy.push(this);
    // 省略上下文
};


2.在CCDirector的主循环里,再当前帧渲染之前调用deferredDestroy()进行销毁。

mainLoop: CC_EDITOR ? function (deltaTime, updateAnimate) {
       // 省略上下文
    } : function (now) {
            // 省略上下文
            // Update
            if (!this._paused) {
                // 省略上下文
                // Destroy entities that have been removed recently
                Obj._deferredDestroy();
            }

            // 省略上下文
        }
    },


3.【deferredDestroy函数内部】遍历objectsToDestroy,如果对象还没销毁,则调用_destroyImmediate。然后把删掉的对象从objectsToDestroy队列里面清除。

function deferredDestroy () {
    var deleteCount = objectsToDestroy.length;
    for (var i = 0; i < deleteCount; ++i) {
        var obj = objectsToDestroy[i];
        if (!(obj._objFlags & Destroyed)) {
            obj._destroyImmediate();
        }
    }
    // if we called b.destory() in a.onDestroy(), objectsToDestroy will be resized,
    // but we only destroy the objects which called destory in this frame.
    if (deleteCount === objectsToDestroy.length) {
        objectsToDestroy.length = 0;
    }
    else {
        objectsToDestroy.splice(0, deleteCount);
    }

    if (CC_EDITOR) {
        deferredDestroyTimer = null;
    }
}


4.【_destroyImmediate函数内部】在对象销毁前,调用_onPreDestroy(). 所有的子类就可以在这个接口里做一些销毁对象前需要执行的操作了。
5.【_destroyImmediate函数内部】调用_destruct(),清除实例的所有引用。

prototype._destroyImmediate = function () {
    if (this._objFlags & Destroyed) {
        cc.errorID(5000);
        return;
    }
    // engine internal callback
    if (this._onPreDestroy) {
        this._onPreDestroy();
    }

    if ((CC_TEST ? (/* make CC_EDITOR mockable*/ Function('return !CC_EDITOR'))() : !CC_EDITOR) || cc.engine._isPlaying) {
        this._destruct();
    }

    this._objFlags |= Destroyed;
};


6.【_destruct函数内部】调用compileDestruct()构造出“析构函数”,然后调用destruct(this)析构函数清除实例的所有引用。

prototype._destruct = function () {
    var ctor = this.constructor;
    var destruct = ctor.__destruct__;
    if (!destruct) {
        destruct = compileDestruct(this, ctor);
        js.value(ctor, '__destruct__', destruct, true);
    }
    destruct(this);
};


7.【compileDestruct函数内部】会遍历对象的key,然后用自带的原型方法hasOwnProperty去检测对象的自有属性,然后把所有自有属性置空再赋值给propsToReset。
8.【compileDestruct函数内部】判断如果有构造函数,则是类类型,同样把类里面的string、object、funciton等置空赋值给propsToReset。
PS:上面的7,8两个步骤很关键,大致意思就是构建一个propsToReset出来,key值用对象的key,value就是置空的值。
9.【compileDestruct函数内部】返回一个方法(可以勉强理解为“析构函数”),方法内部其实就是遍历propsToReset,把propsToReset的值赋值给对象,从而真正实现了清除实例的所有引用。

function compileDestruct (obj, ctor) {
    var shouldSkipId = obj instanceof cc._BaseNode || obj instanceof cc.Component;
    var idToSkip = shouldSkipId ? '_id' : null;

    var key, propsToReset = {};
    for (key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (key === idToSkip) {
                continue;
            }
            switch (typeof obj[key]) {
                case 'string':
                    propsToReset[key] = '';
                    break;
                case 'object':
                case 'function':
                    propsToReset[key] = null;
                    break;
            }
        }
    }
    // Overwrite propsToReset according to Class
    if (cc.Class._isCCClass(ctor)) {
        var attrs = cc.Class.Attr.getClassAttrs(ctor);
        var propList = ctor.__props__;
        for (var i = 0; i < propList.length; i++) {
            key = propList[i];
            var attrKey = key + cc.Class.Attr.DELIMETER + 'default';
            if (attrKey in attrs) {
                if (shouldSkipId && key === '_id') {
                    continue;
                }
                switch (typeof attrs[attrKey]) {
                    case 'string':
                        propsToReset[key] = '';
                        break;
                    case 'object':
                    case 'function':
                        propsToReset[key] = null;
                        break;
                    case 'undefined':
                        propsToReset[key] = undefined;
                        break;
                }
            }
        }
    }

    if (CC_SUPPORT_JIT) {
        // compile code
        var func = '';
        for (key in propsToReset) {
            var statement;
            if (CCClass.IDENTIFIER_RE.test(key)) {
                statement = 'o.' + key + '=';
            }
            else {
                statement = 'o[' + CCClass.escapeForJS(key) + ']=';
            }
            var val = propsToReset[key];
            if (val === '') {
                val = '""';
            }
            func += (statement + val + ';\n');
        }
        return Function('o', func);
    }
    else {
        return function (o) {
            for (var key in propsToReset) {
                o[key] = propsToReset[key];
            }
        };
    }
}

【2】_objFlags:应该是记录对象的状态吧,状态的定义在CCObject.js也有,但具体每个状态什么时候用到,暂时在CCObject还没看到,估计是给子类使用的?

【3】cc.isValid():这个我们经常用来判断对象是否还有效的方法,就是通过_objFlags的状态来判断的。

相关推荐

  1. CocosCreator-CCObject.js分析

    2024-02-08 14:46:02       31 阅读
  2. emacs 分析

    2024-02-08 14:46:02       40 阅读
  3. flink分析之功能组件()-心跳组件

    2024-02-08 14:46:02       42 阅读
  4. freertos 分析 任务调度二

    2024-02-08 14:46:02       38 阅读
  5. SpringMVC分析()--参数名称解析器

    2024-02-08 14:46:02       19 阅读
  6. spring解析(

    2024-02-08 14:46:02       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-08 14:46:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-08 14:46:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-08 14:46:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-08 14:46:02       20 阅读

热门阅读

  1. 最全软件系统架构演变!

    2024-02-08 14:46:02       37 阅读
  2. 精通Python中的正则表达式

    2024-02-08 14:46:02       34 阅读
  3. 贪心算法入门题(算法村第十七关青铜挑战)

    2024-02-08 14:46:02       32 阅读
  4. redis

    redis

    2024-02-08 14:46:02      35 阅读
  5. leetCode 30天

    2024-02-08 14:46:02       27 阅读
  6. 使用gpu_burn对GPU进行压测

    2024-02-08 14:46:02       30 阅读
  7. 典型数据结构的模板实现

    2024-02-08 14:46:02       39 阅读
  8. chagpt的原理详解

    2024-02-08 14:46:02       29 阅读
  9. WebGPU Inter-stage 变量

    2024-02-08 14:46:02       31 阅读
  10. watch 和 watchEffect 的使用

    2024-02-08 14:46:02       28 阅读
  11. Nginx中proxy_pass指令斜杠的作用

    2024-02-08 14:46:02       33 阅读