1

我在原型函数中得到一个未定义的符号。我将'this'和'self'值写入console.log。值从通过直接调用的第一次调用更改为通过来自“缩放”的回调的后续调用。我有一个 jsfiddle,http://jsfiddle.net/eric_l/kQSTH/,打开控制台可以看到错误消息。来自“this”和“self”的任何想法都不能正常工作?

<!DOCTYPE html>
<meta charset="utf-8">
<title>Zoom by Rectangle</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>

body {
  font-family: sans-serif; 
}

svg {
  font: 10px sans-serif;
  shape-rendering: crispEdges;
}

rect {
  fill: #ddd;
}

.axis path, .axis line {
  fill: none;
  stroke: #fff;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 3.0px;
}
</style>
<p><label for="zoom-rect"><input type="checkbox" id="zoom-rect"> zoom by rectangle</label>
<table><tr><td> <div id="chart1"> </div> </td></tr></table>
<script>

var zoomRect = false;

d3.select("#zoom-rect").on("change", function() {
      zoomRect = this.checked;
    });

var Chart = function( _width, _height, _anchor )
{
var self = this;
this.anchor = _anchor;
this.margin = {top: 0, right: 12, bottom: 12, left: 36},
this.width = _width - this.margin.left - this.margin.right,
this.height = _height - this.margin.top - this.margin.bottom;

this.data = [ {x:0         , y:0},
              {x:this.width*0.25, y:this.height},
              {x:this.width*0.5 , y:this.height/2},
              {x:this.width*0.75, y:this.height},
              {x:this.width     , y:0} ];

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

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

this.xAxis = d3.svg.axis()
    .scale(this.xscale)
    .orient("bottom")
    .tickSize(-this.height);

this.yAxis = d3.svg.axis()
    .scale(this.yscale)
    .orient("left")
    .ticks(5)
    .tickSize(-this.width);

this.zoom = d3.behavior.zoom().x(this.xscale).y(this.yscale).on("zoom", this.refresh);

this.svg = d3.select(this.anchor).append("svg")
    .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 + ")")
    .call(this.zoom)
  .append("g")
    .on("mousedown", function() {
      if (zoomRect)
      {
          d3.event.stopPropagation();
      }
    })
    .on("mousemove", function() {
      if (zoomRect)
      {
          d3.event.stopPropagation();
      }
    });

this.svg.append("rect")
    .attr("width", this.width)
    .attr("height", this.height);

this.line = d3.svg.line()
    .x(function (d) { return self.xscale(d.x) } )
    .y(function (d) { return self.yscale(d.y) } )

this.path = this.svg.append("path")
    .attr("class", "line")
    .datum(this.data)
    .attr("d", this.line);

this.svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + this.height + ")")
    .call(this.xAxis);

this.svg.append("g")
    .attr("class", "y axis")
    .call(this.yAxis);
}; // Chart

Chart.prototype.refresh = function() {
  console.log("this=" + this);
  console.log("self=" + self);
  console.log("this.svg=" + this.svg);
  console.log("self.svg=" + self.svg);
  self.svg.select("path").attr("d", self.line );
  self.svg.select(".x.axis").call(self.xAxis);
  self.svg.select(".y.axis").call(self.yAxis);
}

var charts = [];

charts.push( new Chart( 760, 400, "#chart1"));

for( var i = 0; i < charts.length; ++i ) {
    charts[ i ].refresh();
}


</script>

谢谢你。

4

1 回答 1

2

this是保留关键字,self不是。Self 通常用于在可能不会在对象本身上调用的函数中关闭 this 的值。但是,console.log(this)在您的刷新函数中执行操作表明它确实是一个Chart对象。

在该函数内部使用this,而不是 self;或者执行这一行(虽然它是多余的)

var self = this;

编辑:虽然 self 不是保留字,但window.self 它是一个全局属性。因此,为什么self在没有其他上下文的情况下,它本身将是window

编辑 2:此行将导致所述错误

this.zoom = d3.behavior.zoom().x(this.xscale).y(this.yscale).on("zoom", this.refresh);

特别是,它是缩放事件的绑定。从wiki中,该功能将具有

指定的侦听器以与其他运算符函数相同的方式调用,传递当前数据 d 和索引 i,并将 this 上下文作为当前 DOM 元素

(强调我的)。

您需要通过 Chart 对象代理事件,因此将绑定更改为如下所示:

this.zoom = d3.behavior.zoom().x(this.xscale).y(this.yscale).on("zoom", function() {
    self.refresh();
});

更新的 js 小提琴

于 2013-02-05T19:17:11.343 回答