2009-06-25 54 views
7

閱讀JavaScript的prototypical inheritance model了一下後,我改變我的構造一類的風格從更好的方式來訪問私有成員的Javascript

var Some_Class = function() { 
    this.public_method = function() { 
    }; 
    (function() { 
     // constructor 
    }).call(this) 
} 

var Some_Class = function() { 
    (function() { 
     // constructor 
    }).call(this) 
} 
Some_Class.prototype.public_method = function() { 
}; 

雖然我明白,這是一個良好的做法,但我不允許從公共方法訪問私人方法

var Some_Class = function() { 
    var private_member = 'whatever'; 

    (function() { 
     // constructor 
    }).call(this) 
} 
Some_Class.prototype.public_method = function() { 
    return private_member; // not possible 
}; 

通過文章here(封閉創建構造函數)看完後,然後我來到了這個

var Some_Class = function() { 
    var private_member = 'whatever', 

    private_method = function(_some_value) { 
     // private method implementation 
    }; 

    if(!arguments.callee.prototype.public_method) { 
     arguments.callee.prototype.public_method = function() { 
      private_method.call(this, private_method); 
     }; 
    } 

    (function() { 
     // constructor 
    }).call(this) 
} 

然而,什麼是這樣做的缺點?或者如果我想在公共方法中訪問private member,是否有更好的方法?

回答

10

使用函數範圍變量和閉包來模擬私有變量/函數是javascript社區中的一個成熟的習慣用法。如果變量確實是私有的,我認爲這種方法沒有缺點(儘管有人聲稱某些瀏覽器/主機上的高性能代碼必須注意創建了多少個閉包)。

在您的示例中,private_method(及其環境)在所有對象之間共享 - 因爲您的public_method閉包僅在第一次構建對象時創建(並綁定到構造函數的prototype屬性,該屬性設置創建的對象的內部原型鏈) - 所以使用的private_method只是第一次創建的private_method。

下面是一些示例代碼,將有助於說明這是怎麼回事:

 
    var global = 1; 

    var Some_Class = function() { 
    var private_method = 'whatever'; 
    var now = ++global; 
    print("outer now: " + now); 
    private_method = function(_some_value) { 
     // private method implementation 
     print("inner now: " + now); 
    }; 

    if(!arguments.callee.prototype.public_method) { 
     arguments.callee.prototype.public_method = function() { 

      private_method.call(this, private_method); 
     }; 
    } 

    (function() { 
     // constructor 
    }).call(this) 
} 

new Some_Class().public_method(); // outer now: 2, inner now: 2 
new Some_Class().public_method(); // outer now: 3, inner now: 2 
new Some_Class().public_method(); // outer now: 4, inner now: 2 

你確定這是你想要的嗎?

如果你的private_method不需要引用封閉對象的狀態,那麼我看到你按照自己的方式做事情沒有什麼好處。

我最常做的(如果我必須使用「新」創建我的對象)如下:

 
function MyClass() { 
    var private_var = 1; 
    function private_func() 
    { 

    } 
    this.public_func = function() 
    { 
    // do something 
    private_func(); 
    } 
    this.public_var = 10; 
} 

var myObj = new MyClass(); 

對這個缺點的方法是,每次通過構造對象「新」你重新創建所有關閉。但除非我的配置文件告訴我這個設計選擇需要優化,我更喜歡它的簡潔和清晰。

我也沒有看到好處在你做下面的代碼之一:

 
    (function() { }).call(this); // call the constructor 

你爲什麼要建立在你的構造一個單獨的範圍是什麼?

+0

感謝您澄清,第二個問題...我想這可能是因爲我仍然不太熟悉對象模型,並希望使我的代碼類似於OOP代碼在php/java/other OOP編程語言 – Jeffrey04 2009-06-25 06:32:40

11

我的回答是不回答:JavaScript中沒有內置的private訪問權限,但沒關係,因爲YAGNI。以下是我在做我的代碼private成員:

function Some_Class() { 
    this._private_member = 'whatever'; 
} 

Some_Class.prototype._private_method = function() { 
}; 

這是不夠好。當private的唯一真正目的是爲了保護自己... ...自己時,跳過籃球真的不值得。

(我這樣說是花了很多時間自己帶密封蓋和原型設計的每一個排列玩耍,就像你的,最後說:「擰它,它不值得」。)

+0

我同意。在不支持它的語言中強制僞造私人訪問通常意味着UR會發生改變。 – Triptych 2009-06-25 03:48:25

+0

@Triptych - 雖然我一般都認爲,如果你必須打好設計好的語言來做你想做的事情,那麼你應該重新考慮你的設計。但是,在這種情況下,通過函數作用域變量和閉包來模擬私人訪​​問被許多熟知並且經驗豐富的JavaScript程序員認可爲自然的javascript成語。 – 2009-06-25 04:29:54

+0

+1一個副作用是所有古怪的封閉計劃傾向於打破許多IDEs代碼助手 – 2012-04-02 22:26:27

1

如果您還沒有這樣做已經看到了這個JavaScript Module Pattern,它允許您訪問公共職能範圍內的私人方法和變量等。

0

與原型,而不僅僅是單身。問題是,當是子類化的時候,我的子類無法訪問私有成員

1

迴應John Kugelman:在JavaScript中創建私有成員是不可能的。和它一起生活。即使你創建一個這樣的外殼:

function SomeClass() { 

    var _private = 0; 
    this.public_acessor = function() {return _private}; 
} 

任何用戶仍然可以寫:

SomeClass._not_private_anymore = 1; 
SomeClass.public_acessor = function() {return this._not_private_anymore}; 

最後,你不能相信任何公共成員是你聲明的一樣。如果有人打破你的代碼,他會!另一個用戶不會因爲它的用處而破壞你的代碼。