[英]How can I make privileged JS methods?
我希望能夠調用處理私有數據的子功能。 目前我有這個:
var myFunction4 = function() {
this.secret1 = 0;
this.secret2 = 0;
var that = this;
this.iterate1 = function(){
return that.secret1++;
}
this.iterate2 = function(){
return that.secret2++;
}
this.addSecrets = function(){
return that.secret1 + that.secret2;
}
return {
iterate1: this.iterate1,
iterate2: this.iterate2,
addSecrets: this.addSecrets,
}
};
不好的是,要調用其中一種方法,我必須這樣做:
myFunction4().iterate1();
我想每次訪問一個方法都執行myFunction4()
。 這不僅效率低下,而且每次都會重置secret1
因此我無法對其進行迭代。 我嘗試使用new
運算符,但是它公開了secret1
和secret2
,並且弄亂了嵌套函數的能力。
var myFunction3 = function() {
this.secret1 = 0;
this.secret2 = 0;
this.iterate1 = function(){
return this.secret1++;
}
this.iterate2 = function(){
return this.secret2++;
}
this.addSecrets = function(){
return this.secret1 + this.secret2;
}
};
var f3 = new myFunction3();
f3.secret1; // exposes the secret!
有關更多示例,請參見此JSFiddle底部的控制台日志 。
我怎么能同時擁有私有和公共var / method的函數,而這些函數卻保留了它們的值並且不需要多次調用?
盡管其他答案絕對正確且正確,但是在javascript中模擬OOP行為時還需要考慮另一個問題。
當我們嘗試使用公共方法作為異步方法時, 函數執行上下文問題將使我們難以忍受。 打回來。
神奇的是, this
將指向我們在OOP世界中期望的不同對象。
當然,有很多方法可以綁定上下文,但是為什么要在非OOP js中定義“類”后再擔心呢?)
這里有一個簡單的解決方案, this
:不要使用this
。 讓封閉重構this
出來;)
var myFunction4 = function() {
// we could inherit here from another 'class' (object)
// by replacing `this` with e.g. `new SuperClass()`
var that = this;
// 'private' variables
var secret1 = 0;
var secret2 = 0;
// 'public' variables
that.somePublicVar = 4;
// 'private' methods
var somePrivateMethod = function(){
secret2 = 77;
that.somePublicVar = 77;
}
// 'public' methods
that.iterate1 = function(){
return secret1++;
}
that.iterate2 = function(){
return secret2++;
}
that.addSecrets = function(){
return secret1 + secret2;
}
return that;
};
var f = new myFunction4();
console.log( f.iterate1() ); // 0
console.log( f.iterate1() ); // 1
console.log( f.secret1 ); //undefined
console.log( f.somePublicVar ); //4
試試看(關閉電源!):
var myFunction3 = function() {
var secret1 = 0;
var secret2 = 0;
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function(){
return secret1 + secret2;
}
};
var f3 = new myFunction3();
現在只有方法是暴露的
編輯版本:
如果您不想在每次調用子方法時都執行主函數,則可以稍作改動,並使用IIFE(立即調用的函數表達式)的功能
var myFunction4 = (function() {
var secret1 = 0;
var secret2 = 0;
var iterate1 = function(){
return secret1++;
}
var iterate2 = function(){
return secret2++;
}
var addSecrets = function(){
return secret1 + secret2;
}
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets
}
}());
然后,您可以使用以下代碼:
myFunction4.iterate1();
myFunction4.iterate2();
myFunction4.addSecrets();
希望這對您有幫助
我通常只使用工廠模式來創建對象,除非我絕對需要具有原型繼承的性能優勢。
使用工廠模式也意味着你不必應付不斷變化的值, this
在不同的上下文。
var factory = function() { // internal private state var state = { secret1: 0, secret2: 0 } function iterate1(){ return state.secret1++; } function iterate2(){ return state.secret2++; } function addSecrets(){ return state.secret1 + state.secret2; } function __privateMethod() { // this is private because it's not on the returned object } // this is the public api return { iterate1, iterate2, addSecrets } } // create a secret module var secret = factory() console.log( secret.iterate1(), // 0 secret.iterate2(), // 0 secret.addSecrets(), // 2 secret.secret1, // undefined secret.secret2 // undefined ) // you can even create more with the same factory var secret2 = factory()
從第二個片段的解釋中我了解到,您需要實例化對象之間的sharedPrivate
。 您不能使用構造函數,工廠或模塊之類的經典對象創建模式來執行此操作。 這可以通過在構造函數的原型中的關閉狀態下獲取一個私有變量來實現,這樣就不會在每次創建對象時重置該私有變量,同時為實例化的對象提供了必要的方法來私下訪問,修改和共享它。
function SharedPrivate(){ var secret = 0; this.constructor.prototype.getSecret = function(){return secret} this.constructor.prototype.setSecret = function(v){ secret = v;} this.constructor.prototype.incrementSecret = function(){secret++} } var o1 = new SharedPrivate(); var o2 = new SharedPrivate(); console.log(o1.getSecret()); // 0 console.log(o2.getSecret()); // 0 o1.setSecret(7); console.log(o1.getSecret()); // 7 console.log(o2.getSecret()); // 7 o2.incrementSecret() console.log(o1.getSecret()); // 8
獲得類似結果的另一種方法是
function SharedPrivate(){ var secret = 0; return {getS : function(){return secret}, setS : function(v){secret = v}, incS : function(){secret++} }; } sharedProto = SharedPrivate(); // secret is now under closure to be shared var o1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__ var o2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__ o1.setS(7); // o1 sets secret to 7 console.log(o2.getS()); // when o2 access it secret is still 7 o2.incS(); // o2 increments the secret console.log(o1.getS()); // o1 can access the incremented value
您為什么不嘗試顯示模塊模式
var myFunction4 = function() {
var secret1 = 0,
secret2 = 0,
iterate1 = function(){
return secret1++;
},
iterate2 = function(){
return secret2++;
},
addSecrets = function(){
return secret1 + secret2;
};
// public functions and properties
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets,
}
}();
myFunction4.iterate1(); // is available
myFunction4.secret2; // is private and not available outside of myFunction4
希望能幫助到你
基本模式:
var myFunction = function() {
var that = this;
var secret1 = 0;
var secret2 = 0; // private
this.public1 = 0; // public
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function() { // public
return privateMethod();
}
var privateMethod = function() { // private
return secret1 + secret2;
}
return this; // return function itself!
};
var myFn = new myFunction();
myFn.public1 // 0
myFn.secret1 // undefined
myFn.addSecrets();
我建議您閱讀Addy Osmani的優秀的Learning JavaScript Design Patterns 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.