对javascript继承的理解


Posted in Javascript onOctober 11, 2016

由于javascript原生是不支持类的(ES6已经支持class与extends),更不用谈继承、多态了,为了模拟出一些其它面向对象编程语言的这些特性,有好多大牛写了给出了实现方式,看了John Resig的《Simple JavaScript Inheritance》这篇文章,深深被折服了,原来短短几十行javascript也可以这么强大、优雅,下面以我的理解方式来解读下。

主要实现了继承、访问父类的重名方法(这里的实现方式太妙了),但遗憾的是不能实现成员变量/函数的隐藏。

(function(){
  //设置标志位,是new A()过程中还是 B=A.extends({/*   */})过程中;
  var initializing = false,
      //fnTest 可取结果为俩正则对象 /\b_super\b/与 /.*/
      //当正则的test方法参数支持自动调用toString()方法时取前面那个
      fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
    
  // 创建一个全局的 Class对象
  this.Class = function(){};
    
  // 创建继承函数
  Class.extend = function(prop) {
    //此处把_super指向父类的prototype,属性继承时需要用其判断父、子是否有同名方法
    var _super = this.prototype;
      
    //开始B=A.extends({/*   */});
    initializing = true;
    //实例化父类,并把父类的实例方法及属性给prototype
    var prototype = new this();
    initializing = false;
    //结束B=A.extends({/*   */});
      
    // 遍历用户传入的用于构建子类的对象
    //处理的地方包括:
    //1、属性直接存到prototype上
    //2、方法中没通过this._super()调用父类中的同名方法,则直接把该方法存到prototype上
    //3、方法中有通过this._super()调用父类中的同名方法,则把如下过程包裹成一个函数存到prototype上:
    //   把this._super指向父类的同名方法,然后再调用子类的该方法并返回执行结果
    for (var name in prop) {
      // 循环体中看起来略微复杂,是整个代码的精华所在
      //简化下此过程就是  v = a && b && c ? d : e; 等同于 v = (a && b && c) ? d : e
      //该过程中主要运用的就是逻辑运算中的短路运算 a,b,c全为true则v=d,否则v=e
      //a中判断prop[name]是否是函数,b中判断父类中是否也有同名的name函数,c主要判断name函数中是否有调用父类的同名方法(即调用了this._super())
      //d就是a,b,c同时满足的时候,也就是说:name是函数,且name函数存在与父类中,且子类的name函数需要调用了父类的同名函数
      //若a,b,c中有一项不满足则直接把prop[name]给prototype[name]
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          //首先,先决条件决定了prototype[name]是个函数,所以先包裹一个函数返回
          return function() {
            //作者这里备份,然后调用fn后又还原this._super
            //由于return的是一个function,具有延时调用的作用 所以在子类调用fn时this始终指向子类本身
            //而这里的_super是父类的_super,与this._super并无关系,所以备份应该是多余的
            //var tmp = this._super;
            //this._super指向与fn(即prop[name])同名的父类方法,方便fn内部调用
            //这里是实现子类中通过this._super()调用父类同名函数的关键
            this._super = _super[name];
            //此时再调用子类,子类里面的this._super已经指向了父类同名的函数,即_super[name]
            var ret = fn.apply(this, arguments);   
            //this._super = tmp;
            //返回执行结果
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
      
    //此“Class”与外头那个“Class”是两个东西
    //这个Class实为子类的构造函数
    function Class() {
      //不是A.extends({/*   */})过程中
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
      
    //前面处理好的prototype绑定给子类的prototype
    Class.prototype = prototype;
      
    //修正构造函数
    Class.prototype.constructor = Class;
    
    //赋予子类可被继续继承的功能
    Class.extend = arguments.callee;
      
    return Class;
  };
})();

如果想更深入了解js继承,请继续往下查看文章

Javascript 相关文章推荐
js 日期转换成中文格式的函数
Jul 07 Javascript
jQuery对象和DOM对象的相互转化实现代码
Mar 02 Javascript
使用jQuery轻松实现Ajax的实例代码
Aug 16 Javascript
js获取TreeView控件选中节点的Text和Value值的方法
Nov 24 Javascript
Javascript控制页面链接在新窗口打开具体方法
Aug 16 Javascript
二叉树先序遍历的非递归算法具体实现
Jan 09 Javascript
js利用事件的阻止冒泡实现点击空白模态框的隐藏
Jan 24 Javascript
JS实现统计复选框选中个数并提示确定与取消的方法
Jul 01 Javascript
浅析JS获取url中的参数实例代码
Jun 14 Javascript
javascript基于原型链的继承及call和apply函数用法分析
Dec 15 Javascript
mpvue构建小程序的方法(步骤+地址)
May 22 Javascript
浅析vue中的provide / inject 有什么用处
Nov 10 Javascript
Javascript动画效果(3)
Oct 11 #Javascript
JavaScript实现自动切换图片代码
Oct 11 #Javascript
Javascript动画效果(2)
Oct 11 #Javascript
Javascript动画效果(1)
Oct 11 #Javascript
原生Javascript和jQuery做轮播图简单例子
Oct 11 #Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
Oct 11 #Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
Oct 11 #Javascript
You might like
英雄试炼之肉山谷—引领RPG新潮流
2020/04/20 DOTA
php与java通过socket通信的实现代码
2013/10/21 PHP
CodeIgniter实现更改view文件夹路径的方法
2014/07/04 PHP
ThinkPHP实现递归无级分类――代码少
2015/07/29 PHP
PHP实现长文章分页实例代码(附源码)
2016/02/03 PHP
php使用strip_tags()去除html标签仍有空白的解决方法
2016/07/28 PHP
PHP实现随机生成水印图片功能
2017/03/22 PHP
PHP实现爬虫爬取图片代码实例
2021/03/03 PHP
javascript 当前日期加(天、周、月、年)
2009/08/09 Javascript
Tips 带三角可关闭的文字提示
2010/10/06 Javascript
js限制文本框为整数和货币的函数代码
2010/10/13 Javascript
在JavaScript中处理时间之setMinutes()方法的使用
2015/06/11 Javascript
JavaScript+html5 canvas实现图片破碎重组动画特效
2016/02/22 Javascript
Javascript 正则表达式校验数字的简单实例
2016/11/02 Javascript
Node.js 8 中的重要新特性
2017/06/28 Javascript
JS实现前端页面的搜索功能
2018/06/12 Javascript
node Buffer缓存区常见操作示例
2019/05/04 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
PyQt5每天必学之单行文本框
2018/04/19 Python
修改默认的pip版本为对应python2.7的方法
2018/11/06 Python
python 实现调用子文件下的模块方法
2018/12/07 Python
Django发送邮件功能实例详解
2019/09/02 Python
浅谈Python里面None True False之间的区别
2020/07/09 Python
html5中监听canvas内部元素点击事件的三种方法
2019/04/28 HTML / CSS
美国购买韩国护肤和美容产品网站:Althea Korea
2020/11/16 全球购物
毕业生就业自荐信
2013/12/04 职场文书
《玩具柜台前的孩子》教学反思
2014/02/13 职场文书
学生安全承诺书
2014/05/22 职场文书
企业人事任命书
2014/06/05 职场文书
党员发展大会主持词
2015/07/03 职场文书
意外事故赔偿协议书
2016/03/22 职场文书
如何开发一个渐进式Web应用程序PWA
2021/05/10 Javascript
python numpy中multiply与*及matul 的区别说明
2021/05/26 Python
分享mysql的current_timestamp小坑及解决
2021/11/27 MySQL