JavaScript模拟Java类继承
jopen
10年前
javascript采用原型继承的方式继承一个类,但一些使用过Java的程序员可能习惯使用经典的类继承,但javascript原生并不支持这种方式,因此需要手动实现。我是通过定义一个定义类的函数实现的,由于javascript没有访问修饰符,因此如果需要使用到private成员,请使用闭包。
/*将一个对象的自有属性复制到另一个对象的方法*/ function merge(from, to){ for(var i in from){ if(from.hasOwnProperty(i)){ to[i] = from[i]; } } } /*用于定义一个类 *参数:构造函数,继承的父类, 属性, 静态属性, 是否为单例模式 *注意:单例模式下返回非原始构造函数 */ function defineClass(constructor, parent, properties, statics, isSingleton){ /*如果为单例模式,保存实例,并在以后的调用中返回此实例*/ if(isSingleton){ var instance, oldConstructor = constructor; constructor = function(){ if(instance) return instance; oldConstructor.apply(this, arguments); instance = this; } } /*设置原型属性,这意味着传入的构造函数的原型属性将被覆盖 *javascript没有函数重载,因此parent函数需要做一些特殊处理,详情见parent定义 */ constructor.prototype = new parent(); /*将自有属性复制到原型中 *将静态属性复制到构造函数中,这意味着将不会继承parent的静态属性 */ merge(properties, constructor.prototype); merge(statics, constructor); /*将构造函数更改为当前构造函数 *将parent的引用保留 */ constructor.prototype.constructor = constructor; constructor.prototype.parent = parent; return constructor; } function parent(){ /*可以将这里看成两个构造函数,一个在定义子类时使用的无参构造函数,一个有参构造函数 *如果子类需要参数来使用父类初始化,可以通过this.parent得到 */ this.name = "parent"; if(arguments.length){ log(this.name + "'s constructor with params"); } } var child = defineClass(function(){ //this.parent.apply(this, arguments); this.name = "child"; if(arguments.length){ log(this.name + "'s constructor with params"); } }, parent, { say: function(){ log(this.name); } }, { value: "static" }, true); var instance = new child(), instance2 = new child(); log(child.value); //static log(instance.name); //child instance.say(); //child log(instance === instance2); //true log(instance instanceof parent) //true /*可以在child基础上扩展 */ var grandSon = defineClass(function(name){ this.name = "grandSon"; if(arguments.length){ log(this.name + "'s constructor with params"); } }, child, { shout: function(){ log("shout: " + this.name); } }); var instance3 = new grandSon(); instance3.say(); //grandSon instance3.shout(); //shout: grandSon log(instance3 instanceof child); //true log(instance3 instanceof parent); //true /*打印日志*/ function log(msg){ if(window.console){ console.log(msg); } }