2013-11-25 88 views
1

我學習JavaScript和我看到w3schools.com這個例子中(是的,我知道w3fools):爲什麼JavaScript中用作對象構造函數的函數需要分配給對象的屬性?

<script> 
function person(firstname,lastname,age,eyecolor) 
{ 
this.firstname=firstname; 
this.lastname=lastname; 
this.age=age; 
this.eyecolor=eyecolor; 

this.changeName=changeName; 
function changeName(name) 
{ 
this.lastname=name; 
} 

} 
myMother=new person("Sally","Rally",48,"green"); 
myMother.changeName("Doe"); 
document.write(myMother.lastname); 
</script> 

當我試圖刪除this.changeName=changeName;部分,功能不再起作用。我的問題是爲什麼那部分需要?沒有任何解釋,它只是在那裏。

+1

這就是不建議w3schools的原因之一......如果我沒有弄錯,通過這樣做,你實際上是通過將該方法分配給實例來公開該方法 –

+0

@Bartdude我已經一直看到很多w3schools是一個不好的資源,但我一直在努力與它合作,因爲它是唯一一個有它的一切。你可能會提出任何其他選擇 – kentz

+0

@kentz我可能會建議[MDN的教程](https://developer.mozilla.org/en-US/docs/Web/Tutorials);特別是他們的[初學者JavaScript教程](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide?redirectlocale=en-US&redirectslug=JavaScript%2FGuide)。 [使用對象](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects)課程覆蓋了您在此提出的大部分內容。 **免責聲明**:我從未使用MDN開始學習,所以我不知道他們的教程對新開發人員有多大幫助(儘管他們的參考資料非常好)。 – apsillers

回答

4

我們可能重寫代碼使其更清晰:

function person(firstname,lastname,age,eyecolor) { 
    ... 
    var myChangeNameFunc = function(name) { 
     this.lastname = name; 
    } 
    this.changeName = myChangeNameFunc; 
} 

或者更短,使用匿名函數:

function person(firstname,lastname,age,eyecolor) { 
    ... 
    this.changeName = function(name) { 
     this.lastname = name; 
    } 
} 

new關鍵字創建一個新對象,允許你修改對象通過this標識符,然後返回新的對象。通過執行this.changeName=changeName,您可以將changeName函數分配給this中新創建對象的changeName屬性。

這是一個有點混亂,所以我在上面第一個例子,我做了this.changeName = myChangeNameFunc要清楚,構造函數範圍的變量myChangeNameFunc和對象屬性this.changeName是不同的變量(雖然在這種情況下,他們最終指向同一個對象)。

沒有這個賦值,myChangeNameFunc函數從不附加到新創建的對象 - 它只是一個在person構造函數中定義的函數。


一些獎金背景:

  • function(name) { this.lastname = name; }函數表達式

  • var myNameChangeFunc = function() { }指定將函數表達式賦值給構造函數中的局部變量。 (在JS的變量函數作用域的,所以myNameChangeFunc不是構造函數的訪問的外部。)

  • 功能changeName(){}是一個函數定義。這與var changeName = function() { }基本相同,除了賦值被「提升」到包含函數的頂部(所以想象它是構造函數的第一行)。

因此,該函數最初存儲在構造函數局部變量中。通過將其存儲在this的屬性中,它將成爲構造對象的一種方法,而不僅僅是構造函數的本地函數。

+0

所以'myChangeNameFunc'是某種自動指向同名函數的變量? 而我提供的例子中的changeName函數從來沒有以任何方式實際鏈接到person函數? 此外,這是否意味着我必須這樣做'this.changeName = changeName;'部分與每個函數,我想從另一個對象的實例調用? – kentz

+0

如果您想要在通過此對象的實例調用對象的閉包中定義的方法,那麼您肯定需要將此函數「分配」給對象屬性。如果你不這樣做,你只能從對象內部調用該方法,使其成爲一種「私有方法」 –

3

單獨看,function changeName是本地的person構造函數的作用域,因此在該範圍之外不可見 - 它有點像一個私有方法。

如果您希望從外部世界可以調用該方法,那麼您必須在新創建的人員上創建一個屬性並將其值設置爲該函數。這樣它可以被訪問爲myMother.changeName(就像任何其他屬性)並被調用。

0

讓我們看看這個例子:

var object = {}; 

function someFn() {} 

在這裏你可以清楚地看到,object沒有someFn成員。如果你想objectsomeFn功能,我們需要做的:

object.someFn = someFn; 

那麼在你的榜樣,你可以想像,this是前面的例子中objectchangeName只是一個在構造函數的作用域中聲明的私有變量,因此如果您希望它成爲實例化對象上的公共函數,則需要將它分配給this

相關問題