对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 相关文章推荐
从jQuery.camelCase()学习string.replace() 函数学习
Sep 13 Javascript
含有CKEditor的表单如何提交
Jan 09 Javascript
js的Boolean对象初始值示例
Mar 04 Javascript
Node.js和MongoDB实现简单日志分析系统
Apr 25 Javascript
jQuery实现简单的网页换肤效果示例
Sep 18 Javascript
js date 格式化
Feb 15 Javascript
基于JavaScript实现的插入排序算法分析
Apr 14 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
Aug 19 Javascript
全站最详细的Vuex教程
Apr 13 Javascript
vue拦截器实现统一token,并兼容IE9验证功能
Apr 26 Javascript
vue项目初始化到登录login页面的示例
Oct 31 Javascript
js实现表单项的全选、反选及删除操作示例
Jun 05 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
PHP正则表达式之定界符和原子介绍
2012/10/05 PHP
ThinkPHP框架任意代码执行漏洞的利用及其修复方法
2014/07/04 PHP
php中使用array_filter()函数过滤空数组的实现代码
2014/08/19 PHP
php实现的ping端口函数实例
2014/11/12 PHP
php+mysqli事务控制实现银行转账实例
2015/01/29 PHP
PHP封装的Twitter访问类实例
2015/07/18 PHP
详解PHP数组赋值方法
2015/11/07 PHP
Aster vs Newbee BO5 第三场2.19
2021/03/10 DOTA
jquery的颜色选择插件实例代码
2008/10/02 Javascript
关于ExtJS4.1:快捷键支持的问题
2013/04/24 Javascript
JS+CSS实现仿新浪微博搜索框的方法
2015/02/24 Javascript
js调用百度地图及调用百度地图的搜索功能
2015/09/07 Javascript
jQuery实现连续动画效果实例分析
2015/10/09 Javascript
js获取鼠标点击的对象,点击另一个按钮删除该对象的实现代码
2016/05/13 Javascript
Ionic 2 实现列表滑动删除按钮的方法
2017/01/22 Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
2017/02/06 Javascript
layui分页效果实现代码
2017/05/19 Javascript
js指定步长实现单方向匀速运动
2017/07/17 Javascript
vue短信验证性能优化如何写入localstorage中
2018/04/25 Javascript
Vue实现一种简单的无限循环滚动动画的示例
2021/01/10 Vue.js
[01:59]翻天覆地,因你而变,7.20版本地图更新速览
2018/11/24 DOTA
Anaconda入门使用总结
2018/04/05 Python
DataFrame中的object转换成float的方法
2018/04/10 Python
Python的多维空数组赋值方法
2018/04/13 Python
使用opencv将视频帧转成图片输出
2019/12/10 Python
python装饰器使用实例详解
2019/12/14 Python
解决django框架model中外键不落实到数据库问题
2020/05/20 Python
几个解决兼容IE6\7\8不支持html5标签的几个方法
2013/01/07 HTML / CSS
Ajax请求总共有多少种Callback
2016/07/17 面试题
护士自荐信怎么写
2013/10/18 职场文书
个人授权委托书
2014/04/03 职场文书
在职党员进社区活动总结
2014/07/05 职场文书
白鹤梁导游词
2015/02/06 职场文书
永远是春天观后感
2015/06/12 职场文书
合同范本之电脑出租
2019/08/13 职场文书
Python内置数据类型中的集合详解
2022/03/18 Python