一种JavaScript类继承和super方法调用的实现

在设计实现一种Java、Objective-C与JavaScript混合编程的编程风格JSAppSugar时,需要 JavaScript 语言支持类导向的编程风格,然而JavaScript本身是原型导向(Prototype-based)的,因此在JavaScript中也有很多种实现类继承的方式。这里介绍一下JSAppSugar中实现类继承和super方法调用的实现方式。

查看源码:https://github.com/JSAppSugar/JSA4JS/blob/master/src/JSAppSugar.js

该JS文件设计用于JSA4CocoaJSA4Java中,以实现JavaScript与Java、Objective-C混合编程,也可单独使用在普通JavaScript程序中实现类继承和父类方法调用。

类继承编程风格

JSAppSugar编程风格定义一个基础类、子类,以及在子类中调用父类方法。

$class("my.sample.Person",{
  name : "Unknown",
  $init : function(name){
    if(name) this.name = name;
  },
  eat : function(food){
    return this.name + " is eating "+food;
  }
});

$class("my.sample.Programmer",{
  $extends : "my.sample.Person",
  title : "Programmer",
  $init : function(title,name){
    $super(name);
    if(title){
      this.title = title;
    }
  }
  eat : function(food){
    return this.title + " " + $super.eat(food);
  }
});

其中 $init 表示为构造器方法

调用:

var bob = new my.sample.Person("Bob");
var bobDoing = bob.eat("Salad"); //函数将返回字符串 Bob is eating Salad
var bill = new my.sample.Programmer("CTO","Bill");
var billDoing = bill.eat("Sausage"); //函数将返回字符串 CTO Bill is eating Sausage

类继承的实现

JSAppSugar实现类继承的方式采用了原型链方式:

initializing = true;//闭包属性,用于在创建原型链父类对象时避免调用父类的构造器方法
JSAClass.prototype = new SuperClass();//构造原型链
initializing = false;
JSAClass.prototype.constructor = JSAClass;//不是构造原型链继承的必须,设置目的是为了通过类对象查找到类原型

构造器方法的实现(这里只列出了关键代码):

JSAClass = function(){
  if(!initializing && this.$init){//initializing为判断是否在构造原型链,如果是则忽略执行构造器方法
    this.$init.apply(this, arguments);
  }
}

通过$super调用父类方法

调用父类方法的原理就是找到父类原型类对象上的同名方法,然后使用function.apply方法调用这个方法,同时将this设置为当前调用对象。

前面DEMO中的$super对象和方法实际是不存在的,$class类定义方法会在类定义时将原代码转换为 this.$super("funcName")的形式。$super方法将返回当前调用链上父类的方法。$super()则会转换为this.$super("$init") 也就是父类的$init构造器方法。

$super方法定义:

JSAClass.prototype.$super = function(){
    var func = this.$SuperClass[name];//闭包方法对$SuperClass进行动态赋值
	var $this = this;
	return function(){
		return func.apply($this,arguments);
	};
}

JSAppSugar使用查找父类原型类对象的方式为闭包引用:

var SuperClassProto = SuperClass.prototype;//SuperClass是定义中 $extends对应的类的构造器方法

if(typeof define[key] == "function" && /\$super/.test(define[key])){//函数定义使用了$super时
  JSAClass.prototype[key] =(
    function(defineFunction){//定义一个闭包方法
      if(engine.f_redefine) defineFunction = engine.f_redefine(defineFunction);//将$super关键字替换为this.$super('functionName')
      return function(){
        var t = this.$SuperClass;
        this.$SuperClass = SuperClassProto;//通过闭包引用,将执行当前方法的父类原型赋值到当前对象,以便$super方法快速获取
        var result = defineFunction.apply(this,arguments);
        this.$SuperClass = t;
        return result;
      }
    }
  )(define[key]);
}else{
  JSAClass.prototype[key] = define[key];
}

通过闭包引用,实现快速查找当前方法所属类的父类方法。

转载于:https://my.oschina.net/u/4018755/blog/2874624

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值