对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 事件绑定函数代码
Apr 28 Javascript
某页码显示的helper 少量调整,另附js版
Sep 12 Javascript
原生Js页面滚动延迟加载图片实现原理及过程
Jun 24 Javascript
深入理解JavaScript系列(43):设计模式之状态模式详解
Mar 04 Javascript
浅谈js 闭包引起的内存泄露问题
Jun 22 Javascript
AngularJS改变元素显示状态
Apr 20 Javascript
JS实现多张图片预览同步上传功能
Jun 23 Javascript
深入浅出es6模板字符串
Aug 26 Javascript
jQuery表单元素过滤选择器用法实例分析
Feb 20 jQuery
JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】
May 12 Javascript
vue scroll滚动判断的实现(是否滚动到底部、滚动方向、滚动节流、获取滚动区域dom元素)
Jun 11 Javascript
Antd的table组件表格的序号自增操作
Oct 27 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
for循环连续求和、九九乘法表代码
2012/02/20 PHP
PHP实现简单的新闻发布系统实例
2015/07/28 PHP
基于Laravel 5.2 regex验证的正确写法
2019/09/29 PHP
jquery+ashx无刷新GridView数据显示插件(实现分页、排序、过滤功能)
2010/04/25 Javascript
jQuery阻止冒泡和HTML默认操作
2010/11/17 Javascript
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
2011/03/28 Javascript
jquery绑定原理 简单解析与实现代码分享
2011/09/06 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
JavaScript获得url所有参数键值表的方法
2015/03/21 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
2015/11/25 Javascript
浅谈js多维数组和hash数组定义和使用
2016/07/27 Javascript
Bootstrap导航简单实现代码
2017/03/06 Javascript
微信小程序自动客服功能
2017/11/02 Javascript
微信小程序radio组件使用详解
2018/01/31 Javascript
使用veloticy-ui生成文字动画效果
2018/02/08 Javascript
Vue中mintui的field实现blur和focus事件的方法
2018/08/25 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
2018/12/28 Javascript
js图片查看器插件用法示例
2019/06/22 Javascript
js布局实现单选按钮控件
2020/01/17 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
2020/09/21 Javascript
Python实现的多线程端口扫描工具分享
2015/01/21 Python
使用Python实现一个简单的项目监控
2015/03/31 Python
Python中用于返回绝对值的abs()方法
2015/05/14 Python
python正则表达式面试题解答
2020/04/28 Python
python与caffe改变通道顺序的方法
2018/08/04 Python
python getopt模块使用实例解析
2019/12/18 Python
python 串行执行和并行执行实例
2020/04/30 Python
美国二手复古奢侈品包包购物网站:LXRandCo
2019/06/18 全球购物
俄罗斯最大的在线珠宝大卖场:Nebo
2019/12/08 全球购物
linux面试题参考答案(7)
2014/07/24 面试题
焊接专业毕业生求职信
2013/10/01 职场文书
美容师的职业规划书
2013/12/27 职场文书
公司拓展活动方案
2014/02/13 职场文书
年度评优评先方案
2014/06/03 职场文书
医生党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
Golang 并发编程 SingleFlight模式
2022/04/26 Golang