これで、完全なコードでエラーが明確にわかります。
JavaScript では、コードの書き方は、パーサーが実際にコードを読み取る方法とは異なります。3つのグループに要約される特定の順序に従って読まれます。
- 変数宣言
- 関数宣言
その他すべて、スコープに表示される順序に従います。これも
- 操作 (関数呼び出し、条件、ループなど)
- 変数の割り当て (変数、関数式、プロトタイプの割り当て)
- 私が逃した他のすべて
たとえば、次のコード:
new foo();
function foo(){...}
foo.prototype.bar = function(){...};
var bar = 'baz';
実際には、パーサーには次のように見えます。
var bar; //variable declaration
function foo(){...}; //function declaration
//operations and assignments
new foo(); //this is foo, but no bar yet
foo.prototype.bar = function(){}; //function expressions (prototype assignment)
bar = 'baz'; //variable assignment
次のコードをテストして、コード内で宣言がその後にある場合でも、変数がundefinedat ではなくどのようになっているかを確認できます。console.log()これは、宣言が「持ち上げられた」が、割り当てではないためです。したがって、変数は認識されますが、値は認識されません。違いを確認するために、存在しない変数との比較が行われます。
console.log('ndefined is:',ndefined); //undefined, sees the variable
console.log('notDefined is:',notDefined); //not defined, non-existent variable
var ndefined = 'I should be defined!!!';
今あなたのコードでは、このコード:
if (_object_id) {...new NewObject(_object_id)...}
function NewObject(params) {...return this.fetchConfig(params)...}
NewObject.prototype.fetchConfig = function (id) {}
パーサーが解析する順序により、パーサーには次のように表示されます。
//priority 2: function declarations
//function declarations are "hoisted up"
function NewObject(params) {...return this.fetchConfig(params)...}
//priority 3: assignments and operations
//at this point, fetchConfig is not yet in the prototype
//yet your constructor uses it, hence the error
if (_object_id) {...new NewObject(_object_id)...}
NewObject.prototype.fetchConfig = function (id) {}
要するに、ifステートメントは、巻き上げられたためにコンストラクターを見ました。しかし、コンストラクターはfetchConfigその時までに持っていませんでした。これを修正するには、順序を変更します。
function NewObject(params) {...return this.fetchConfig(params)...}
if (_object_id) {...new NewObject(_object_id)...}
NewObject.prototype.fetchConfig = function (id) {}
ベストプラクティスは、パーサーが行う方法で何かを宣言するか、それらを操作することです。これは、その方法でコードをフォーマットすることも意味します。このようにして、コードに関する混乱が解消されます。