2012-08-08 70 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