2012-01-12 49 views
4

我正在做一些JavaScript [R & d和,雖然我讀過JavaScript權威指南的JavaScript面向對象的編程,我仍然有一些小問題得到我的課程基於面向對象的面向對象和基於對象的面向對象的面向對象方法。的Javascript「私」與實例屬性

我喜歡模塊。名稱空間,子類和接口。 w00t。下面是我用玩什麼:

var Classes = { 
    _proto : { 
     whatAreYou : function(){ 
      return this.name; 
     } 
    }, 
    Globe : function(){ 
     this.name = "Globe" 
    }, 
    Umbrella : new function(){ 
     this.name = "Umbrella" 
    }(), 
    Igloo : function(){ 
     function Igloo(madeOf){ 
      this.name = "Igloo" 
      _material = madeOf; 
     } 
     // Igloo specific 
     Igloo.prototype = { 
      getMaterial : function(){ 
       return _material; 
      } 
     } 
     // the rest 
     for(var p in Classes._proto){ 
      Igloo.prototype[p] = Classes._proto[p] 
     } 
     return new Igloo(arguments[0]); 
    }, 
    House : function(){ 
     function House(){ 
      this.name = "My House" 
     } 
     House.prototype = Classes._proto 
     return new House() 
    } 
} 
Classes.Globe.prototype = Classes._proto 
Classes.Umbrella.prototype = Classes._proto 

$(document).ready(function(){  
    var globe, umb, igloo, house; 

    globe  = new Classes.Globe(); 
    umb  = Classes.Umbrella; 
    igloo  = new Classes.Igloo("Ice"); 
    house  = new Classes.House(); 

    var objects = [globe, umb, igloo, house] 

    for(var i = 0, len = objects.length; i < len; i++){ 
     var me = objects[i]; 
     if("whatAreYou" in me){ 
      console.log(me.whatAreYou()) 
     }else{ 
      console.warn("unavailable") 
     } 
    } 
}) 

我試着去找到模塊化我的代碼(和理解原型)的最佳方式和獨立的東西展現出來。通知Globe是一個需要用new實例化的函數,Umbrella是一個單例並且已經聲明,Igloo使用了我今天工作中想到的,似乎和我希望的一樣工作,並且House是另一個函數的函數供測試用。

的這個輸出是:

Globe 
unavailable 
Igloo 
My House 

到目前爲止好。由於語法原因,Globe原型必須在Classes對象之外聲明,由於它已經存在(或實例化或...不知道這個「正確」的術語),並且Igloo具有一些聲明的閉包它適合你。

無論其...

如果我將其更改爲:

var Classes = { 
    _proto : { 
     whatAreYou : function(){ 
      return _name; 
     } 
    }, 
    Globe : function(){ 
     _name = "Globe" 
    }, 
    Umbrella : new function(){ 
     _name = "Umbrella" 
    }(), 
    Igloo : function(){ 
     function Igloo(madeOf){ 
      _name = "Igloo" 
      _material = madeOf; 
     } 
     // Igloo specific 
     Igloo.prototype = { 
      getMaterial : function(){ 
       return _material; 
      } 
     } 
     // the rest 
     for(var p in Classes._proto){ 
      Igloo.prototype[p] = Classes._proto[p] 
     } 
     return new Igloo(arguments[0]); 
    }, 
    House : function(){ 
     function House(){ 
      _name = "My House" 
     } 
     House.prototype = Classes._proto 
     return new House() 
    } 
} 
Classes.Globe.prototype = Classes._proto 
Classes.Umbrella.prototype = Classes._proto 

$(document).ready(function(){  
    var globe, umb, igloo, house; 

    globe  = new Classes.Globe(); 
    umb  = Classes.Umbrella; 
    igloo  = new Classes.Igloo("Ice"); 
    house  = new Classes.House(); 

    var objects = [globe, umb, igloo, house] 

    for(var i = 0, len = objects.length; i < len; i++){ 
     var me = objects[i]; 
     if("whatAreYou" in me){ 
      console.log(me.whatAreYou()) 
     }else{ 
      console.warn("unavailable") 
     } 
    } 
}) 

,使this.name_name(以下簡稱 「私有」 屬性),這是行不通的,而是輸出:

My House 
unavailable 
My House 
My House 

有人會友好地解釋這一個嗎?很明顯,_name在每次迭代時都會被覆蓋,而不會讀取它所附加的對象的屬性。

這一切似乎有點太冗長需要this和有點怪異IMO。

謝謝:)

+2

,因爲你的 「私人」,是全球性的。 – Raynos 2012-01-12 12:09:20

+0

我原本在那裏有'var'關鍵字,但是錯過了它。這就是爲什麼你不會在凌晨3點提問的原因;) 無論如何,感謝你的迴應,現在它更有意義並適用相同的解決方案。乾杯! – Phix 2012-01-12 17:39:35

+0

您可能感興趣的[ES5 OO sugar](http://raynos.org/blog/17) – Raynos 2012-01-12 17:51:07

回答

5

您聲明瞭一個全局變量。在聲明之後,它可以在代碼中的任何地方使用。無論您何時請求_name(更接近window._name),您將收到每次全球通。你的情況在每個函數中被替換爲_name。最後一個功能是House,並且已設置爲「我的房子」

「私人」(本地)變量的聲明必須使用var聲明

檢查了這一點:

var foo = function(a) { 
    _bar = a; 
    this.showBar = function() { 
     console.log(_bar); 
    } 
}; 
var a = new foo(4); // _bar (ie window._bar) is set to 4 

a.showBar(); //4 


var b = new foo(1); // _bar is set to 1 
a.showBar(); //1 
b.showBar(); //1 

_bar = 5; // window._bar = 5; 
a.showBar();// 5 

應該是:

var foo = function(a) { 

    var _bar = a; 
    // _bar is now visibled only from both that function 
    // and functions that will create or delegate from this function, 
    this.showBar = function() { 
     console.log(_bar); 
    }; 
    this.setBar = function(val) { 
     _bar = val; 
    }; 
    this.delegateShowBar = function() { 
     return function() { 
      console.log(_bar); 
     } 
    } 
}; 
foo.prototype.whatever = function(){ 
    //Remember - here don't have access to _bar 
}; 

var a = new foo(4); 
a.showBar(); //4 

_bar // ReferenceError: _bar is not defined :) 
var b = new foo(1); 

a.showBar(); //4 
b.showBar(); //1 

delegatedShowBar = a.delegateShowBar(); 
a.setBar(6); 
a.showBar();//6 
delegatedShowBar(); // 6 
1

如果刪除關鍵字「這」,那麼_name是在「環球報」的範圍。

看着你的代碼。

var globe, umb, igloo, house; 

globe  = new Classes.Globe(); 
umb  = Classes.Umbrella; 
igloo  = new Classes.Igloo("Ice"); 
house  = new Classes.House(); 

最後,房子將覆蓋全球範圍內名爲「我的房子」的「_name」值。