对此感到困惑 - 得到错误“this.myfuntion()不是函数”

时间:2012-08-08 19:57:44

标签: javascript jquery

背景:我正在尝试编辑zen cart水平弹出菜单,以使popout在菜单中内联打开。我遇到的问题是我正在努力解决随之而来的javascript / jquery。

在没有发布整个事情的情况下,代码的结构是这样的:

(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 show来打开元素,所以我尝试了这个:

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);
                });
            }
        }

但我得到了这个 - > TypeError:this.finishOpeningChild不是函数

现在,这个js还有很多其他的东西,所以我不想让这里的人为我做我的工作,但我希望如果有人可以向我解释为什么这个功能不是功能我可以休息一下。

注意:我认为这与“this”的范围有关,但在两个版本的代码中,它的值似乎完全相同。

我知道这是一个很长的问题,但非常感谢你的帮助。

3 个答案:

答案 0 :(得分:2)

函数中this的值称为函数运行的“上下文”。通常,每当您将回调函数作为参数传递时(与$(divref).show(function() {...})一样),该函数可以在任何上下文中运行回调。在这种情况下,jQuery show函数选择在动画元素的上下文中运行其回调。

但是,您希望在匿名回调函数定义时访问this的值,而不是在运行时访问this。这里的解决方案是将self的外部值存储在一个变量(传统上称为this.slideChildMenu = function() { //... var self = this; $(divref).show(function(){ self.finishOpeningChild(divref, ulref); }); } )中,该变量包含在新定义的函数的范围内:

{{1}}

答案 1 :(得分:1)

我认为jQuery选择器已经改变了this的范围。

在您的示例$(this);中,将引用根据jQuery api文档设置动画的对象:

  

如果提供,则动画完成后将触发回调。这对于按顺序将不同的动画串联在一起非常有用。回调不会发送任何参数,但这将设置为动画的DOM元素。如果动画了多个元素,请务必注意每个匹配元素执行一次回调,而不是整个动画执行一次。

如果有问题的对象已实例化,您可以使用点表示法调用它而不使用this

bigFunc.finishOpeningChild(divref, ulref);

答案 2 :(得分: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
}

通常会让跟踪变得容易一些。