括号中的构造函数调用时,JavaScript原型函数未定义

时间:2018-11-16 09:50:23

标签: javascript

为什么

function Example() {
  this.go();
}
Example.prototype.go = function() {
    console.log("going");
  }
  (new Example());

对我说this.go不是一个函数,而

function Example() {
  this.go();
}
Example.prototype.go = function() {
  console.log("going");
}
new Example();

是否按预期正确记录?

执行环境是macOS High Sierra 10.13.4上的节点v10.4.1

3 个答案:

答案 0 :(得分:3)

您依赖ASI,它无法按您期望的方式工作。

在第一个示例中,()将您尝试分配给Example.prototype.go的函数表达式转换为IIFE

因此,事件的顺序是:

  1. Example已定义
  2. new Example()得到评估
  3. 结果将作为参数传递给匿名函数的调用
  4. 该函数(undefined)的返回值已分配给Example.prototype.go

…,但是由于在该点未定义go,因此在第2步出错。

为了避免这种情况,请在每个语句的末尾使用明确的分号。

答案 1 :(得分:2)

这是因为您依赖自动分号插入(ASI)(可能是无意的),而且还以(开始。如果您使用;正确终止了分配,则问题将消失:

function Example() {
  this.go();
}
Example.prototype.go = function() {
    console.log("going");
}; // <==== ; here
(new Example());

问题是没有 ;,赋值后的()表达式和其前面的function() { }表达式在语法上结合在一起-(但不是逻辑上有效的方式):它调用函数,并传递new Example的结果。因此ASI不会介入。

如果您不是故意依赖ASI,只需注意赋值表达式需要以;结尾。

如果您有意依赖ASI,则由于这个原因,您必须以主动(开始以[;开头的行。因此,在您的情况下:

    function Example() {
      this.go();
    }
    Example.prototype.go = function() {
        console.log("going");
    }
    ;(new Example());
//  ^----

答案 2 :(得分:1)

问题是您在分配给.go的函数 expression 后忘记了分号:

Example.prototype.go = function() {
  console.log("going");
} // <--- no semicolon!
(new Example());

以下行带有开括号()-因此,解释器认为您正在立即调用上述函数:

Example.prototype.go = function() {
  console.log("going");
}(new Example());

这是在 被分配给Example.prototype.go之前发生的-解释器试图在将结果分配给{{1}之前将表达式的右侧求值}。但是,您是在Example.prototype.go被填充之前打电话给new Example()。因此,Example.prototype.gothis.go

只需在undefined后面加上分号即可:

}