为什么'this'变量不是预期值?

问题描述:

我遇到以下代码的问题。在具有“console.log”的行上,'this'变量应该包含'Object Chart',但是包含'path.line'。因此,对xscale的引用是未定义的。我为什么得到这个?在Chrome和Firefox下发生此错误。为什么'this'变量不是预期值?

谢谢。

<!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> 
+0

['this'](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this)不是一个 “可变的”,而是一种特殊的关键字结合到当前执行 – Bergi

+0

一个常用的方法是在函数的顶部声明一个变量,比如'var self = this;',然后在所有指向父函数的地方使用'self' ......在其他地方你想在嵌套函数中引用'this'的具体值,你可以按照预期使用'this'。 – Ian

除非你直接在图表构造(未在作为参数传递的匿名函数)或以图表对象或手动的方法使用callapply与聊天对象使用thisthis不会引用一个Chart对象。

你可以做的是显式地为图表对象设置一个变量并在函数中使用它。

<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); // <<== is '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>