2012-08-08 20 views
0

背景:我試圖編輯一個禪宗購物車水平彈出菜單,使彈出菜單內嵌在菜單內。我遇到的問題是我正在努力讓自己的頭腦圍繞它附帶的javascript/jquery。困惑 - 獲取錯誤「this.myfuntion()不是一個函數」

沒有張貼了整個事情的代碼的結構是這樣的:

(declare some vars) 

//some functions like this: 
function funcname(obj) { 
//do something 
} 

//then one big master function like this: 
function bigfunc(arg1, arg2, arg3, arg4, arg5) { 

//declare some vars based on this 
this.varname1=varname1; 
this.varname2=varname2; 

//declare some functions inside the big function 
this.innerfunc1= function() { 
//do stuff 
} 

this.innerfunc2= function() { 
//do stuff 
} 

}//end of big function 

//then goes on to declare init function 

function initfunc(){ 
//this creates new bigfunc(arg1 arg2 arg3...) for each main menu item 
} 

//finally calls init function with 
window.onload = initfunc(); 

現在到我的困惑 -

1)首先澄清,我在思考基礎上正確的這在bigfunc()中是浮動的,而且它是用new bigfunc()調用的,這是創建一個對象的事實?

2)我現在的問題是與內部bigfunc的功能之一(),它看起來像這樣:

this.slideChildMenu = function() { 
     var divref = this.children[0].div; 
     var ulref = this.children[0].ul; 
     var maxwidth = this.children[0].width; 
     var nextWidth; 
     if (this.isMouseOnMe || this.isMouseOnChild()) { 
      nextWidth = divref.offsetWidth + slideSpeed_out; 
      if (nextWidth >= maxwidth) { 
       this.finishOpeningChild(divref, ulref, maxwidth); 
      } else { 
       ulref.style.left = nextWidth - maxwidth + "px"; 
       divref.style.width = nextWidth + "px"; 
       setTimeout("slideChildMenu('" + this.getId() + "')", slideTimeout_out); 
      } 
     } 

現在我的計劃是要改變這種使用jquery顯示打開元素,所以我想這:

this.slideChildMenu = function() { 
     var divref = this.children[0].div; 
     var ulref = this.children[0].ul; 
     if (this.isMouseOnMe || this.isMouseOnChild()) { 
      $(divref).show(function(){ 
        this.finishOpeningChild(divref, ulref); 
       }); 
      } 
     } 

但我得到這個 - >類型錯誤:this.finishOpeningChild不是一個函數

現在,有很多其他的東西在這個事情JS所以我不會博士在這裏問某人爲我做我的工作,但我希望如果有人能向我解釋爲什麼這個功能不是一個功能,我可能能夠解決其他問題。

注意:我認爲這與「this」的範圍有關,但是這兩個版本的代碼中的值似乎完全相同。

我知道這是一個很長的,但你的幫助,不勝感激。

回答

2

函數中的this的值稱爲函數運行的「上下文」。一般來說,只要你傳遞一個回調函數作爲參數(就像你使用$(divref).show(function() {...})),該函數可以在任何需要的上下文中運行回調函數。在這種情況下,jQuery show函數選擇在被動畫元素的上下文中運行其回調。

但是,您希望在匿名回調函數爲時定義爲而不是在運行時訪問this的值。這裏的解決方案是存儲在一個變量中(傳統上被稱爲self),它包含在新定義函數的範圍this外值:

this.slideChildMenu = function() { 
    //... 
    var self = this; 
    $(divref).show(function(){ 
     self.finishOpeningChild(divref, ulref); 
    }); 
} 
+0

謝謝,這正是我所需要的 - 沒有更多的錯誤...仍然無法正常工作,但我想我現在有機會修復它。再次感謝。 – WebweaverD 2012-08-08 21:03:19

+0

不錯的建議。我已經完成了它,因爲它可以讓您在更改之前捕獲當前範圍。 +1! – PJH 2012-08-08 21:34:49

1

我在想,jQuery選擇器已經改變了this的範圍。

在您的例子$(this);將參照每jQuery的API文檔進行動畫反對:

If supplied, the callback is fired once the animation is complete. This can be useful for stringing different animations together in sequence. The callback is not sent any arguments, but this is set to the DOM element being animated. If multiple elements are animated, it is important to note that the callback is executed once per matched element, not once for the animation as a whole.

如果有問題的對象實例化時,你可以用點符號調用它,而無需使用thisbigFunc.finishOpeningChild(divref, ulref);

+0

感謝你的建議 - 對象已經在被稱爲這一點(因爲這個函數是在對象內),但改變爲建議給出的錯誤:TypeError:bigfunc.finishOpeningChild不是一個函數 – WebweaverD 2012-08-08 20:36:15

1

你可能對範圍有點困惑,但並不總是很容易跟蹤,但做更像這樣的事情:

var site = { 
    init: function(elm) { 
     self=site; 
     self.master.funcname2(self.varname1, elm); //call function in master 
    }, 
    funcname: function(obj) { 
     //do something 
    }, 
    varname1: 'some string', 
    varname2: 3+4, 
    master: function() { 
     this.varname3 = sin(30); 
     this.funcname2 = function(stuff, element) { 
      site.funcname(element); //call function in 'site' 
      var sinus = site.master.varname3; //get variable 
     } 
    } 
} 

window.onload = function() { 
    var elm = document.getElementById('elementID'); 
    site.init(elm); //call init function 
} 

通常使它更容易跟蹤。

+0

謝謝你的提示 - 我肯定不會像這樣寫它,但它是它是,我沒有時間重寫整個事情,所以我需要一個快速和骯髒的修復。 – WebweaverD 2012-08-08 21:02:20