我的HTML文件中包含以下代码:
<script type="text/javascript">
window.never = function() {
console.log('this function is never called');
}
(function(d, s, id){
var js, srjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "this.script.does.not.exist.js";
srjs.parentNode.insertBefore(js, srjs);
}(document, 'script', 'streamrail-jssdk'));
</script>
请参阅小提琴:http://jsfiddle.net/sebvaeja/
查看控制台,您可以看到实际调用了window.never
函数('此函数永远不会被调用'写入控制台)。
使用Chrome开发工具调试时,我在调用堆栈中看到调用者是闭包(第一行:http://jsfiddle.net/sebvaeja/
)。
如果我将never函数更改为全局范围:
function never() {
console.log('this function is never called');
}
然后它没有被调用。
有人可以解释为什么是window.never函数被调用?什么是触发通话?我想这与窗口对象上的函数有关,但我看不出背后的原因。
答案 0 :(得分:13)
函数表达式后跟括号:
window.never = function() { ... }
(...)
函数表达式后的换行符不终止变量语句,因此对于函数调用的解析器:
function() { ... }(...)
事实上,你在这里使用的技术非常相似:
(function(d, s, id){
// ...
}(document, 'script', 'streamrail-jssdk'))
这是一个函数表达式,后跟(...)
,它调用函数。
解决方案:在定义后添加分号,你就是好的。
如果我将never函数更改为全局范围......那么它就不会被调用。
在这种情况下,函数定义被解释为函数声明,而不是表达式。函数声明更像是一个语句,因此不能成为 CallExpression 的一部分。因此,以下括号被解释为分组运算符(如您所愿)。
答案 1 :(得分:5)
在函数声明后放置分号:
window.never = function() {
console.log('this function is never called');
};
这是因为之后的(...)
会触发函数调用。
window.never = function() {
console.log('this function is never called');
}
( ... ) // <-- Triggers call of `window.never`