Search code examples
javascriptd3.jsprototypejs

Functions don't recognize variables


I discovered prototypejs some days ago when I wanted to create a class in JavaScript. I had some functions which worked perfectly, to draw a profile as following: My Race Profile

To create this profile with any data, I wanted to create a full class.

Here is my code on codepen.

So, to explain my problem:

I declared my variables in my constructor. When I use var rp = new RaceProfile('data.json', 'markers.json');, I haven't any problems. All my variables are created with the good values.

But, when I use " rp.profile(data);", all the variables declared before are undefined. It seems all the values defined before are erased. And my code can't work because of that.

If someone know where the problem come from, let me know too :)


Solution

  • When you said "all the variables", do you talking about "xScale", "yScale" ... ? Because these variables can't be reach in profile function, indeed "var" variable is only visible on its current scope (between {}).

    To access variable in class function you have to use "this" keyword like for the dataProfile field :

    var RaceProfile = Class.create({
    initialize: function (dataProfile, dataCP) {
        this.dataProfile = dataProfile;
        this.dataCP = dataCP;
        this.xScale = d3.scaleLinear();
    }
    

    Now you can access these variables in other functions.

    Morever in JS, by default "this" is a contextual keyword, to learn more about it : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

    "this" is share through all object functions but anonymous functions have its own this (anonymous functions aren't attach to your object).

    So this can't work, you can't access xScale directly :

    profile: function (rawData) {
        d3.json(this.dataProfile, function (error, rawData) {
            // ..
            this.xScale.range([0, width]).domain(d3.extent(data, function (d) {
                return d.distance;
            }));
    

    You have to save the "this" of your object in a variable :

    profile: function (rawData) {
        var self = this;
    
        d3.json(this.dataProfile, function (error, rawData) {
            // ..
            self.xScale.range([0, width]).domain(d3.extent(data, function (d) {
                return d.distance;
            }));