2014-03-31 45 views
-1

讓我們創建一個簡單的構造函數:構造函數:這裏的「公共」性質位於內存上運行時

function User(firstName) { 
    this.firstName = firstName; 
    this.sayHi = function() { 
     console.log('Hi, my name is ' + this.firstName); 
    }; 
} 

很明顯,我們不能這樣寫代碼:

console.log(User.firstName); //undefined 
console.log(User.sayHi);  //undefined 

讓我們畫用戶構造函數對象如何位於內存運行時:

 
______________ 
|    | 
| User  | 
|______________| 
| prototype | 
|______________| 
|  name  | 
|______________| 
| length | 
|______________| 
| arguments | 
|______________| 

所以,我們知道原型,姓名,長度和參數屬性是任何函數對象的默認值。事實上,函數對象中沒有字段firstName和sayHi。

所以,問題是: 在內存中的位置屬性 「名字」 和 「sayHi的」,直到解釋調用代碼是這樣的:提前

var user = new User('Bob'); 

感謝

+0

你會想要使用setters和getters。例如User.getfirstname()。試圖公開訪問私有變量是不好的OOP。不只是壞,但平原,錯誤。 – Fallenreaper

+0

只有將它們添加到構造函數中的對象後,它們纔會存在。 – Musa

+0

這個問題不是關於面向對象的優點或錯誤。我談論的是內存問題 - 在用「新」關鍵字解析構建之前,運行時解釋器在哪裏定位公共屬性? –

回答

1

所以問題是:在位於內存中的屬性「firstName」和 「sayHi」中,直到解釋器調用代碼如下:

var user = new User('Bob');

在你的例子中,沒有屬性firstNamesayHi直到你創建一個新的用戶對象。 User對象的構造函數在它爲其分配值時在由new運算符創建的對象上創建這些屬性。那時,這些屬性就創建了。

這是沒有什麼不同,如果我有:當我分配給它

var x = {}; 
x.foo = "Hello"; 

「富」屬性被自動創建。在我分配給它之前,該財產不存在。你的對象一樣。

現在,如果您在定義對象時使用了.prototype,那麼它會是一個不同的故事(屬性將在原型中定義並自動成爲新對象的一部分),但是您定義的方式你的新對象這些屬性在對象被創建和構造器代碼運行之前不存在。


你可以使用此代碼證明給自己:

function User(firstName) { 
    console.log(this.hasOwnProperty("firstName")); 
    this.firstName = firstName; 
    this.sayHi = function() { 
     console.log('Hi, my name is ' + this.firstName); 
    }; 
} 

http://jsfiddle.net/jfriend00/qfat6/


下面是不是提前知道動態創建的屬性的極端的例子。

var obj = {}; 
var propName = window.prompt("Enter property Name"); 
if (propName) { 
    var propValue = window.prompt("Enter property Value"); 
    if (propValue) { 
     obj[propName] = propValue; 
    } 
} 

如果用戶輸入在所述第一提示,「年齡」和「45」中的第二提示,然後OBJ將有一個與"45"的值命名age屬性。此代碼在該代碼運行之前不存在,並且不能提前知道。它只是在代碼運行時根據需求創建,並要求創建代碼。在JavaScript中指定一個不存在的對象屬性只是創建該屬性。


您已經詢問了有關代碼存儲方式/位置的更多問題。我可以在這個主題上稍微解釋一點,但是細節或者如何將內容存儲在javascript中完全是特定於實現的。它不像C或C++,其中對象具有非常特定的內存表示。像Javascript這樣的解釋性語言並不具備這一點。

當代碼初始分析時,會爲用戶功能創建一個Function對象。那麼Function對象就具有許多屬性,這些屬性會包含對它的代碼的引用。 Javascript引擎如何以及在哪裏存儲代碼完全取決於特定的Javascript實現,並且可能因實現選擇如何管理內存而有所不同。它沒有在標準中規定,並且不需要在不同的實現中實現相同的代碼存儲。唯一必須是true的是,當調用該函數時,解釋器知道如何檢索該Function對象的代碼並執行它。

+0

我想你不明白我的問題。 我在談論內存中的屬性之前,我們使用構造函數創建了一個對象。 1. \t解釋器像內存中的字符串數組一樣加載js代碼。 2. \t然後解釋器找到構造函數。 3. \t解釋器解析它並創建一個函數對象(空的) 但是他如何知道當我們編寫代碼時應該創建哪些字段: var user = new User(); 你應該明白,無論如何解釋器知道用戶對象應該包含什麼字段。口譯員如何理解它應該是什麼領域? –

+0

@YuryPetrankov - 在構造函數實際執行之前,代碼中沒有任何屬性。直到構造函數執行並且解釋器遇到指示它創建這些屬性的代碼時,解釋器才知道這些字段。在像你這樣的代碼中,Javascript會在運行時添加這些屬性。在執行構造函數之前存在於內存中的唯一的東西是字符串「firstName」作爲代碼分配函數的一部分。它在代碼中,而不是在一個對象中。 – jfriend00

+0

@YuryPetrankov - 我想我確實回答了你確切的問題。這些屬性不存在UNTIl構造函數被執行,然後解釋器遇到創建屬性的代碼。 Javascript與C++等其他語言不同。 Javascript可以隨時動態地創建屬性,並且不必提前定義屬性。 – jfriend00