2013-02-05 2 views
1

프로토 타입 함수 내에 정의되지 않은 기호가 나타납니다. 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> 

감사합니다.

답변

2

this은 예약 키워드이므로 self은 아닙니다. Self는 일반적으로 객체 자체에서 호출 할 수없는 함수 내에서 값을 닫는 데 사용됩니다. 그러나 새로 고침 기능 내에 console.log(this)을 실행하면 실제로는 Chart 개체임을 알 수 있습니다.

this을 자체 기능이 아니라 내부에 사용하십시오. (이 중복 비록) 양자 택일

var self = this; 

편집이 줄을 실행 자체가 예약어 아니지만, window.self 전역 속성입니다. 따라서 왜 self 그 자체로, 다른 상황으로, window

편집이 될 것입니다 : 이 라인은 특히 언급

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

로 오류가 발생할 것입니다, 그것은 줌 이벤트의 결합이다. the wiki에서, 함수

지정된 수신기 다른 연산자 함수와 같은 방식으로 호출을 갖 상기 현재 DOM 요소 등이 컨텍스트 현재 데이텀 D 인덱스 I 전달된다.

(강조 광산).

당신은 당신의 차트 개체를 통해 프록시에 이벤트가 필요합니다, 그래서 이런 식으로 바인딩을 변경 : 미안 해요

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

updated js fiddle

+0

,하지만 나는 importent 재미있는 이야기를 잊었 하나가 필요합니다 마우스 왼쪽 버튼을 클릭하고 디스플레이 창에서 마우스를 움직여 오류를 관찰하십시오. 'this'는 첫 번째 호출에는 적합하지만 클릭 드래그를 수행하는 경우에는 올바르지 않습니다. –

+0

아, 그래. 운 좋게 해결하기가 쉽습니다. 지금 편집 중입니다. –

관련 문제