Summary
私人變數 在對象內部使用'var'關鍵字來聲明,而且它只能被私人函數和特權方法訪問。
私人函數 在對象的建構函式裡聲明(或者是通過var functionName=function(){...}來定義),它能被特權函數調用(包括對象的建構函式)和私人函數調用。
特權方法 通過this.methodName=function(){...}來聲明而且可能被對象外部的代碼調用。它可以使用:this.特權函數() 方式來調用特權函數,使用 :私人函數()方式來調用私人函數。
公用屬性 通過this.variableName來定義而且在對象外部是可以讀寫的。不能被私人函數所調用。
公用方法 通過ClassName.prototype.methodName=function(){...}來定義而且可以從對象外部來調用。
原型屬性 通過ClassName.prototype.propertyName=someValue來定義。
靜態屬性 通過ClassName.propertyName=someValue來定義。
另外注意下這種寫法: var 函數名=function 函數名(){...} 這個函數被調用時具有特權函數和私人函數的特性。
例:
複製代碼 代碼如下:<html>
<head>
<title></title>
<script type="text/javascript">
function Container( param ) {
function dec(){
if ( secret > 0 ) {
secret -= 1;
setSecret( 7)
alert( secret );
return true;
}
else {
// alert( "over"+this.member);
return false;
}
}
// this.dec = dec;
//this.dec = function dec (){...} different from above code.
function setSecret( num ){
secret = num;
}
this.member = param;
var secret = 3;
var self = this;
this.service = function () {
if (dec()) {
alert();
}
else {
return null;
}
}
}
// ---------------------------------------
function start(){
alert( "Start" )
var test = new Container( 'liuqi' );
// test.setSecret( 2 );
test.service();
test.service();
test.service();
test.service();
var test2 = new Container( 'liuqi' );
//test2.service();
// Container.dec();
}
</script>
</head>
<body>
<div onclick="start()" style="color:blue">click me</div>
</body>
</html>
JavaScript是世界上最被誤解的程式設計語言。有人認為它缺少資訊隱藏的特性,因為JavaScript對象不能擁有私人變數的方法。
但是這是個誤解。JavaScript對象可以擁有私人成員。
對象
JavaScript從根本上就是關於對象的。數組是對象,方法是對象,Object也是對象。什麼是對象?對象就是索引值對的集合。鍵是字串,
值可以是字串,數字,布爾和對象(包括數組和方法)。對象通常被實現為Hashtable,這樣值就可以被快速擷取。
如果值是一個函數,我可以稱其為方法。當對象的方法被調用時,“this”變數則被賦予該對象。方法可以通過“this”變數訪問執行個體
變數。
對象可以由初始化對象的方法 -- 建構函式產生。建構函式提供在其他程式設計語言中類提供的特性,包括靜態變數和方法。
Public
對象的成員都是public成員。任何對象都可以訪問,修改,刪除這些成員或添加新成員。主要有兩種方式來在一個新對象裡放置成員:
在建構函式裡
這種技術通常用來初始化public執行個體變數。建構函式的“this”變數用來給對象新增成員。
Java代碼 複製代碼 代碼如下:functin Container(param) {
this.member = param;
}
functin Container(param) {
this.member = param;
}
這樣,如果我們構造一個新對象var myContainer = new Container('abc'),則myContainer.member為'abc'。
在prototype裡
這種技術通常用來添加public方法。當尋找一個成員並且它不在對象本身裡時,則從對象的建構函式的prototype成員裡找。
prototype機制用來做繼承。為了添加一個方法到建構函式建立的所有對象裡,只需添加到建構函式的prototype:
Java代碼 複製代碼 代碼如下:Container.prototype.stamp = function (string) {
return this.member + string;
}
Container.prototype.stamp = function (string) {
return this.member + string;
}
這樣,我們可以調用該方法myContainer.stamp('def'),結果為'abcdef'。
Private
private成員由建構函式產生。普通的var變數和建構函式的參數都稱為private成員。
Java代碼 複製代碼 代碼如下:function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}
function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}
該建構函式建立了3個private執行個體變數: param,secret和that。它們被添加到對象中,但是不能被外部存取,也不能被該對象自己的
public方法訪問。它們只能由private方法訪問。private方法是建構函式的內部方法。
Java代碼 複製代碼 代碼如下:function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
}
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
}
private方法dec檢查secret執行個體變數。如果它大於0,則減少secret並返回true,否則返回false。它可以用來讓這個對象限制用3次。
按照慣例,我們定義一個private的that變數。這用來讓private方法可以使用本對象。這樣做是因為ECMAScript語言規範有一個錯誤,
該錯誤導致不能正確的設定this給內部方法。
private方法不能被public方法調用。為了讓private方法有用,我們需要引入privileged方法。
Privileged
privileged方法可以訪問private變數和方法,並且它本身可以被public方法和外界訪問。可以刪除或替代privileged方法,但是不能
更改它或強制它泄露自己的秘密。
privileged方法在建構函式裡用this分配。
Java代碼 複製代碼 代碼如下:function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function() {
if (dec()) {
return that.member;
} else {
return null;
}
};
}
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function() {
if (dec()) {
return that.member;
} else {
return null;
}
};
}
service是privileged方法。前三次調用myContainer.service()將返回'abc'。之後,它將返回null。service調用private的dec方法,
dec方法訪問private的secret變數。service對其他對象和方法可見,但是它不允許直接存取private變數。
閉包
由於JavaScript有閉包,public,private和privileged成員的模式是可行的。這意味著一個內部方法始終可以訪問它的外部方法的
var變數和參數,甚至在外部方法返回之後。這是JavaScript語言的一個非常強大的特性。當前沒有展示如何發掘這種特性的JavaScript
編程書籍,大多數甚至都沒提到。
private和privileged成員只能在對象被構造時產生。public成員則可以在任何時候添加。
模式
public
Java代碼 複製代碼 代碼如下:function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
Private
Java代碼 複製代碼 代碼如下:function Constructor(...) {
var that = this;
var membername = value;
function membername(...) {...}
}
// 注意: function語句
// function membername(...) {...}
// 是如下代碼的簡寫
// var membername = function membername(...) {...};
function Constructor(...) {
var that = this;
var membername = value;
function membername(...) {...}
}
// 注意: function語句
// function membername(...) {...}
// 是如下代碼的簡寫
// var membername = function membername(...) {...};
Privileged
Java代碼 複製代碼 代碼如下:function Constructor(...) {
this.membername = function (...) {...};
}
function Constructor(...) {
this.membername = function (...) {...};
}
譯者注:我認為可以簡單的把privileged方法簡單的看成是建構函式裡的public方法,因為privileged方法可以被外界和public方法訪問,
而它自身又可以訪問private變數。