简体   繁体   English

Javascript:无法调用undefined方法

[英]Javascript: Cannot call method of undefined

This may be a common error, but I can't find another way of doing this. 这可能是一个常见的错误,但我找不到另一种方法。 I'm creating a timeline showing multiple projects using timeline.js with the following code 我正在使用timeline.js创建一个显示多个项目的timeline.js其中包含以下代码

function createTimeline(){
        for(var length = data.section.length,i = 0; i < length; i++){
            var divWrapper = document.createElement("div");
            if(i != data.section.length - 1)
                divWrapper.setAttribute('class','timelineWrapper');
            $('body').append(divWrapper);
            layer[i] = new links.Timeline(divWrapper);
            links.events.addListener(layer[i], 'rangechange',
                function(){
                    var that = this;
                    var range = layer[i].getVisibleChartRange();
                    for (var j = 0; j < layer.length; j++){
                        if(j != i){
                            layer[j].setVisibleChartRange(range.start, range.end);
                        }
                    }
                }
            );
            layer[i].draw(data.section[i].project, options);   
        }
    }

It gives the error Cannot call method 'getVisibleChartRange' of undefined . 它给出了错误Cannot call method 'getVisibleChartRange' of undefined What is the problem here? 这里有什么问题? Why is layer[i] undefined? 为什么layer [i]未定义? It is not being detected during the event rangechange itself. 在事件范围更改期间未检测到它。

The issue is caused because the unnamed function used as event handler uses its parent scope's i variable. 导致该问题是因为用作事件处理程序的未命名函数使用其父作用域的i变量。 At the end of your loop, i==data.section.length in this scope. 在循环结束时,i == data.section.length在此范围内。

This is also the i value for all your events handlers. 这也是所有事件处理程序的i值。 Because of this, layer[i] is undefined, and this is causing the error message. 因此,layer [i]未定义,这导致错误消息。

The easiest way to address this issue is to create a functionBuilder function taking i as parameter and returning a new function (your handler). 解决此问题的最简单方法是创建一个函数构造函数,将i作为参数并返回一个新函数(您的处理程序)。 In this returned handler's direct parent's scope, i value will be the parameter you passed to the functionBuilder function. 在此返回的处理程序的直接父级作用域中,i值将是您传递给functionBuilder函数的参数。

I'll post some code example later today, as soon as I have access to a pc (no way I can type that from a tablet :o) ) 我今天晚些时候会发布一些代码示例,只要我可以访问一台电脑(我无法从平板电脑输入:o))

EDIT: I've been too slow... mc10 posted more or less what I wanted to post :o) 编辑:我太慢了... mc10或多或少发布了我想发布的内容:o)

In case you don't understand why this works, or what closures, scopes or bind means, here is an old but complete explanation: http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html 如果您不理解为什么这样做,或者闭包,范围或绑定意味着什么,这里有一个古老而完整的解释: http//blog.niftysnippets.org/2008/02/closures-are-not-complicated。 HTML

You must bind i within a closure to save its value for your addListener call, as i is undefined when the function in your addListener later gets called. 您必须在闭包内绑定i以保存其addListener调用的值,因为稍后调用addListener的函数时, i将未定义。 Try replacing the third argument of your addListener call with the below: 尝试使用以下代码替换addListener调用的第三个参数:

(function(i) {
    return function() {
        var that = this;
        var range = layer[i].getVisibleChartRange();
        // Rest of code
    };
}(i)); // Anonymous function binds i in a closure

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM