5

私は最近、言語を完全に理解するために JavaScript を深く調べており、答えが見つからないように見えるいくつかのしつこい質問があります (具体的にはオブジェクト指向プログラミングを扱っています)。

次のコードを想定します。

function TestObject()
{
    this.fA = function()
    {
        // do stuff
    }

    this.fB = testB;

    function testB()
    {
        // do stuff
    }
}

TestObject.prototype = {
    fC : function 
    {
        // do stuff
    }
}

fA関数とはどう違いfBますか?それらは範囲と潜在的な能力においてまったく同じように動作しますか? それは単なる慣習ですか、それとも技術的に優れているか適切な方法ですか?

オブジェクトのインスタンスが一度に 1 つしか存在しない場合、プロトタイプに関数を追加するfC価値があるでしょうか? そうすることに何かメリットはありますか?プロトタイプは、オブジェクトまたは継承の多くのインスタンスを処理する場合にのみ本当に役立ちますか?

TestObject.prototype.functionName = function(){}そして、私が上記の方法で、または毎回呼び出す方法でプロトタイプにメソッドを追加する技術的に「適切な」方法は何ですか?

私は自分の JavaScript コードをできるだけクリーンで読みやすいものに保つことを目指していますが、この言語におけるオブジェクトの適切な規則についても非常に興味があります。私は Java と PHP のバックグラウンドを持っていますが、JavaScript がどのように機能するかについては何も仮定しないようにしています。

4

4 に答える 4

6

関数fAとfBの違いは何ですか

実際には、何もありません。関数式 (fA) と関数宣言 (fB) の主な違いは、関数の作成時です (宣言された関数はコードが実行される前に使用できますが、関数式は式が実際に実行されるまで使用できません)。また、関数式に関連するさまざまな癖があり、遭遇する可能性があります。

この例では、関数式を宣言して結果を代入するのが少し抽象化されているように見えるため、関数式を使用します。しかし、どちらのアプローチにも「正しい」または「間違っている」というものはありません。

オブジェクトのインスタンスが一度に 1 つしか存在しない場合、fC などの関数をプロトタイプに追加する価値があるでしょうか?

いいえ。継承を行うほぼすべての人が、単純なオブジェクトの方が多くの場合、単純であり、したがって「優れている」ことに気付きます。ただし、プロトタイプの継承は、組み込みオブジェクトにパッチを適用するのに非常に便利です (たとえば、存在しない場所に Array.prototype.each を追加するなど)。

また、プロトタイプにメソッドを追加する技術的に「適切な」方法は何ですか...</p>

1つもありません。デフォルトのプロトタイプを他のオブジェクトに置き換えるのは少し無駄に思えるかもしれませんが、リテラルによって作成されたオブジェクトを代入する方が、一連の代入をより整然として読みやすくなります。1 つまたは 2 つの割り当てには、次のように使用します。

 Constructor.prototype.method = function(){…}

しかし、多くのメソッドでは、オブジェクト リテラルを使用します。古典的な拡張機能を使用して実行するものもあります。

myLib.extend(Constructor.prototype, {
    method: function(){…}
});

メソッドのいくつかがすでに定義されている場合、これはメソッドを追加するのに適しています。

いくつかのライブラリを見て、好きなものを決めてください。特定の状況に合ったものを実行します。多くの場合、すべてが同じに見えるように十分なコードを取得するだけの問題であり、選択したパターンが何であれ、きれいに見えます。

于 2012-09-07T05:36:25.757 に答える
3

fAfBは実質的に同じであり、慣例の問題です。

オブジェクトのインスタンスが 1 つしかない場合は、コンストラクター関数も使用せず、次のようなオブジェクト リテラルのみを使用します。

var o = {
   fA: function () { ... },
   fB: function () { ... },
   fC: function () { ... }
};

インスタンスまたはプロトタイプに追加する場合、インスタンスが 1 つしかない場合は、プロトタイプに追加するよりもインスタンスの方がわずかに効率的ですが、前述のように、代わりにリテラルを使用します。

コンストラクターを呼び出すたびに、各関数を表す新しいオブジェクトが作成されるため、コンストラクターで関数を宣言することは避けます。これらのオブジェクトはそれほど大きくはありませんが、多くのオブジェクトが作成された場合に加算される傾向があります。関数をプロトタイプに移動できる場合は、移動する方がはるかに効率的です。

プロトタイプへの追加に関しては、私は

TestObject.prototype.functionName = function () { };

スタイルですが好みの問題です。プロトタイプを拡張する場合でも、最初のプロトタイプを作成する場合でも同じように見えるため、上記が気に入っています。

于 2012-09-07T05:29:04.790 に答える
0

私は最初の部分に答えます:違いはありません、あなたが変数としてではなく関数を宣言するとき、それの宣言はブロックで上がるので、

...
func();
...    
function func () { ... }

に等しい

var func = function () { ... };
...
func();
...

だからあなたのコード

function TestObject () {
  this.fA = function() { // do stuff };   
  this.fB = testB;    
  function testB() { // do stuff }
}

に等しい

function TestObject () {
    var testB = function () { // do stuff };    
    this.fA = function () { // do stuff };
    this.fB = testB;
}
于 2012-09-07T05:26:32.143 に答える
0

また、JavaScriptが低レベルでどのように動作するかについての決定的なJavaScriptスタイルガイドまたはドキュメントはありますか?

「Web開発者向けのプロフェッショナルJavaScript」を見逃してはならないjavascriptプログラマーはいないでしょう。これは素晴らしい本であり、深く掘り下げられています。オブジェクト、クラスエミュレーション、関数、スコープなどについて説明します。JSリファレンスでもあります。

そして、技術的には、上記の方法でプロトタイプにメソッドを追加したり、毎回TestObject.prototype.functionName = function(){}を呼び出したりする「適切な」方法は何ですか?

クラスを定義する方法については、さまざまなJS MVCフレームワーク(軽量のSpine.jsなど)を確認することをお勧めします。それら全体は必要ありません。クラスエミュレーションライブラリだけが必要です。この主な理由は、JSにはクラスの概念がなく、純粋にオブジェクトとプロトタイプで構成されているためです。一方、クラスは完全にエミュレートできます(エミュレートされた単語は欠落しているため、使用しないでください)。これにはプログラマーからのある程度の訓練が必要なので、仕事をしてコードをよりクリーンにするためにクラスエミュレーションライブラリを用意することをお勧めします。

プログラマーがクラスエミュレーションライブラリに期待する必要のある標準的なメソッドは次のとおりです。

// define a new Class
var AClass = Class.create({
   // Object members (aka prototype), 
   // usually an initialize() method is called if it is defined 
   // as the "constructor" function when a class object is created
}, {
   // Static members
}); 

// create a child class that inherits methods and attributes from parent
var ChildClass = AClass.extend({
   // Child object members
},{
   // Child static members
}); 

AClass.include({
   // Object amendments (aka mixin), methods and attributes 
   //   to be injected to the class object
},{
  // Statics amendments, methods and attributes to be 
  //  injected as class static members
});


// check object type
var aObj = new AClass();
aObj instanceof AClass; //  true
aObj instanceof ChildClass; //  false


var cObj = new ChildClass();
cObj instanceof AClass; //  true
cObj instanceof ChildClass; //  true
于 2012-09-07T09:02:37.737 に答える