原型函数中的未定义符号

时间:2013-02-05 19:01:39

标签: javascript d3.js

我在原型函数中得到一个未定义的符号。我向console.log写了'this'和'self'值。值从第一次调用通过直接调用变为后来的调用,通过'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>

谢谢。

1 个答案:

答案 0 :(得分:2)

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

在该功能中使用this,而不是自我;或者执行这一行(虽然它是多余的)

var self = this;

编辑:虽然自我不是保留字,window.self 是全局属性。因此,为什么self本身,没有其他背景,window

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

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

特别是,它是zoom事件的绑定。从the wiki开始,函数将具有

  

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

(强调我的)。

您需要通过Chart对象代理事件,因此将绑定更改为以下内容:

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

updated js fiddle