博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript模拟Java类继承
阅读量:4497 次
发布时间:2019-06-08

本文共 2937 字,大约阅读时间需要 9 分钟。

javascript采用原型继承的方式继承一个类(javascript没有类这个概念,暂时这么称呼吧),但一些使用过Java的程序员可能习惯使用经典的类继承,但javascript原生并不支持这种方式,因此需要手动实现。这里通过定义一个定义类(defineClass)的函数实现,经测试越用越顺手。由于javascript没有访问修饰符,因此如果需要使用到private成员,请使用闭包。

 

1 /* 简单的对象扩充方法 2  */ 3 merge:function (target, origin) { 4     for (var attribute in origin) { 5         if (origin.hasOwnProperty(attribute)) { 6             target[attribute] = origin[attribute]; 7         } 8     } 9 },10 defineClass:function defineClass(constructor, parent, properties, statics, isSingleton) {11 12     /* 如果为单例模式,保存实例,并在以后的调用中返回此实例13      */14     if (isSingleton) {15         var oldConstructor = constructor,16             instance;17         constructor = function () {18             if (instance) return instance;19             oldConstructor.apply(this, arguments);20             instance = this;21         }22     }23 24     /* 设置原型属性,这意味着传入的构造函数的原型属性将被覆盖25      * 重要:parent内部需要检测参数,下面将会讲到26      */27     constructor.prototype = parent ? new parent() : {};28 29     /* 将自有属性复制到原型中30      * 将静态属性复制到构造函数中,这意味着将不会继承parent的静态属性31      */32     Lang.merge(constructor.prototype, properties);33     Lang.merge(constructor, statics);34 35     /* 将构造函数更改为当前构造函数36      * 将parent的引用保留37      */38     constructor.prototype.constructor = constructor;39     constructor.prototype.parent = parent;40     constructor.parent = parent;41 42     /* 借用父类函数43      */44     constructor.borrow = function(methodName, context, args){45         var oldParent;46 47         if(typeof methodName === "object") {48             args = context;49             context = methodName;50         }51 52         oldParent = context.parent;53         context.parent = parent;54 55         if(typeof methodName === "string") {56             constructor.prototype[methodName].apply(context, args || []);57         } else {58             constructor.apply(context, args || []);59         }60 61         context.parent = oldParent;62     };63     return constructor;64 }

 

使用时,父类如此定义

 

1 var Body = Lang.defineClass(function(x, y, shapes, sprites, detection){ 2     /* 由于类定义函数会创建父类实例作为子类的原型,因此必须检测参数 3      * 如果没有参数,相当于调用父类的默认构造函数  4      */ 5     if(arguments.length) { 6         /* 使用父类方法  7          */ 8         this.parent.borrow(this, arguments); 9 10         /* 非基本类型请放到构造函数中而不是原型中11          */12         this._tasks = [];13     }14 }, Object, {15     _distance: 0,16     setX: function(x){},17     setY: function(y){}18 }, {19     type: 'Base'20 });

 

继承Body

 

1 var Ninja = Lang.defineClass(function(){ 2     this.parent.borrow(this, arguments); 3 }, Body, { 4     _status: 1, 5     setStatus: function(x){ 6         /* 使用父类方法 7          */ 8         this.parent.borrow('setStatus', this, arguments); 9     }10 }, {});

 

注意,不能用此方法继承如Array等内置对象,如果你想通过定义一个类扩展Array的功能,那么在调用Array的某些方法时会出现问题,比如concat返回的数组直接包含两个对象,而不是包含两个对象中的元素。原因是虽然子类的原型链包含Array.prototype,但毕竟不是由Array直接构造,在调用某些方法时可能不会按照原始的方式执行。

转载于:https://www.cnblogs.com/smalldragonluo/p/3949989.html

你可能感兴趣的文章
pygame-KidsCanCode系列jumpy-part2-加速度与摩擦力
查看>>
[elk]logstash的grok匹配逻辑grok+date+mutate
查看>>
准备Android面试
查看>>
界面与后台逻辑完全分离,单例模式,接口
查看>>
redis安装及测试
查看>>
38-系统标准模块与第三方模块(1)
查看>>
[转]Android U 盘功能实现和分析
查看>>
dedecms织梦副栏目名称和链接调用
查看>>
iOS 离屏渲染学习笔记
查看>>
iOS Xib布局某些控件显示或隐藏<约束的修改>
查看>>
软件工程第一次作业
查看>>
乘法逆元+模的运算规则
查看>>
.net 实现微信公众平台的主动推送信息
查看>>
线程池ThreadPool详解
查看>>
宝石TD迷宫设计器
查看>>
DOM对象和JQuery对象的区别
查看>>
vue脚手架安装笔记
查看>>
P2146 [NOI2015]软件包管理器
查看>>
像素与DPI之间的关系
查看>>
druid监控配置
查看>>