2016-10-19 9 views
0

ここでは全く同じ質問をdefine property in constructorに聞いていますが、回答が満足できるものではないと思います。 このコードは、「オブジェクト指向のJavaScriptの原則」という本からコピーされています。コンストラクター、ゲッター、セッターメソッドのObject.defineProperty

function Person(xname) { 
    Object.defineProperty(this, "name", { 
     get: function() { 
      return xname; 
     }, 
     set: function(newName) { 
      name = newName; 
     }, 
     configurable: true, 
     enumerable: true 
    }); 
    this.sayName = function() { 
     console.log(this.name); 
    }; 
} 

var One = new Person("Mark"); 

One.sayName(); 
console.log(One.name); 
//output: 
//Mark 
//Mark 

それがさらに同じ名前のローカル変数やオブジェクトプロパティの使用を混乱されたので、私は、名前へのXNameパラメータを変更しています。

私は、このコードが意図したとおりに動作しているのではないかと疑いますが、何かをしているようにも私を混乱させます。

  1. 私は「名前」と呼ばれる新しく作成されたインスタンスのプロパティを作成するためにコンストラクタ内Object.defineProperty使用されていることを理解しています。

  2. getterメソッドは、たXNameを返し、まだのXNameは、行の後にスコープを消灯します。varワン=新しい人(「マーク」)。どのようにして後でコードオブジェクトにすることができますか?xnameの値を返すように1つのゲッターを管理しますか?私はそれが動作するはずのように、を返すためにgetterメソッドを変更した場合ので

  3. そして、それは、のXName値であり、エンジンがエラーが定義されていない報告します。

  4. setterメソッドがまったく機能しないことは言うまでもありません。 One.name = "Mickey"の場合、One.nameはまだ "Mark"に設定されています。

xnameの.nameへの割り当てはありませんが、私はそれを見ませんか?

+2

* "同じ名前のローカル変数とオブジェクトプロパティの使用をさらに混乱させたため、xnameにパラメータ名を変更しました。" 。あなたはセッターを逃した。 –

+0

\ * have =>半*(申し訳ありません)* –

答えて

0

getterメソッドはxnameを返し、まだxnameライン後の範囲を出て行く:var One = new Person("Mark");はどのように後からコードオブジェクトの一つゲッターでxnameの値を返すように管理することができます?

はまだ使用されている範囲内にあるので、まだです。はい、Person関数が返されましたが、Personへの呼び出しのコンテキストで閉じる関数があるため、そのコンテキスト内で定義されている引数と変数には引き続きアクセスできます。

関数を呼び出すと、関数の引数、呼び出し内のローカル変数などの "バインディング"(プロパティのようなものと考える)が含まれるオブジェクトが作成されます。関数の呼び出しはそのオブジェクトへの参照を保持しているので、関数が返ってもオブジェクトは引き続き存在します。それがJavaScriptのクロージャの基礎です。それで、Personがそのインスタンスのgettersとsettersを作成する呼び出しから戻った後でも、xnameを使用し続けることができます。

パラメータ名をxnameに変更しました。これは、同じ名前のローカル変数とオブジェクトプロパティの使用がさらに混乱していたためです。

これはゲッターでのみ行いました。

function Person(xname) { 
    Object.defineProperty(this, "name", { 
     get: function() { 
      return xname; 
     }, 
     set: function(newName) { 
      xname = newName;  // *** Here too 
     }, 
     configurable: true, 
     enumerable: true 
    }); 
    this.sayName = function() { 
     console.log(this.name); 
    }; 
} 

Object.definePropertyものをすべて多少のポイントの横にある(実際にさえnewは、):それが正しく動作するためにあなたはゲッターセッターの両方でそれを行う必要があります。あなたが見ている基本的な事は、クロージャの仕組みで、それでは、単純な例を見てみましょう:私たちはc1またはc2関数を呼び出すとき、それは使用しています、あなたが見ることができるように

function createClosure(arg) { 
 
    return function() { 
 
    console.log(arg); 
 
    }; 
 
} 
 
var c1 = createClosure("one"); 
 
var c2 = createClosure("two"); 
 
c1(); // "one" 
 
c2(); // "two" 
 
c1(); // still "one" 
 
c2(); // still "two"

createClosureが返されたにも関わらず、その関数が作成されたときにcreateClosureが受け取られた引数argc1(およびc2)にはそれぞれ、作成されたコンテキストの参照があります。それらは、作成された呼び出しに関連するargを「閉じる」。

もっと読み:

+0

OKです。ありがとう。閉鎖は私がまだ知らない方法で働くかもしれません、本はこれまで言及していませんが、私は –

+0

OKです。ありがとう。 クローズは、私がまだ分かっていない方法で動作するかもしれません、本はそれまで言及していませんが、私は本からコードスニペットを取得しません。 彼は "名前"と呼ばれる新しいPersonオブジェクトのプロパティを定義しています。 なぜsetterはnewNameをxname insted of .nameに割り当てるべきですか? definePropertyを使用しない場合、同じコードは何ですか? これは何か? 関数Person(名前){ this.name = name; this.get = function(){return this.name;}; this.set = function(v){this.name = v;}; } –

+0

@ b'stard:もし本が閉鎖をまだカバーしていないのであれば、あなたは上のコードを捨てるべきではないかと思います。あなたは別の本を考えるかもしれません。 Re 'name'と' xname'との比較:getter/setterコードでは、 'Person'への引数の名前は完全に無関係です。それはプロパティが何と呼ばれるかにまったく影響しません。プロパティの名前は 'defineProperty'の第2引数で決まります。ゲッター/セッターを使用するときは、プロパティー自体からデータを格納する場所(存在する場合)をデカップリングします。格納するarg /変数の名前は重要ではありません。 –

関連する問題