这篇文章介绍了JavaScript模拟类机制及私有变量的方法及思路
有需要的朋友可以参考一下
在使用一些 Javascript 框架时或许会看到类似的代码
复制代码 代码如下:
var MyClass = new Class({
initialize: function(param
) {
this
param = param;
}
func
: function(
) {
}
});
var myObj = new MyClass(param);
myObj
func
(
);
这是一种典型的面向对象的类机制应用与原生的 Javascript 类机制相比显得更为清晰和自然并且在此基础上实现类的继承也较为方便那么这是如何实现的呢?
众所周知在 Javascript 中将一个函数作为构造器可以创建出一个对象上面的代码可以简单的写成
复制代码 代码如下:
function MyClass(param) {
this
param = param;
this
func
= function(
) {
};
}
var myObj = new MyClass(param);
myObj
func
();
其实还是蛮简单的也不难理解不过如果要构建一套大型的 Javascript 类库可能就会比较混乱从一堆代码中要找出哪些是类哪些是函数哪些是类方法哪些是类属性是一件痛苦的事
当然这里并不是要比较它们的优劣只是好奇 new Class 的实现方式而已
在 上面的代码中使用 new MyClass() 这样的语句意味着 MyClass 必须是一个函数同时也就意味着 new Class 需要返回一个函数对象从字面的意思上可以看出函数 initialize 是当做构造函数来使用的所以new Class 返回的函数中必须使用 initialize 来对对象进行初始化基于这样的分析可以得出以下代码
复制代码 代码如下:
function Class(argu) {
return function() {
var init = argu[
initialize
] || function() {}; //如果没有构造函数 initialize
使用一个空函数作为默认构造函数
for(var p in argu) {
this[p] = argu[p];
}
init
apply(this
arguments); //使用当前函数的 this 来代替函数 initialize 原有的 this
}
}
上 面的代码并不够严谨但用来说明问题已经足够了需要注意 initapply(this arguments) 这一句这里有几个变量的指代一个是 this原本 initialize 中默认的 this现在已被替代为返回的这个匿名函数的 this而这个匿名函数是通过 new Class 新建的自定义类的构造器另外一个是 arguments它指代的是匿名函数的参数也就是上面的 new MyClass(param) 中的 param
this 的转换有些让人头晕那么有没有更为简单的方法呢?请看下面的代码
复制代码 代码如下:
function Class(argu) {
var obj = argu[
initialize
] || function() {};
for(var p in argu) {
obj
prototype[p] = argu[p]; //注意
这里用的是 prototype
}
return obj; // 其实还是返回一个函数
}
呵呵感觉直白了许多
这就完成了一个简单的类机制的构建通过这种机制可以创建类的构造函数方法及属性但这些显然都是公有的那么如何实现私有变量及方法呢?
我们知道Javascript 类的私有变量可以通过闭包的机制来完成但使用 new Class({}) 的方式转换后显然很难形成有效的闭包如何绕过这个问题呢?
Javascript 提供了两个方法eval() 及函数对象的 toString() 方法前者较为常见而后者可用于获取函数的具体代码通过这两个方法可以简单的模拟类的私有变量
复制代码 代码如下:
function Class(argu) {
var _ = argu[
private
] || {};
eval(
var obj =
+ (argu[
initialize
] || function() {})
toString());
for(var p in argu) {
if(p ==
initialize
|| p ==
private
)
continue;
if(typeof argu[p] ==
function
)
eval(
obj
prototype[p] =
+ argu[p]
toString());
else
obj
prototype[p] = argu[p];
}
return obj;
}
通过函数对象的 toString() 方法提取出函数的代码并使用 eval 方法执行这些代码这样就可以构造出一个有效的闭包范围从而实现私有机制我们可以如下应用
复制代码 代码如下:
var Person = new Class({
private: {
height:
weight:
}
initialize: function(name
height
weight) {
this
name = name;
_
height = height || _
height;
_
weight = weight || _
weight;
}
show: function() {
alert(
Name:
+ this
name +
/nheight:
+ _
height +
/nweight:
+ _
weight);
}
});
var my = new Person("Zh");
my
show();
看起来不不错不过在实际应用中其实并没有太大的用途主要是效率上相比通常的实现方式大概需要多花四倍的时间在大型类库的构建上这是不可容忍的而小型的应用中实现下面的代码更为简单直接
复制代码 代码如下:
function MyClass(param) {
var privateVar = ;
thisparam = param;
thisfunc = function() {
alert(privateVar);
};
}