对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 相关文章推荐
prototype 学习笔记整理
Jul 17 Javascript
高性能Javascript笔记 数据的存储与访问性能优化
Aug 02 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
Nov 14 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
Aug 20 Javascript
Bootstrap Chart组件使用教程
Apr 28 Javascript
js基于cookie记录来宾姓名的方法
Jul 19 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
简单实现AngularJS轮播图效果
Apr 10 Javascript
Vue2 配置 Axios api 接口调用文件的方法
Nov 13 Javascript
基于Vue2的独立构建与运行时构建的差别(详解)
Dec 06 Javascript
react native 原生模块桥接的简单说明小结
Feb 26 Javascript
JavaScript解析JSON数据示例
Jul 16 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
解决phpmyadmin中文乱码问题。。。
2007/01/18 PHP
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
解析MySql与Java的时间类型
2013/06/22 PHP
CI框架Session.php源码分析
2014/11/03 PHP
PHP实现删除字符串中任何字符的函数
2015/08/11 PHP
php限制文件下载速度的代码
2015/10/20 PHP
php简单获取复选框值的方法
2016/05/11 PHP
php实现保存周期为1天的购物车类
2017/07/07 PHP
PHP解析url并得到url参数方法总结
2018/10/11 PHP
javascript学习笔记(十四) window对象使用介绍
2012/06/20 Javascript
js实现翻页后保持checkbox选中状态的实现方法
2012/11/03 Javascript
jQuery实现新消息在网页标题闪烁提示
2015/06/23 Javascript
angular.js 路由及页面传参示例
2017/02/24 Javascript
NodeJS学习笔记之Module的简介
2017/03/24 NodeJs
JavaScript实现QQ聊天消息展示和评论提交功能
2017/05/22 Javascript
详解angularJS+Ionic移动端图片上传的解决办法
2017/09/13 Javascript
js字符串处理之绝妙的代码
2019/04/05 Javascript
微信小程序与webview交互实现支付功能
2019/06/07 Javascript
[02:04]2020年夜魇暗潮预告片
2020/10/30 DOTA
[03:07]完美世界DOTA2联赛PWL DAY10 决赛集锦
2020/11/11 DOTA
python批量修改文件后缀示例代码分享
2013/12/24 Python
Python格式化压缩后的JS文件的方法
2015/03/05 Python
python获取本机mac地址和ip地址的方法
2015/04/29 Python
Python中字典的setdefault()方法教程
2017/02/07 Python
python简单鼠标自动点击某区域的实例
2019/06/25 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
Python selenium爬取微博数据代码实例
2020/05/22 Python
MATLAB数学建模之画图汇总
2020/07/16 Python
澳大利亚领先的在线美容商城:Adore Beauty
2017/04/14 全球购物
迪卡侬印度官网:购买所有体育用品
2017/06/24 全球购物
迎接领导欢迎词
2014/01/11 职场文书
《晚上的太阳》教学反思
2014/04/23 职场文书
商务英语专业大学生职业生涯规划书
2014/09/14 职场文书
小学英语教学随笔
2015/08/14 职场文书
中学生打架检讨书之500字
2019/08/06 职场文书
关于ObjectUtils.isEmpty() 和 null 的区别
2022/02/28 Java/Android