-1

クロージャーとプロトタイプについてはすでにたくさんの記事を読んでいます...しかし、まだいくつか質問があります。私はこの記事から始めました:http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

私の質問は、パブリックメソッドを公開しようとしています。

この方法ですか:

// Closure implementation
function Pixel(x, y){
  this.x = x;
  this.y = y;
  this.getX = function(){
    return this.x;
  }
  this.getY = function(){
    return this.y;
  }
  this.setX = function(value){
    this.x = value;
  }
  this.setY = function(value){
    this.y = value;
  }
}

これとは異なります:

// Closure implementation
function Pixel(x, y){
  this.x = x;
  this.y = y;
    return {
        getX : function(){
            return this.x;
          },
        getY : function(){
            return this.y;
          },
        setX : function(value){
            this.x = value;
          },
        setY : function(value){
            this.y = value;
          }
    }
}

どれが一番いいですか?なぜ?

最後の質問:上記のベンチマークから、クロージャーを使用してプロトタイプと同様のパフォーマンスを実現する方法はありますか?

tx

4

2 に答える 2

1

「より良い」実装はありません。

2番目のオプションは、 new を呼び出すことができないためエラーが発生するためthis、ウィンドウ(または関数が定義/呼び出されたときのスコープ)を参照するため、使用しないでください

2 番目のオプションでは、次のようなクロージャーを使用できます。

function Pixel(x, y){
  this.x = x;
  this.y = y;
  var that = this;
    return {
        getX : function(){
            return that.x;
          },
        getY : function(){
            return that.y;
          },
        setX : function(value){
            that.x = value;
          },
        setY : function(value){
            that.y = value;
          }
    }
}

しかし、これは本当に醜いものであり、互換性がなくprototype、私の意見では、プライバシーの問題を重要視しすぎています.

于 2013-02-06T17:54:39.020 に答える
0

言いたいことはたくさんあります。まず第一に、この種のget/setメカニズムは Javascript ではめったに適切ではありません。この Java コンストラクトは、データへのすべてのアクセスがプライベート プロパティではなくパブリック メソッドを介して行われるようにする必要がありました。Javascript の世界はまったく気にしません。

xしかし、Pixel オブジェクトが必要で、それらとyデータをカプセル化し、次の 2 つの関数を公開したいとします。

toString(); // String (a representation of this Pixel)
offset(deltaX, deltaY); // Pixel (a new Pixel shifted by deltas from this one)

次に、次のようにします。

var PixelA = function(x, y) {
    this.x = x; this.y = y;
    this.toString = function() {
        return "(" + this.x + ", " + this.y + ")";
    };
    this.offset = function(deltaX, deltaY) {
        return new PixelA(this.x + deltaX, this.y + deltaY);
    };
};

または、次のようにすることもできます。

var PixelB = function(x, y) {
    this.toString = function() {
        return "(" + x + ", " + y + ")";
    };
    this.offset = function(deltaX, deltaY) {
        return new PixelB(x + deltaX, y + deltaY);
    };
};

または、次のようにすることもできます。

var PixelC = function(x, y) {
    this.x = x; this.y = y;
}
PixelC.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
};
PixelC.prototype.offset = function(deltaX, deltaY) {
    return new PixelC(this.x + deltaX, this.y + deltaY);
};

(: すべて未テストです。)

PixelAかなり素朴です。私たちのデータはカプセル化されていません。誰でも内部xおよびyプロパティに直接アクセスまたは変更できます。また、メモリを大量に消費します。toStringPixelA のすべてのインスタンスには、関数と関数の独自のコピーがありoffsetます。

PixelB最初の問題に対処します。内部データは、コンストラクター関数によって生成されたクロージャーに格納されます。toStringおよび関数はこれらoffsetの変数にアクセスできますが、外部から直接それらを見ることはできません。しかし、それは 2 番目の問題を解決するものではありません。

PixelC2番目の問題に対処します。toStringおよび関数はプロトタイプに格納されているためoffset、インスタンスに繰り返しコピーが散らばることはありません。しかし、xandyプロパティは再びパブリックになり、最初の問題が再発します。

オプション D については知りません。内部状態をカプセル化するか、プロトタイプ関数にその状態へのアクセスを許可するかを選択する必要があると思います。これを修正するために経験できる構文上のゆがみはたくさんあります。しかし、この根本的な問題に実際に対処するものはありません。どちらの方向にも特定の最適化を実行できますが、問題は根本的なものです。

私が間違っていると証明されたいです。

パフォーマンスの問題に関しては、クロージャーベースの構築がプロトタイプベースの構築と同じくらい高速になる方法はありません。クロージャーベースのバージョンで各インスタンスにこれらすべてのプロパティを割り当てるために実行する必要があるすべての作業を考えてみてください。プロトタイプベースのバージョンでは単に実行する必要がない作業です。クロージャーベースのプロパティアクセスが高速になる可能性があります...

于 2013-02-06T19:10:31.013 に答える