0

次のように定義された独自のカスタム Javascript オブジェクトがあります。

function NewObject(){
   this.fetchConfig();
}

NewObject.prototype.fetchConfig = function(params){
    [Code]
}

簡潔にするために実際の実装は省略しましたが、上記以外に特別なことは何もしていません。問題は、実際に Google Analytics を埋め込むのと同じようにスクリプトを埋め込むと (下記参照) Uncaught TypeError: Object #<NewObject> has no method 'fetchConfig'、.

以下の非同期コードを使用するまで、この問題は見たことがありませんでした。これは、Google アナリティクスではなく、私のスクリプトを指すように基本的に Google が変更したものです。

私が使用する埋め込みコード:

<script>_object_id = 19782135;
    var tb = document.createElement('script'); tb.type = 'text/javascript';
    tb.async = true; tb.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'cfurl.cloudfront.net/script.min.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(tb, s);
</script>

この問題は、async プロパティの使用によって引き起こされる可能性がありますか (たとえば、プロトタイプが変更される前にスクリプトが実行されるなど)? Web デバッガーを使用して NewObject のプロトタイプを検査しようとしましたが、コンストラクターしか表示されません。私が作成した他のメソッドはデバッガーにまったく表示されません...

4

1 に答える 1

1

これで、完全なコードでエラーが明確にわかります。

JavaScript では、コードの書き方は、パーサーが実際にコードを読み取る方法とは異なります。3つのグループに要約される特定の順序に従って読まれます。

  1. 変数宣言
  2. 関数宣言
  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) {}

ベストプラクティスは、パーサーが行う方法で何かを宣言するか、それらを操作することです。これは、その方法でコードをフォーマットすることも意味します。このようにして、コードに関する混乱が解消されます。

于 2012-12-13T04:57:43.437 に答える