2011-06-25 48 views
3
var name = "The Window"; 
var object = { 
  name : "My Object", 
  getNameFunc : function(){ 
    return function(){ 
      return this.name; 
    }; 
 } 
}; 
alert(object.getNameFunc()()); 

當我測試代碼。結果是The Window。但我認爲this.name;應該是My Object。我的想法出了什麼問題。爲什麼結果不是我的對象?

當我在添加var之前name : "My Object",它顯示一個錯誤。爲什麼?

+0

爲什麼你裏面'getNameFunc'另一個內部匿名函數?你可以做'return this.name'; – vsync

+0

我刪除getNameFunc中的另一個內部匿名函數,但代碼無法工作。 var name =「The Window」; var object = { name:「My Object」, getNameFunc:function(){ return this.name; }; }; alert(object.getNameFunc()); – zhuanzhou

+0

檢查下面的答案,我已經爲它創建了一個代碼片段 – vsync

回答

3

this一個函數內部是「接收器」它是在調用。

即,

  1. 供構建x.f()this函數(f)內將評估爲的x值。

  2. 對於所有其他情況,this將評估爲window在被調用的函數內部。(功能callapply,並bind也改變this ......但那是另一回事。)

在投稿例如第二功能(具有this.name)是使用調用x.f()表格等等thiswindow對象。

「簡單修復」是使用一個封閉件:(第一功能x.f()形式調用,並且因此this相同object,其如預期我們在目前捕捉的this值。通過與self創建的關閉和返回的功能範圍。)

getNameFunc : function() { 
    var self = this 
    return function() { 
     return self.name 
    } 
} 

不過,我可能會考慮其他的設計,這取決於:)

編碼愉快。


進一步澄清,發表評論:

...那是因爲你使用的是circle.getArea()它的形式是x.f()的。因此getArea函數內的this評估爲circle

在發佈的代碼中,您連續調用兩個不同的函數。想象一下,寫這樣的代碼:

var nameFunc = object.getNameFunc() 
nameFunc() 

第一個函數調用中的x.f()的形式,因此this內getNameFunc是object評價。但是,在第二行中,函數(nameFunc)是而不是x.f()的形式調用。因此,nameFunc中的this(從getNameFunc返回的函數)將評估爲window,如上所述。

+0

哦,對不起 - 我在發佈我的文章之前忽略了你的文章。 –

+0

@JanTuroň不要道歉;-) – 2011-06-25 07:49:32

+0

偏偏這個代碼:var圈= { 半徑:9, 的getArea:函數(){ 回報 (this.radius * this.radius)* Math.PI; } };這個.radius是9? – zhuanzhou

2

您需要保存對對象this的引用,因爲
範圍在您在getNameFunc內返回的內部函數內發生了更改。

var name = "The Window"; 

var object = { 
  name : "My Object", 

  getNameFunc : function(){ 
    var that = this;  // the reference to 'this' 
    return (function(){ // I've fixed your function to execute itself 
      return that.name; 
    })(); 
  } 
}; 

alert(object.getNameFunc()); 

你不能做VAR對象內literal..only裏面的內心
功能,如內部 「getNameFunc

進一步閱讀 「這一」 範圍In this article

無論如何,你應該改變你的getNameFunc功能就像這樣:

getNameFunc : function(){ 
    return this.name;      
} 

使用apply另一種方法是:

getNameFunc : function(){ 
    return (function(){ return this.name }).apply(this); 
} 
+0

其中內部函數的範圍是Window對象(使其更易混淆;) –

+0

「修復」會打破'getNameFunc'的語義,因爲它現在返回一個...非函數:(:(並且增加了很多多餘的代碼。) – 2011-06-25 08:13:34

+0

不,它可能不是你可能使用他的方法而不是我的。這工作很好,它返回它應該返回 – vsync

1

正如其他人寫的,你需要的目標是this。我相信這一段代碼將幫助您瞭解如何this在JavaScript的工作

var name = "The Window"; 
var object = { 
    name : "My Object", 
    getNameFunc : function(){ 
    that = this; // targeting this 
    return function() { 
     return that.name; 
    }; 
    } 
}; 
alert(object.getNameFunc()()); // it is My Object now 
+0

正如其他人寫的... – vsync

+0

是的,對不起,我忽略了它 - 該死的字符... –

+2

請確保使用'var = this'。沒有'var'變量'that'將會是一個*全局屬性*(真的是'window.that'),而不是一個綁定在閉包中的變量:(這在這裏不重要,但它會導致除了最微不足道的情況外,還有很多微妙的錯誤 – 2011-06-25 07:50:14

2
var myObject = { 
    name:'My Object' 
}; 

console.log(myObject.name); 
console.log(myObject['name']); 

有各種其他的方式來使JavaScript對象。

this是一個隱藏的參數,自動從調用函數傳遞給被調用者。傳統的方式是要做到:

function MyObject() { 
    this.name = 'My Object'; 
} 
myObject = new MyObject(); 

console.log(myObject.name); 

現在,你可能只需要使用瓶蓋:

[**edit**: redacted because not a good method] 

現在你可能只是使用閉,正確:

function makeObject() { 
    var THIS = {}; 

    THIS.name = 'My Object'; 
    THIS.sayMyName = function() { 
     return THIS.name+" is my name"; 
    } 

    return THIS; 
} 

有跡象表明,支持許多圖書館「更聰明」的方式來製作物體。

+0

你最後一個例子沒有任何意義..你爲什麼要將'name'定義爲VAR,然後參考以名字命名:名字... – vsync

+1

它是有道理的......以一種奇怪的脆弱的方式。他'sayMyName'函數綁定到閉包的'name'變量,但是可以通過'name'屬性直接訪問'name' ...因爲timmy.name =「TIMMMEH!」而變得很脆弱。 timmy.sayMyName()'可以導致一些非常有趣的結果。這就是說,與埃德*新* getters/setters。 5,類似這樣的東西可以完全用閉包來實現......(在它需要getName/setName或類似之前) – 2011-06-25 08:17:07

+0

@pst:謝謝,我感覺有關這種方法的一些東西是關閉的。 – ninjagecko

1
var object = { 
  name : "My Object", 
  getNameFunc : function(){ 
    return (function(){ 
      return this.name; 
    }).bind(this); 
 } 
}; 

.bind,使用ES5-shim對瀏覽器的支持

+0

+1我對Ed的學習已經很晚了。 5 - 美孚。 – 2011-06-25 08:05:00

+0

美麗的代碼,我喜歡它。不知道這個綁定的事情,這種類型的方法有沒有名稱? – vsync

+0

嗯..這不適用於我的FF4 – vsync

相關問題