2

私はこれに慣れていないので、できるだけ詳しく説明しようと思います。

関数を使用してJSクラスを作成しています。

function Bandstar(p, id)
{
  var numberOfSides, Xcenter, Ycenter;
  var canvas;
  var circlesInt;
  var linesInt;
  var lines;
  var linesInt2;
  var linesMidToEdge; 
.....

メソッドに関しては、次のように宣言します。

this.IAset = function(a) 
{
   for (var i =0; i<= this.numberOfSides-1;i++)
   {
      if (parseInt(a[i]) == a[i])
         this.circles[i].value = a[i];
      else
         return false;
    }

    this.IArepaint();
    return true
}

それだけです。

ここでの問題は、特定のメソッドを作成しているときに、次のことです。

this.moveFunc = function(e)
{
   var p = e.target;
   this.IAmove(p);
};

メソッドIAmoveは次のように宣言されています。

this.IAmove = function(p)
{
   var m = (p.oTop - this.Ycenter ) / (p.oLeft - this.Xcenter);
   var linea = m * ( p.left - p.oLeft) + p.oTop;
   var ejeX = p.left;
   ...
} 

コンパイラはこのエラーをスローし続けます:

Uncaught TypeError: Object function (e)   {     var p = e.target;     this.IAmove(p);   } has no method 'IAmove'

つまり、moveFunc関数として宣言しているのですが、プロパティを使用しようとするとthis、実際にはその上のクラスのインスタンス()は使用されませんがBandstar、それ自体は使用されます(明らかにmoveFuncと呼ばれるメソッドIAmove、それが作成されているクラスは)..。

これはうまくいったようだと思いましたが、JSの遺産とクラスの形態の概念を正しく理解していないはずです。

同じクラス内の別のメソッドからクラス内のメソッドにアクセスするにはどうすればよいですか?私が書いIAmove(p)ただけでは、メソッドIAmove()は未定義であるとだけ表示されます(定義されていないため、Bandstar名前空間の一部です。

私はそれが私が見ていない何か愚かなものでなければならないことを知っています。助言がありますか?

4

3 に答える 3

3

関数内のコンテキストは、呼び出しに基づいて変更される場合があります。したがってthis、元のオブジェクトにすることはできませんでした。

次のようなプライベート変数を追加する必要があります。

 function Bandstar(p, id)
{
  var numberOfSides, Xcenter, Ycenter;
  var canvas;
  var that = this; // add this line

元のオブジェクトの関数を呼び出そうとする(またはプロパティを取得する)ときに使用します

this.moveFunc = function(e)
  {
    var p = e.target;
    that.IAmove(p); // change this line
  };

必ず元のオブジェクトを指すようにしてください。

編集:コメントによると、あなたはスチュアートの答えでより多くの情報を読むことができます

于 2013-01-04T09:48:42.587 に答える
1

これらのメソッドがすべてコンストラクターで定義されていると仮定すると、構文は正しいです。次のフィドルは、それが機能していることを示しています。コードは、コードの簡略化されたバージョンに基づいています...

function Test() {
    this.move = function(p) {
        document.write("Moved to: " + p);
    };
    this.another = function(e) {
        this.move(e.target);
    };
}

var test = new Test();
test.another({target: "The moon"});

問題の原因は、次の2つのいずれかである可能性があります。

  1. メソッドのmoveFunc呼び出し方法
  2. メソッドmoveFuncが呼び出されたとき
  3. IAmoveメソッドの呼び出し方法 (そのエラーの原因となっている関数ではない可能性がありますmoveFunc)。

キーワードは、this通常はメソッドの所有者である関数のスコープを参照します...

var bandstar = new Bandstar(p, id);
bandstar.moveFunc(e); // this should be bandstar

そうでない可能性がある唯一の理由は、moveFunc関数を別のオブジェクトに明示的にバインドしている場合、またはより一般的な状況は、関数が所有者にアタッチされずに呼び出されていることです...

var bandstar = new Bandstar(p, id);
var moveFunc = bandstar.moveFunc(e);
moveFunc(e); // this will now be window

所有者が切り離されている場合、キーワードthisはデフォルトで になります。windowを使用して関数をバインドできます。

var bandstar = new Bandstar(p, id);
var moveFunc = bandstar.moveFunc(e);
moveFunc.bind(bandstar);
moveFunc(e); // this will now be bandstar again

moveFunc2番目の問題では、関数を呼び出す前に両方のメソッドをコンストラクターで定義する必要があります

this.moveFunc = function(e) { ... }
this.moveFunc(e); // Will throw an error that IAmove does not exist in the object
this.IAmove = function(p) { ... }

thisを使用してオブジェクトをログに記録し、console.log(this);それが何であるかを調べることができます。

IAmoveエラーから、関数を呼び出そうとしているように見えますmoveFunc。このエラーが発生するにはmoveFunc、自分自身を所有者またはバインドされたオブジェクトとして呼び出す必要があります...これは特にありそうにありません。

エラーは実際には想定どおりのthis.IAmove(p);呼び出しに関連していない可能性があるという予感があります。スタック トレースを投稿すると、それを使用してエラーが発生した場所を見つけることができます。moveFunc

于 2013-01-04T09:56:04.970 に答える
1

おそらく、これらのメソッドをBandstarプロトタイプに追加したいと思うでしょう。

function Bandstar(p, id)
{
   // ...
}

Bandstar.prototype.IAset = function(a) 
{
   // ...
}

Bandstar.prototype.moveFunc = function(e)
{
   var p = e.target;
   this.IAmove(p);
};

このようにして、メソッドは Bandstar コンテキストを保持し、thisBandstar インスタンス参照のままになります。

Object.prototypeリファレンスをご覧ください

于 2013-01-04T09:56:32.317 に答える