function Foo() {
var that = this;
that.bar = function() {}
that.baz = function() {}
(function() {
that.baz();
}());
}
new Foo;
Uncaught TypeError: Object #<Foo> has no method 'baz'
that.bar
工作正常,它只是最后一个不存在的函数。在;
函数定义之后添加baz
可修复所有内容。
我知道排除;
可能会弄乱一些事情,但我确信你不应该把;
放在功能之后。没有语言可以做到。为什么在;
函数之后排除baz
会导致此错误?我应该在我的函数定义之后放置;
吗?
答案 0 :(得分:9)
与Michael Geary's answer相反,作业语句 不 需要分号。
考虑一下简单的立即调用的函数表达式:
(function() { /* do something */ })();
包裹function() { ... }
的额外括号是什么?它们是为了防止它被解释为函数定义,迫使它被解释为函数表达式。它基本上等同于此,但没有创建另一个变量:
var temp = function() { /* do something */ };
temp();
但括号只是引入必须表达的东西的一种方式。特别是,赋值语句的初始值设定项将引入表达式 1 :
someVar = /* what goes here must be an expression */;
显然,撰写这些概念表明:
someVar = (function() { return 5; })();
实际上并不需要包裹括号!我们可以轻松地写这个,因为function()
不能被解释为函数定义:
someVar = function() { return 5; } ();
那么这与分号有什么关系呢?事实证明,如果下一行可以继续语句或表达式,它将会。 2 你写的是:
that.baz = function() {}
(function() {
that.baz();
}());
有了这些知识,你知道它实际上被解释为:
that.baz = (function() {})(function() {
that.baz();
}());
这有点棘手,所以这就是发生的事情:
function() {}
(不执行),产生一个函数对象。唯一的参数是表达式
function() {
that.baz();
}()
这显然是一个立即调用的函数表达式,所以我们将开始执行它。
that.baz
并调用它,但它失败了,因为that.baz
不存在,因此解析为undefined
!不好了! JavaScript引擎在这里停止,因为抛出了未捕获的异常,但为了清楚起见,让我们假装它继续。 function() { that.baz(); }
返回任何内容,因此function() {}
的参数为undefined
。function() {}
。它永远不会绑定它的参数,因此忽略undefined
。它不会返回任何内容,因此调用会生成undefined
。that.baz
设置为结果undefined
。希望您现在看到解析器误解了您的立即调用的函数表达式,因为它是另一个匿名函数的参数,立即调用 it 。
如前所述,括号不是明确引入表达式的唯一方法。事实上,当他们无意中处于表达的中间时,它可能会导致这样的问题。我们还提到了作业,但我们不想分配内容。
还剩下什么? 一元运营商。 我们可以使用一些。我喜欢!
,所以我们会用它。而不是使用:
(function() {
that.baz();
}());
我们使用:
!function() {
that.baz();
}();
!
只能出现在表达式的开头,因此JavaScript开始解析表达式。只有表达式可以在!
之后出现,因此该函数被解析为函数表达式而不是函数定义。由于优先级,首先调用该函数。它不返回任何内容,因此返回undefined
。 undefined
是假的,所以!
翻转它并产生true
。由于我们从未对此表达式的结果执行任何操作,因此true
将被丢弃。 (如果我们返回一个真正的值,它就不重要;然后!
会产生false
并且会被丢弃。无论如何,它都会被丢弃。)
1 技术上,赋值是表达式,而不是声明,但对于我们的目的而言,它无关紧要。
2 return
,continue
,break
以及类似的陈述除外,它会使多混淆更多。
答案 1 :(得分:5)
函数声明后不需要分号:
function foo() {
}
如果你添加分号,没有任何伤害,你只需要它:
function foo() {
};
在函数声明后插入一个空语句,该语句无效。以同样的方式,这不会造成伤害,除了让阅读代码的人感到困惑:
var i = 1;;;;;;;;;;;;;;;;;;;;;;;;;;
OTOH,你做在转让声明后需要一个分号:
that.prop = 1;
如果您指定的值是函数表达式,则不会更改:
that.foo = function() {};
答案 2 :(得分:0)
这也可行
function Foo() {
var that = this;
{ that.bar = function() {} }
{ that.baz = function() {} }
(function() {
that.baz();
}());
}
new Foo;
得到它?
他们是两个陈述。他们需要两个结局。