0

JSでOOPのような動作を模倣して実験しています。私は(プライベート)変数を持とうとしています:idそしてname関数内にPerson。この関数には、(プライベート) 変数の初期化に使用される引数を渡しています。次に、 getter と setter をname持ち、 の getter のみを持つオブジェクトを返すためid、実質的にid読み取り専用になります。

そのため、id はコンストラクターを介してのみ設定できますが、name はいつでも設定および取得できます。

これはコードです:

     var Person = function (_id,_nm) {
        var id, name;    
                  
        this.id = _id;
        this.name = _nm;

        return {               
            setName: function (nm) {
                name = nm;
            },
            getName: function () {
                return name;
            },
            getId: function () {
                return id;
            },
            print: function () {
                document.writeln("Id: "+id+"<br />Name: "+name);
            }
        }
    }

    var person = new Person(123, "Mahesh");
    person.print();

ただし、実行すると、実際に設定されてnew Person(123,"Mahesh")いるかどうかがわかりません。デバッグ中に値にカーソルを合わせると適切に設定された値が表示されますが、ローカルパネルには初期化された値が表示されないためです。idname

デバッグ

または、print() で目的の変数idname変数を参照していない場合:

デバッグ

ここで何が問題なのですか?

4

5 に答える 5

2

働くフィドル

その理由は、 にpublicメンバーを使用しているためですPerson.prototypethisこれら 2 つの参照を追加する必要はありません。だから削除:

this.id = _id;
this.name = _nm;

そして単に使用します:

 var id = _id,
     name = _nm;  

これですべてが正常に機能します。全体のアイデアはvar、 ではなくを使用するthisことです。そうしないと、クロージャが作成されません。nameこれで、 andidに直接アクセスできなくなり、代わりにsetName(), getName(), setId(), getId()etcを使用する必要があります。

2 つのメンバーidnameは、必要に応じてクロージャーになります。

アップデート

を使用this.idした場合は、そうではなく、または直接アクセスprivateするだけで済みます。彼らはそうあるべきなので、これはあなたが望むものではありません。var p = new Person(1, "Mahesha");p.namep.idprivate

クロージャー パターンでは、 p.name と p.id は定義されておらず、 と を介してのみアクセスできp.getName();ますp.getId();。クロージャーがどのように機能するかを読んでください。アイデアは、それを使用しているため、そのvar name値を記憶するためにクロージャーが作成されるということです。

あなたのgetNamesetNameは、そのクロージャを使用してnameプロパティにアクセスしています。はありませんthis.name。高次のクロージャーを通じて記憶される値があります。

于 2013-05-12T11:26:29.740 に答える
1

this.idvar id同じではありません。this.idオブジェクトのプロパティです。var idローカルスコープに属します。

于 2013-05-12T11:42:27.067 に答える
1

値を使用するnewか、または返します。両方ではありません。

Person問題は、キーワードを使用して新しいインスタンスを作成しているのにnew、コンストラクター関数が代わりに別のオブジェクトを返していることです。

コンストラクター関数から何かを返すと、関数のインスタンスではなく、その値が返されます。

new Person(123, "Mahesh")の新しいインスタンスを実行すると、作成されることがわかりますPerson。これは、コンストラクター関数内で としてアクセスできますthis

コンストラクタから何も返さない場合、JavaScript は自動的に を返しますthis。ただし、明示的に別のオブジェクトを返しています。

とプロパティ ( でのみ定義したもの)var personがないのも不思議ではありません。idnamethis

さらに、 and をprint表示しません。これは、( ) を宣言したにもかかわらず、値を指定しなかったためです。したがって、それらはです。idnamevar id, nameundefined

Personこれは、コンストラクターを次のように書き直す方法です。

function Person(id, name) {
    this.getId = function () {
        return id;
    };

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

    this.setName = function (new_name) {
        name = new_name;
    };

    this.print = function () {
        document.writeln("Id: " + id + "<br/>Name: " + name);
    };
}

idおよびnameプロパティをオンに設定しませんでしthisた。それらを含める意味がないからです。

于 2013-05-12T13:54:20.397 に答える
1

_idおよび_nmと 「パブリック」インスタンス プロパティ (this.idおよび) に対して、ローカル スコープ (「プライベート」) 変数を使用するのを混同しましたthis.nm

この場合、前者が必要ですが、両方を作成し、後者のみを初期化しました。

id読み取り専用であるため、別のローカル変数はまったく必要ないことに注意してください。コンストラクターに字句スコープの最初のパラメーターを使用するだけです。

var Person = function (id, _nm) {
    var name = _nm;

    ...
};
于 2013-05-12T11:28:53.223 に答える
0

以下を使用して説明してみましょう。

// Scope 1
var Person = function (_id,_nm) {
    // Scope 2
    var id, name;    

    this.id = _id;
    this.name = _nm;

    return {
        // Scope 3
        setName: function (nm) {
            name = nm;
        },
        getName: function () {
            return name;
        },
        getId: function () {
            return id;
        },
        print: function () {
            $("#output").append("<p>Id: "+id+"; Name: "+name  + "<p/>");
        }
    }
}

コードで設定されていないを参照しているため、メソッドprintは戻ります。andをプロパティに設定しましたが、作成したばかりのオブジェクトを返すことができません。代わりに、設定したことのない変数を参照する辞書を返すため、呼び出しで未定義の出力が発生します。undefinedvar id, name;_id_nameidnamenameidScope 2print()

これがあなたがすべきことです:

var NewPerson = function (_id,_nm) {
    var self = this;
    this.id = _id;
    this.name = _nm;  

    this.print = function () {
        $("#output").append("<p>New Person Id: "+this.id+"; Name: "+ this.name  + "<p/>");
    };

    return this;
};

var nperson = new NewPerson(456, "Marcos");
nperson.print();

これは出力されます:

New Person Id: 456; Name: Marcos

本質的に、newは で表される新しいオブジェクトを作成 しており、作成されたオブジェクトへの参照を取得するためにthis戻る必要があります。実際、オブジェクトを作成する前に をthis使用しないと、 のグローバル インスタンスを参照することになります。次のことを試してください。newthis

var nperson = new NewPerson(456, "Marcos");
this.name = "Hello";
nperson.print();

var nperson1 = NewPerson(456, "Marcos");
this.name = "Hello";
nperson1.print();

最初の出力が期待どおりになることがわかります。

New Person Id: 456; Name: Marcos

しかし、2番目はに加えられた変更を取得しthis.nameます:

New Person Id: 456; Name: Hello

これが JSFiddleです。

于 2013-05-12T13:09:57.527 に答える