日期:2014-05-16  浏览次数:20377 次

[Js++开发历程] 模拟面向对象

1.2 模拟面向对象

要说到面向对象,Java的语法规范应该会比较熟悉,C#也同样。

谈到面向对象就得做到封装,对于Javascript如何做封装才最有效呢?不禁让我联想到闭包

1.2.1 闭包

? 闭包是能够读取其他函数内部变量的函数。

1.2.2 链式作用域

? JavaScript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。

所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

?

综合以上两点,Js++ 的面向对象都在函数体内实现“成员变量”和“成员函数”。

1.2.3 现在疑问就是这些“成员变量”和“成员函数”如何能开放出来,使得外界可以访问呢?其实有普遍有两种方法:

A. 将“成员变量”和“成员函数”做json成员,然后通过 return 关键字 从函数返回。

var D = function(){
 
return { //然后通过 return 关键字 从函数返回。
  v:1,
  fun:function(){
 
  }
};
 
};
 
var Class = D();

?

?

B. 通过传出一个对象,将“成员变量”和“成员函数”扩展到此对象中

?

var D = function($){
 
 $.extend($,{  // “成员变量”和“成员函数”扩展到此对象$
   a:1,
   fun:function(){
 
   }
 });
};
 
var Class = {};
D(Class);

?

?

C. 其实有一种更加巧妙的方法是通过 Function.caller

Function.caller

? 返回一个对函数的引用,该函数调用了当前函数。

? 有了此caller,我们就可以“成员变量”和“成员函数”存入到外围的函数上

?

function jpublic(overrides) {
    $.extend(jpublic.caller.$Public, overrides);
}
function jprotected(overrides) {
    $.extend(jprotected.caller.$Public, overrides);
}
 
var D = function(){  // 外围的函数
 
  jpublic({  // “成员变量”和“成员函数” 会存入外围的函数的$Public变量上
    a:1,
    fun:function(){
 
    }
  });
 
  jprotected({
    b:2
  });
 
};
 
var Class = D().$Public;
 

?

此时,就可以定义类似public,protected,private等关键字来区分类“成员变量”和“成员函数”不同作用域

?

?

1.2.4 关于继承的模拟

? 可以采用原型链的方式

?

1.2.5 对父类成员的“成员函数”的访问

? ? 由于在继承的模拟原型链中,已将子类和父类prototype通过superclass关联,因此可以这样访问:

'class A'.j(function(){
  jpublic({
    fun:function(){
 
    }
  });
 
});
 
'class B extends A'.j(function(){
  jpublic({
    fun:function(){
      B.superclass.fun.apply(this,arguments);  //通过superclass关联访问父类成员的“成员函数” fun
      // 可用 jsuper(this); 替换 B.superclass.fun.apply(this,arguments);
    }
  });
 
});

?

B.superclass.fun.apply(this,arguments); 这个写太长,而且麻烦,有没有更好的呢,经过多次的实践,终于又回到了Function.caller

?

function jsuper(jthis) {
    var m = jsuper.caller;  // 获得当前调用者,以上的例子为"fun" 函数
    if (m.methodname && m.owner) { // 在类定义时,已将每个“成员函数”的函数名和所属的类的构造函数存入到每个“成员函数”中
        var method = m.methodname;
        var owner = m.owner;
        var args;
        if (arguments.length > 1) { // 如果 jsuper 有传入参数,则采用传入参数,否则采用 fun 的 arguments
            args = $.toArray(arguments, 1);
        } else {
            args = $.toArray(m.arguments);
        }
        return owner.superclass[method || 'constructor'].apply(jthis, args); //访问父类成员的“成员函数” fun
    }
    return null;
}
 

?

1.2.6 在“成员函数”中使用“静态变量”

? Js++ 将静态变量存在类的构造函数中,可通过 jstatic.caller.owner获取构造函数

function jstatic(overrides) {
    if (arguments.length == 0) {
        return jstatic.caller && jstatic.caller.owner;
          //在类定义时,已将每个“成员函数”的函数名和所属的类的构造函数存入到每个“成员函数”中
    }
    return $.extend(jstatic.caller.$Static, overrides);
}

?

?

?

1.2.7 完整例子:

?

'class C extends P implements I'.j(function(csuper){
 
     jstatic({
         a:1
     });
 
     jpublic({
         constructor: function () {
             jsuper(this);
         },
         echo:function(){
             console.log(jstatic().a);
         }
     });
 
     jprotected({
 
     });
 
     jprivate({
 
     });
 
},'alias class name');

?

?

1 楼 mfkvfn 昨天  
JS++,我还以为又出新语言了呢