What is causing the 'this' variable to be different from the anticipated value?

I'm encountering a problem with this code snippet. The 'this' variable is expected to hold 'Object Chart' on the lines where 'console.log' is used, but instead, it contains 'path.line'. As a result, the reference to xscale remains undefined. What could be causing this issue? This error seems to occur consistently in both Chrome and Firefox.

Thank you.

<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8">
<style>
body {
  font: 10px sans-serif;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 3.0px;
}
</style>
</head>
<body>
<script src="d3.v2.js"></script>
<script>
var kev_vs_rho= [{ 
values: [{x: 0.01, y: 0.2058},{x: 0.03, y: 0.2039},{x: 0.05, y: 0.2020}] }, {
values: [{x: 0.01, y: 1.6468},{x: 0.03, y: 1.6303},{x: 0.05, y: 1.6137}] }, ];
kev_vs_rho.minX=0.01;
kev_vs_rho.maxX=0.99;
kev_vs_rho.minY=0.01;
kev_vs_rho.maxY=33.66;
</script>

<div id="chart1"> </div>
<script>

"use strict";

var Chart = function ( _width, _height, _data, _div ) {
    this.data = _data;
    this.div = _div;

    this.idx1 = 0;
    this.select1 = 0;

    this.margin = {top: 30, right: 30, bottom: 30, left: 80};
    this.width = _width - this.margin.left - this.margin.right;
    this.height = _height - this.margin.top - this.margin.bottom;

    this.xscale = d3.scale.linear()
        .domain([this.data.minX, this.data.maxX])
        .range([0, this.width]);

    this.yscale = d3.scale.linear()
        .domain([this.data.minY, this.data.maxY])
        .range([this.height, 0]);

    this.lineA = d3.svg.line()
        .x(function (d) {
             console.log( this ); // <<== is 'path.line', not object Chart
             console.log( this.xscale ); // <<== undefined

             return this.xscale(d.x); // <<== undefined
             })
        .y(function (d) { return this.yscale(d.y); });

    this.svg1 = d3.select(_div).append("div").append("svg")
        .datum(_data[this.select1].values)
        .attr("width", this.width + this.margin.left + this.margin.right)
        .attr("height", this.height + this.margin.top + this.margin.bottom)
        .append("g")
        .attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");

    this.lineB = this.svg1.append("path")
        .attr("class", "line")
        .datum(this.data[this.select1].values)
        .attr("d", this.lineA);
};

var chart1 = new Chart( 960, 400, kev_vs_rho, "#chart1");

</script>
</body>
</html>

Answer №1

To ensure that this refers to a Chart object, it is essential to use it directly within the Chart constructor (not within an anonymous function passed as a parameter), in a method of a Chart object, or by manually employing call or apply with a Chart object.

A recommended approach is to explicitly assign the chart object to a variable and utilize that variable in the functions.

<script>

"use strict";

var Chart = function ( _width, _height, _data, _div ) {
    self = this;
    this.data = _data;
    this.div = _div;

    this.idx1 = 0;
    this.select1 = 0;

    this.margin = {top: 30, right: 30, bottom: 30, left: 80};
    this.width = _width - this.margin.left - this.margin.right;
    this.height = _height - this.margin.top - this.margin.bottom;

    this.xscale = d3.scale.linear()
        .domain([this.data.minX, this.data.maxX])
        .range([0, this.width]);

    this.yscale = d3.scale.linear()
        .domain([this.data.minY, this.data.maxY])
        .range([this.height, 0]);

    this.lineA = d3.svg.line()
        .x(function (d) {
             console.log( self ); // <<== 'path.line', not object Chart
             console.log( self.xscale ); // <<== undefined

             return self.xscale(d.x); // <<== undefined
             })
        .y(function (d) { return self.yscale(d.y); });

    this.svg1 = d3.select(_div).append("div").append("svg")
        .datum(_data[this.select1].values)
        .attr("width", this.width + this.margin.left + this.margin.right)
        .attr("height", this.height + this.margin.top + this.margin.bottom)
        .append("g")
        .attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");

    this.lineB = this.svg1.append("path")
        .attr("class", "line")
        .datum(this.data[this.select1].values)
        .attr("d", this.lineA);
};

var chart1 = new Chart( 960, 400, kev_vs_rho, "#chart1");

</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue encountered: Next.js version 14, Tesseract.js Error: Module not found .../.next/worker-script/node/index.js'

While working with nextjs 14 and trying to extract text from an image using the tesseract.js node module, I encountered an error where the module was not found. The specific error message I received is as follows: Error: Cannot find module '...(projec ...

Combining multiple meteor servers into a single database collection (local)

I'm currently working on a Meteor project that involves making multiple external API calls at different intervals and storing the retrieved data in MongoDB. My goal is to separate these API calls into individual "micro-services", each running on its ...

