2016-10-15 22 views
0

我希望能夠調用與私人數據一起工作的子功能。目前,我有這樣的:如何製作特權JS方法?

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操作符,但是這個操作符暴露了secret1secret2,它破壞了嵌套函數的能力。

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! 

有關更多示例,請參見console logs at the bottom of this JSFiddle

我怎樣纔能有私人和公共瓦爾/方法保留其價值,不需要多次調用的函數?

回答

2

試一下(關閉電源!):

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(); 

現在只有方法exposeds

編輯後的版本:

如果你不想執行main函數每次調用時間子方法,您可以稍微改變一下您的方法並使用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(); 

希望這有助於你

+0

這樣的作品,但我仍然沒有看到如何使用該策略的子方法。 –

+0

你好,我編輯了答案,希望對你有幫助 –

1

我一般只使用工廠模式來創建對象,除非我絕對需要有原型繼承的性能優勢。

使用工廠模式還意味着您不必在不同的上下文中處理不斷變化的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()

+0

這個策略是否允許子功能?我一直在努力,而且它變得很快。 –

+0

@您可以多次描述子功能。我不明白你指的是什麼 – synthet1c

1

我從你的解釋,按您的第二個片段明白什麼是你需要的實例化的對象之間的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

1

你爲什麼不嘗試顯露的模塊模式

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 

希望它可以幫助

1

一個基本的模式:

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(); 

我建議你閱讀由阿迪·奧斯馬尼優秀Learning JavaScript Design Patterns

4

儘管其他答案絕對正確,但在模擬JavaScript中的OOP行爲時還有一個問題需要考慮。

function execution context問題會咬我們很難,當我們嘗試使用公共方法作爲例如異步。回電話。

神奇的this將指向一個不同的對象,那麼我們期望在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