1

プロトタイプ関数内に未定義のシンボルがあります。「this」と「self」の値をconsole.logに書き込みます。値は、直接呼び出しによる最初の呼び出しから、「zoom」からのコールバックによる後の呼び出しに変わります。私はjsfiddle、http: //jsfiddle.net/eric_l/kQSTH/を持っており、コンソールを開くとエラーメッセージが表示されます。「これ」も「自己」も正しく機能していないという考えはありますか?

<!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の値を閉じるために使用されます。ただし、refresh関数の内部で実行すると、それが実際にオブジェクトconsole.log(this)であることがわかります。Chart

this自己ではなく、その関数内で使用します。または、この行を実行します(冗長ですが)

var self = this;

編集:selfは予約語でwindow.self ありませんが、グローバルプロパティです。selfしたがって、他のコンテキストなしで、それ自体がなぜwindow

編集2:この行は述べられているようにエラーを引き起こします

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

特に、それはズームイベントのバインドです。ウィキから、関数は

指定されたリスナーは、他のオペレーター関数と同じ方法で呼び出され、現在のDOM要素としてこのコンテキストを使用して現在のデータムdとインデックスiが渡されます。

(私の強調)。

Chartオブジェクトを介してイベントをプロキシする必要があるため、バインディングを次のように変更します。

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

更新されたjsフィドル

于 2013-02-05T19:17:11.343 に答える