4

私はJavaに慣れているので、次のようなことをしようとすると:

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=0;
}

function enhancer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

function silencer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

var a = new enhancer("aaa");
document.write(a.distance)

「未定義」になります。total および distance データ メンバを継承したと思いました

4

4 に答える 4

3

使用しないでください__proto__。これはMozilla独自のプロパティ(他のいくつかによってコピーされたもの)であり、非推奨です。construtor.prototpyeに割り当てます。

この線:

> __proto__:subSection;

は何にも割り当てられていません。ラベル(__proto__)の後に、subSection何にも割り当てられていないsubSection関数への参照であるステートメントが続きます。

プロトタイプの継承を理解していないようです。JavaScriptでダグラス・クロックフォードのプロトタイプの継承を試してください

以下はあなたがやろうとしていることのようなものかもしれません、ここに千の同様の質問があるに違いありません:

function SubSection(pattern) {
    this.pattern = pattern;
    this.total = 0;
    this.distance=0;
}

// Add a method to subSection.prototype
SubSection.prototype.getDistance = function() {
  return this.distance;
}

function Enhancer(pattern) {
    this.pattern = pattern;
}

// To make enhancer inherit from subSection, make its prototype
// an instance of subSection
Enhancer.prototype = new SubSection();

var a = new Enhancer("aaa");

document.write(a.getDistance()); // 0

ああ、そして慣例により、コンストラクター名は大文字で始まります。

于 2012-06-18T00:43:46.243 に答える
3
function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    this.__proto__=new subSection(pattern);
}

function silencer(pattern){
    this.__proto__=new subSection(pattern);
}

var a = new enhancer("aaa");
document.write(a.distance)​;

しかし、前述のように、これは Mozilla 独自のプロパティにすぎませんRobG

デモ。

アップデート:

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();    
}

function silencer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();
}

var a = new enhancer("aaa");
document.write(a.distance)​;

デモ。

便利なリンク: ここここ.

于 2012-06-18T00:44:58.987 に答える
0

オブジェクトにはプロトタイプ継承を使用する必要があります。私はあなたのエンハンサーオブジェクトを取り、次のように定義します:

    //create Enhancer object
function Enhancer(pattern){
    this.subSection(pattern);    
}

//extend Enhancer with object methods
Enhancer.prototype = {

   subSection: function(pattern){
         this.pattern = pattern;
         this.total = 0;        
         this.distance=0;
  }

};

だからここに私がこのコードで行っていることです:

  1. 関数を使用して Enhancer オブジェクトを定義しています。このデータ構造の「オブジェクト」を表すために「エンハンサー」を大文字にしていることに注意してください。
  2. オブジェクトに渡された「パターン」値を取得し、それを使用して Enhancer.subSection(); を呼び出します。.prototypeでメソッドとして定義したので、.subSection()をEnhancerオブジェクトのメソッドとして呼び出すことができます。

これは、このアプローチの実際のフィドルの例です

于 2012-06-18T00:45:33.947 に答える
0

一般的に言えば、オブジェクトのすべてのインスタンスに対してまったく同じ値に初期化されることを意図したtotalやのようなプロパティは、コンストラクタではなく で定義する必要があります。distancesubSectionprototype

オブジェクトprototypeは基本的に、そのオブジェクトのすべてのインスタンスが基づいている「テンプレート」です。すべてのインスタンスには、 で定義された各プロパティとメソッドがありprototypeます。

したがって、3 つの「クラス」 (JavaScript には、Java のような古典的な継承言語で定義されているクラスはありませんが、これらの言語に慣れている人にとっては用語を使用する方が簡単な場合があります) は、次のように宣言する必要があります。

function subSection(pattern) {
    this.pattern = pattern;
}

function enhancer(pattern) {
    this.pattern = pattern;
}

function silencer(pattern) {
    this.pattern = pattern;
}

コンストラクタの外に出て、プロトタイプに移動totalします。distancesubSectionsubSection

subSection.prototype.total = 0;
subSection.prototype.distance = 0;

subSection次のステップは、間のプロトタイプの継承を設定し、それらの間の一種のプロキシとして no-op 関数を使用することですenhancer:silencer

function fn() {}
fn.prototype = subSection.prototype;

enhancer.prototype = new fn();
silencer.prototype = new fn();

最後に、とプロトタイプのconstructorプロパティを正しいオブジェクトに設定して、インスタンスのプロパティが適切なコンストラクタ関数を参照するようにします。この手順を実行しない場合、orのインスタンスはコンストラクターを誤って参照します。enhancersilencerconstructorenhancersilencersubSection

enhancer.prototype.constructor = enhancer;
silencer.prototype.constructor = silencer;

enhancerこれでandオブジェクトをインスタンス化できます。silencer結果のインスタンスにはtotal、anddistanceプロパティとconstructor、それぞれのオブジェクトを参照するプロパティがあります。

var a, b;
a = new enhancer('aaaa');
b = new silencer('bbbb');
console.log(a.total + ', ' + a.distance); // 0, 0
console.log(b.total + ', ' + b.distance); // 0, 0
console.log(a.constructor); // (string representation of enhancer constructor)

継承プロセス中に関数をプロキシとして使用する理由はfn、オブジェクトが、必ずしも同じコンストラクター引数のセットを持たない別のオブジェクトから継承できる必要があるためです。

次の 2 つのコンストラクタがあるとします。

function Person(name, age, hometown) {
    this.name = name;
    this.age = age;
    this.hometown = hometown;
}

function Employee(name, company, title) {
    this.name = name;
    this.company = company;
    this.title = title;
}

EmployeePerson同じコンストラクター引数のセットを共有していなくても、から継承できる必要があります。Employee.prototypeの新しいインスタンスと等しくなるように単純に設定した場合PersonEmployeeプロトタイプには と の 3 つの未定義のプロパティnameが含まagehometownます。

Employee.prototype = new Person; // name, age and hometown are undefined
var e = new Employee('John Smith', 'New York Times', 'editor'); // e's prototype has undefined properties name, age and hometown

no-op 関数fn(事実上好きな名前を付けることができます) を使用するとfn、コンストラクターは引数を期待しないため、各インスタンスのクリーンなプロトタイプになります。

これは必須ではありませんが、プロトタイプの継承をセットアップするためのよりクリーンな方法です。未定義のプロパティでプロトタイプを乱雑にする理由はあまりありません。

于 2012-06-18T03:20:58.647 に答える