39

重複の可能性:
Javascript での「プロトタイプ」と「これ」の使用?
Javascript でのオブジェクト指向の質問

次のうち、どれが一番良いか、またはそれぞれの長所と短所を教えてください。

方法 1

function User() {

    this.name = "my name";
    this.save = function() {

    };
}

方法 2

function User() {

    this.name = "my name";
}

User.prototype.save = function() {

}
4

4 に答える 4

57

私はJavaとPHPのバックグラウンドから来て、最初はJavaScriptの「クラス」の概念全体に苦労していました。ここで考えるべきことがいくつかあります。

工事

まず、クラスを次のように定義する可能性が高いためです。

Customer = function () {}
Customer.prototype = new Person();

構築中にプロパティとメソッドを定義していると、あらゆる種類のコードの悪夢に遭遇することになります。その理由は、のようなコードではCustomer.prototype = new Person();、真の継承のためにCustomerコンストラクターでPersonを呼び出す必要があるためです。そうしないと、元のコードが何を設定するかを常に知る必要があります。次の例を見てください。

Person = function (name) {
    this.name = name;
    this.getName = function () {return this.name}
}
Customer = function (name) {
    this.name = name;
}
Customer.prototype = new Person();

次に、Personを更新して、それらが「新規」であるかどうかも設定します。

Person = function (name, isNew) {
    this.name = name;
    this.isNew = isNew;
    this.getName = function () {return (this.isNew ? "New " : "") + this.name; }
}

これで、Personから継承している「クラス」で、フォームに従うようにコンストラクターを更新する必要があります。次のようなことを行うことで、それを回避できます。

Customer = function () {
    Person.apply(this, arguments);
}

これにより、新しい「顧客」の範囲内で「個人」が呼び出され、個人の構造について知る必要がなくなります。

スピード

これらのベンチマークを見てください:http: //jsperf.com/inherited-vs-assigned
基本的に、ここで証明しようとしているのは、これらのオブジェクトをまとめて作成する場合最適なルートはプロトタイプで作成することです。次のように作成します。

Person = function (name) {
    this.name = name;
    this.getName = function () {return this.name}
}

オブジェクトを作成するたびに新しい関数が作成されるため、非常に低速です。既存のプロトタイプチェーンを検索するだけではありません。逆に、メソッドが非常に頻繁に呼び出されるオブジェクトが数個しかない場合は、それらをローカルで定義すると、プロトタイプチェーンを検索することで速度が低下します。

共有プロパティ

これはいつも私を取得します。次のようなものがあるとしましょう。

Person = function () {
    this.jobs = {};
    this.setJob = function (jobTitle, active) {this.jobs[jobTitle] = active; }
}

Employee = function () {}
Employee.prototype = new Person();

var bob = new Employee();
bob.setJob('janitor', true);

var jane = new Employee();
console.log(jane.jobs);

何だと思う?ジェーンは用務員です!冗談抜き!これが理由です。this.jobsをEmployeeのインスタンス化の新しいオブジェクトとして定義しなかったため、「jobs」が検出されてそのまま使用されるまで、プロトタイプチェーンを検索しているだけです。楽しいですよね?

したがって、これはインスタンスを追跡したい場合に便利ですが、ほとんどの場合、非常にイライラすることになります。次の手順を実行することで、これを回避できます。

Employee = function () { Person.apply(this); }

これにより、「Person」は新しい「this.jobs」を作成します。

プライベート変数

JavaScriptには本当に「プライベート」なものはないので、プライベート変数を取得する唯一の方法は、コンストラクターでそれらを作成し、それらに依存するものをコンストラクターで初期化することです。

Person = function () {
    var jobs = {};
    this.setJob = function (jobTitle, active) {jobs[jobTitle] = active; }
    this.getJob = function (jobTitle) { return jobs[jobTitle]; }
}

ただし、これは、継承されたクラスのインスタンス化のたびにそのコンストラクターを呼び出す必要があることも意味します。


提案

http://ejohn.org/blog/simple-javascript-inheritance/

これは非常に基本的なクラスの設定です。それは簡単です。できます。そして、JavaScriptが提供するすべての狂気に対処する必要なしに、90%の時間で必要なことを実行します:)

</rant>

于 2012-11-02T06:37:10.037 に答える
10

ベストは非常に主観的な用語です。

方法1は、真にプライベートな変数の可能性を示します。例:

function User() {
   var name = "fred";
   this.getName = function () { return name;};
}

方法2では、単一の保存関数がすべてのユーザーオブジェクトで共有されるため、使用するメモリが少なくなります。

「最良」は、特定の要件によって決定されます。

于 2012-11-02T06:04:45.747 に答える
7

JavaScriptは「オブジェクトベース」言語であり、「クラスベース」言語ではありません。クラスの概念である共有動作は、プロトタイプをリンクすることによって実装されます。

メソッド1はクラスを作成しません。それを呼び出すたびに、定義されたとおりに属性と関数を作成し、それらは他の「インスタンス」と共有されません。置き換えるthis.saveと、1つのインスタンスのみが動作を変更します。

方法2は、共有動作を実装します。したがって、それは人々がクラスやインスタンスに関連付けるものです。this.save別の関数に置き換えると、すべての派生インスタンスはすぐに新しい動作になります。

「最良」とは、メモリを消費する関数の再定義がなく、一般的な動作(クラスベースのプログラミングと同等になる傾向がある)を共有しないことを意味する場合、方法2が最適です。

于 2012-11-02T07:44:59.453 に答える
6

他の人が述べたように、2 つの主な違いがあります。

  • 方法 1 は、User のすべてのインスタンスに対して新しい関数を作成します
  • 方法 1 は、コンストラクターのスコープ内のローカル変数にアクセスできます。

これらを示す例を次に示します。

function User() {

    var name = "my name";

    this.foo = function() {
        // one function per User instance
        // can access 'name' variable
    };
}

User.prototype.bar = function() {
    // one function shared by all User instances
    // cannot access 'name' variable
};

var a = new User();
var b = new User();

console.log(a.foo === b.foo); // false; each instance has its own foo()
console.log(a.bar === b.bar); // true; both instances use the same bar()
于 2012-11-02T06:28:56.990 に答える