0

我有自己的自定义 Javascript 对象,定义如下:

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

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

为简洁起见,我省略了实际的实现,但除了上述之外,我没有做任何特别的事情。问题是,当我实际嵌入类似于 Google Analytics 嵌入方式的脚本时(见下文),我得到Uncaught TypeError: Object #<NewObject> has no method 'fetchConfig'.

在我使用下面的异步代码之前,我从未见过这个问题,它本质上是谷歌修改为指向我的脚本而不是谷歌分析。

我使用的嵌入代码:

<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 中,您编写代码的方式与解析器实际读取代码的方式不同。它按照一定的顺序阅读,归纳为三组:

  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

您可以测试以下代码以查看变量的情况,undefined而不是在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 回答