Incorrectly modifying the _locals property while rendering a MySQL result in Express/Node.js leads to the error: "Cannot assign to read only property '_

I am currently using Handlebars to display data retrieved from a MySQL query. The route is set up as shown below: var query = "SELECT col1, col2, col3 FROM table WHERE section >= " + start + " AND section <= " + end + " ORDER BY col1 ASC"; connecti ...

Horizontal Accordion Design for Cascading Style Sheets (CSS) Books

I am currently working on developing a page that features a book layout. This page will include tabs that users can expand individually. If you would like to see a working example, you can check out this link: https://codesandbox.io/s/book-layout-l28gh?fi ...

What's the best way to update the value of an angular field upon submission?

Could someone please provide instructions on how to update the myName variable when the "submit" button is pressed? Thank you! app.js: app.controller('SomeController', ['$scope', 'emails', function($scope, emails) { emails ...

What is the method to apply a class exclusively to an img tag?

While using the Cycle2 Carousel plugin, I encountered an issue with the class being set for my thumbnails. The plugin sets the .cycle-pager-active class for both images and divs, which is not ideal. I attempted to fix this by adding 'img' before ...

Retrieve the value of a dynamically generated input element within a form object

I'm trying to figure out how to reference a dynamic 'name' of an input element in a form. Can anyone help? Here's an example using HTML: <form> <input type="text" name="qty1" value="input1" /> <input type="text ...

How can we retrieve an API response using Fetch, manipulate it with JSON.stringify(), and what are the next steps in

After countless attempts, I still can't figure out what's missing here. I'm utilizing fetch to retrieve data from Mapbox: var response = fetch(myURL) .then(response => response.json()) .then(data => console.log(JSON.stringify(data))) ...

Prevent mobile view from activating when zoomed in on the screen

I've built a webpage with a responsive design that adjusts to mobile view on mobile devices or when the screen size is reduced using developer tools. While this functionality works correctly, I have noticed that the design also switches to mobile vie ...

Is your list rendering in Vue.js with AJAX ready to go?

At this moment, my Vue.js component is retrieving data from an Elasticsearch query and displaying it in a list like this: <li v-for="country in countries">{{ country.key }}</li> The issue I am facing is that I want to show users only a snippe ...

Stop the bootstrap accordion from expanding when a button in its header is clicked

Currently, I am facing an issue with two action buttons located in the header of an accordion. Here is the setup: https://i.sstatic.net/HU2Kp.png Whenever I click on one of these buttons, it toggles the accordion's state. I have attempted to use e.p ...

Upon clicking, the input texts revert to their original default values

I have a form below that is working as intended, except for one issue. When I click the 'Add' link, the texts in all the textboxes revert to their default values, as shown in the images. How can I resolve this problem? Thank you. before click: ...

Tips for retrieving corresponding values from a TypeScript dictionary object?

I am currently working with a dictionary object that is filled in the following manner: const myDictionaryElement = this.myDictionary["abc"]; In this case, myDictionaryElement contains the values: ACheckStatus: "PASS" QVVStatus: "READY" VVQStatus: "READ ...

Display only one dropdown menu at a time

Hey there, I'm currently working on a dropdown menu and struggling to figure out how to keep only one item open at a time. I've tried using an array with useState for all my dropdowns but haven't been able to find a solution yet: code co ...

Exploring innovative designs for asynchronous JavaScript programming

Imagine you have an Express app and you need to retrieve data from a database to display on the frontend. There's a function in your code that looks like this (using node-mysql for handling database queries) exports.getData = function() { ...

Route.get() function is expecting a callback function, but instead received a string object

Having searched through similar posts, I am unsure and lack the experience to apply the suggested resolutions to my project. I recently built a basic app with two main routes as part of a Udemy course, but I am struggling with the following error: "Route.g ...

Eliminate every instance using the global regular expression and the replace method from the String prototype

function filterWords(match, before, after) { return before && after ? ' ' : '' } var regex = /(^|\s)(?:y|x)(\s|$)/g var sentence1 = ('x 1 y 2 x 3 y').replace(regex, filterWords) console.log(sentence1) sentence2 ...

Tips for accessing the FormControlName of the field that has been modified in Angular reactive forms

My reactive form consists of more than 10 form controls and I currently have a subscription set up on the valueChanges observable to detect any changes. While this solution works well, the output always includes the entire form value object, which includ ...

Creating a javascript variable in c#

Currently, I am working on incorporating the selected index text from a DropDownList into a JavaScript string. My approach involves storing the text in a hidden field and retrieving it through C# to ensure the JavaScript variable retains its value even aft ...

Tips for retrieving nested data objects from a JSON API on the web

Below is the provided API link - I attempted to utilize this jQuery script in order to collect data for each state individually for my project. However, I am facing difficulties accessing the information with the code provided below. $.getJSON('http ...