cocos2d-js中关于继承的细节

var A = Class.extend({
    arr   : [1, 2]
});
var a1 = new A();
var a2 = new A();
a1.arr.push(3);
console.log("arr = " + a1.arr);     //arr = 1,2,3
console.log("arr = " + a2.arr);     //arr = 1,2,3


 

Cocos2d-js里面简单的类继承和对象创建,但是奇怪的是,a1对象和a2对象里面的成员属性arr明显是指向了同一个数组,所以这样的写法是不可取的,数组的定义应该在init函数里面进行定义。

出现这个问题的原因要从JavaScript的继承的实现来找。JavaScript本身没有提供继承的机制,一般是通过对象的原型来实现。Cocos2d-JS里面的类继承实现参考了John Resiq的JavaScript继承的机制,并修改了Class根类的实现。下面是John Resiq的Class实现

(function(){
    var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

    // The base Class implementation (does nothing)
    this.Class = function(){};

    // Create a new Class that inherits from this class
    Class.extend = function(prop) {
        var _super = this.prototype;

        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        initializing = true;
        var prototype = new this();
        initializing = false;

        // Copy the properties over onto the new prototype
        for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
                (function(name, fn){
                    return function() {
                        var tmp = this._super;

                        // Add a new ._super() method that is the same method
                        // but on the super-class
                        this._super = _super[name];

                        // The method only need to be bound temporarily, so we
                        // remove it when we're done executing
                        var ret = fn.apply(this, arguments);
                        this._super = tmp;

                        return ret;
                    };
                })(name, prop[name]) :
                prop[name];
        }

        // The dummy class constructor
        function Class() {
            // All construction is actually done in the init method
            if ( !initializing && this.init )
                this.init.apply(this, arguments);
        }

        // Populate our constructed prototype object
        Class.prototype = prototype;

        // Enforce the constructor to be what we expect
        Class.prototype.constructor = Class;

        // And make this class extendable
        Class.extend = arguments.callee;

        return Class;
    };
})();

从上面的代码可以看出,A继承了Class,把Array类型的成员属性指向实参prop对象中对应Array,而构造函数也没有对Array类型的成员属性进行处理,所以像本文一开始那样创建对象,属性arr会指向同一个数组。

如果你就是喜欢那样定义类里面的数组的话,可以对构造函数Class()进行修改,如下

// The dummy class constructor
function Class() {
    // All construction is actually done in the init method
    if ( !initializing && this.init )
        this.init.apply(this, arguments);

    for(var name in this) {
        this[name] instanceof Array &&
            (this[name] = this[name].slice());
    }
}
原来代码的结果如下

var A = Class.extend({
    arr   : [1, 2]
});
var a1 = new A();
var a2 = new A();
a1.arr.push(3);
console.log("arr = " + a1.arr);     //arr = 1,2,3
console.log("arr = " + a2.arr);     //arr = 1,2
在构造函数里面把每一个数组属性都给一个副本就可以了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值