2016-06-28 7 views
1

私はJavaScriptを学んでいます(最新のGoogle Chromeを使って64ビットDebian Jessieをビルドしています)、今、私はちょうどObject.definePropertyがどのくらい正確に動作しているか理解していません。私はconsole.log(...)内のプロパティを使用しようとするラインでUncaught TypeError: Cannot read property 'fullName' of undefinedを得るObject.defineProperty - オブジェクトを返す関数内のスコープと使用?

function createPerson() { 
    var person = { 
     firstName: 'Lilly', 
     lastName: 'Louis', 
    }; 

    Object.defineProperty(person, 'fullName', { 
     get: function() { 
      return this.firstName + ' ' + this.lastName; 
     }, 
     set: function(name) { 
      var words = name.split(' '); 
      this.firstName = words[0] || ''; 
      this.lastName = words[1] || ''; 
     } 
    }); 
} 

var p1 = createPerson(); 
console.log("Person's default name is \"" + p1.fullName + "\""); 

:私は以下のページを持っています。関数の外にObject.definePropertyと一緒にpersonという定義を置くと、すべて正常に動作します。私はp1後に関数の外のみObject.definePropertyを移動した場合、次のように作成されます。

var p1 = createPerson(); 
Object.defineProperty(p1, 'fullName', { 
    get: function() { 
     return this.firstName + ' ' + this.lastName; 
    }, 
    set: function(name) { 
     var names = name.split(' '); 
     this.firstName = names[0] || ''; 
     this.lastName = names[1] || ''; 
    } 
}); 

は、私は、コンソールは、それが(anonymous function)(つまりp1です)さらに混乱している時に呼び出されていることを指摘続いUncaught TypeError: Object.defineProperty called on non-objectを取得私が​​を私のp1にブラケットなしで代入すれば、関数オブジェクトをそれに渡します。それ以外の場合は、関数自体を呼び出して戻り値を代入しています(返り値がない場合未定義が返されます)。 p1

私は両方の問題が完全に別々であると感じていますが、私は同じ質問に両方を入れることを100%確信していないからです。私がここで間違っていることについて何かアドバイスはありますか?私は単に

function createPerson() { 
    var person = { 
     firstName: 'Lilly', 
     lastName: 'Louis', 
     getFullName: function() { 
      return ...; 
     } 
     setFullName: function(name) { 
      ... 
     } 
    }; 
} 

を行うことで、私のgettersetter昔ながらの方法を定義することができますが、私はここで何が起こっているのかを理解したいと思います。 :D

答えて

4

あなたのdefinePropertyコールは絶対にうまくいきます。問題は、createPersonは何も返さないので、呼び出した結果はundefinedです。あなたは最後にreturn person;をしたい:

function createPerson() { 
 
    var person = { 
 
    firstName: 'Lilly', 
 
    lastName: 'Louis', 
 
    }; 
 

 
    Object.defineProperty(person, 'fullName', { 
 
    get: function() { 
 
     return this.firstName + ' ' + this.lastName; 
 
    }, 
 
    set: function(name) { 
 
     var words = name.split(' '); 
 
     this.firstName = words[0] || ''; 
 
     this.lastName = words[1] || ''; 
 
    } 
 
    }); 
 
    
 
    return person; // <======= 
 
} 
 

 
var p1 = createPerson(); 
 
console.log("Person's default name is \"" + p1.fullName + "\"");

代わりに、それ(newで使用)コンストラクタ機能ではなく、ファクトリ関数作り、関数内thisを使用しています。この場合、名前からcreateを削除し、最後にreturn this;を使用しません。これは、関数が別のオブジェクトを返さない場合、デフォルトでnew XYZの結果がnewオペレータとthisとしての機能に供給された:

function Person() { 
 
    this.firstName = 'Lilly'; 
 
    this.lastName = 'Louis'; 
 

 
    Object.defineProperty(this, 'fullName', { 
 
    get: function() { 
 
     return this.firstName + ' ' + this.lastName; 
 
    }, 
 
    set: function(name) { 
 
     var words = name.split(' '); 
 
     this.firstName = words[0] || ''; 
 
     this.lastName = words[1] || ''; 
 
    } 
 
    }); 
 
} 
 

 
var p1 = new Person(); 
 
console.log("Person's default name is \"" + p1.fullName + "\"");

+0

の周りにコードを移動しながら、手のひらを顔に当てる* *キリスト、私は(ここに)私のコードでそれを削除しました。だから私の愚かな...それを指摘してくれてありがとう。 – rbaleksandar

1

これは、あなたがperson変数を作成しているためですが、それを返されることはありません。したがって、何も関数から返さされていない、と割り当てが定義されていない:

function createPerson() { 
    var person = { 
     firstName: 'Lilly', 
     lastName: 'Louis', 
    }; 

    Object.defineProperty(person, 'fullName', { 
     get: function() { return this.firstName + ' ' + this.lastName; }, 
     set: function(name) { 
      var words = name.split(' '); 
      this.firstName = words[0] || ''; 
      this.lastName = words[1] || ''; 
     } 
    }); 
    return person; // Add this line 
} 
関連する問題