這篇文章介紹了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);
};
}
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19923.html