JavaScript中的私人成員

來源:互聯網
上載者:User

JavaScript是世界上是被誤解得最厲害的程式設計語言。有些人認為它不具備“資訊隱藏”的能力,因為JavaScript的對象沒有私人變數和方法。這是誤解。JavaScript對象可以擁有私人成員,下面我們來看看怎麼做。(SharkUI.com註:JavaScript並不是真正擁有私人、公有等等OOP的特性,這篇譯文中提到的這些私人、公有、特權等特性,是利用JavaScript的其他特性(參看本文的“閉包”一節)“類比”出來的。感興趣的話可以搜尋相關的文章來看,當然也可以不管這些,就當它是真正的OOP來用。Have fun!)

對象

JavaScript是建立在對象之上的。數組(Array)是對象,函數(Function)是對象,對象(Objects)當然也是對象。那什麼是對象呢?對象是一組“名稱:值”對(name-value pair)的集合。名稱是字串,值卻可以是字串、數值、布爾或對象(包括數組和函數)。對象通常是用雜湊表來實現的,以便可以快速地取值。

如果值是一個函數,我們就可以把它當作一個“方法”。當對象的一個方法被執行,變數this就被設為對象本身。如此,方法就可以通過this變數來訪問對象的執行個體。

對象可以通過“構造器(constructor)”來建立。構造器是一個擁有初始化對象的函數。構造器提供了類似其他語言中的“類(class)”所提供的特性和功能,包括靜態變數和方法。

公有

對象的所有成員都是公有成員。任何函數都可以訪問、修改或者刪除這些成員,當然也可以添加新的成員。給對象新增成員的兩種主要方法:

通過構造器

這種方法一般用來初始化對象執行個體的公有變數。構造器的this變數被用來給對象新增成員:

function Container(param) {  this.member = param;}

構造一個新的對象:

var myContainer = new Container('abc');

然後,公有變數 myContainer.member 就擁有了值 'abc'。

通過原型(prototype)

這種方法通常用來添加公有方法。在對象本身搜尋一個成員但沒有找到時,就使用構造器的原型(prototype)成員。這種原型機制實現了物件導向所謂的 “繼承(inheritance)”,同時也節省了記憶體。給建立自同一個構造器的所有的對象加上一個方法,只需要給構造器的prototype增加一個函數:

Container.prototype.stamp = function (string) {  return this.member + string;}

然後我們就可以調用這個方法:

myContainer.stamp('def')

返回'abcdef'。

私人

私人(Private)成員是由構造器建立的。通常構造器中用var聲明的變數和函數參數成為私人成員。

function Container(param) {  this.member = param;  var secret = 3;  var self = this;}

這個構造器建立了三個私人的執行個體變數:param,secret和self。

function Container(param) {  function dec() {   if (secret > 0) {     secret -= 1;     return true;   } else {     return false;   }  }  this.member = param;  var secret = 3;  var self = this;}

私人方法dec會檢查執行個體變數secret,如果它大於0,自減1並返回true;如果它小於0,返回false。這樣就實現了由這個架造器所建立對象的dec函數只能用三次的功能。

按慣例,我們建立了一個私人變數self。私人方法可以通過它來訪問到對象本身。但這隻是一種權宜之計,因為《ECMAScript Language Specification》中有一個錯誤,使得內建函式的this變數被設定成一個錯誤值。

公有方法(SharkUI.com註:即上文說的通過prototype建立的方法)是無法調用私人方法的,所以為了能使用私人方法,我們需要引入特權方法(privileged method)。

特權

一個特權方法可以訪問私人變數和方法,而它本身可以被公有方法和外界訪問。你可以刪除或替換一個特權方法,但不能修改它,也不能強制它放棄自己的密秘(SharkUI.com註:原文如此,可能是指它的特權,關於這點請高手指教)。

特權方法是在構造器內部通過this來建立的。

function Container(param) {  function dec() {   if (secret > 0) {     secret -= 1;     return true;   } else {     return false;   }  }  this.member = param;  var secret = 3;  var self = this;  this.service = function () {   if (dec()) {     return self.member;   } else {     return null;   }  };}

service是一個特權方法。前三次調用myContainer.service()將返回'abc',之後將返回null。service通過調用私人方法dec來訪問私人變數secret。對於其他對象和方法來說,可以訪問到service,但不能直接存取到私人的成員。

閉包

這種公有、私人和特權成員模式的存在是由於JavaScript的內在機制:閉包。這意味著一個內建函式永遠可以訪問它外部函數的變數和參數,即使外部函數已經返回。這是JavaScript語言非常強大的一個特性。目前還沒有關於JavaScript編程的書籍展示了如何來利用它,它們甚至都沒有提到這一點。

私人和特權成員只能在對象初始化的時候建立,而公有成員可以被隨時添加進來。

模式公有
function Constructor(...) {  this.membername = value;}Constructor.prototype.membername = value;
私人
function Constructor(...) {  var self = this;  var membername = value;  function membername(...) {...}}

註:這句代碼:

function membername(...) {...}

事實上是以下代碼的簡略寫法

var membername = function membername(...) {...};
特權
function Constructor(...) {  this.membername = function (...) {...};}
後記

Douglas Crockford的這篇文章為我們寫出更優美的JavaSciprt程式奠定了基礎,為我們建立出更合理的物件導向應用和架構帶來了可能。在這篇譯文快要完成的時候,驚詫的發現作者網站上出現了一個本文中文版的連結。好事!有越來越多的中國人開始關注這些“邊邊角角”的技術。雖然做了重複工作,但一樣希望各位能從這篇文章中有所收益。也希望有更多的人能投入到原創和翻譯前端技術文章中來,在多數人浮躁的時候,我們需要更多基礎性的工作。一周一篇不多,一年一篇不少,只要開始了就行!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.