我遇到了这段代码,并且不明白为什么块中的代码像自动执行函数一样包含在parens中。
function foo(a,b) {
var b = b || window,
a = a.replace(/^\s*<!(?:\[CDATA\[|\-\-)/, "/*$0*/");
if (a && /\S/.test(a)) {
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
}
}
第一个参数是脚本标记中的文本。我没有得到的唯一部分是为什么脚本eval包含在parens中。
答案 0 :(得分:5)
我假设你在谈论这一部分:
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
这是一种简短的写作形式:
if (b.execScript) {
b.execScript(a);
}
else {
b["eval"].call(b, a);
}
即。如果已定义,则执行b.execScript
,否则请调用b["eval"].call(b, a)
。
分组运算符的目的是在函数调用之前评估... || ...
,即无论分组运算符的结果是什么,它都被视为函数并通过将a
传递给它来调用。 / p>
看起来代码可以简化为
(b.execScript || b["eval"])(a);
虽然如果需要明确地将this
设置为b
,那么函数表达式也是必要的,以便有两个函数只接受一个参数a
。
答案 1 :(得分:4)
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a)
这包含在parens中,因为需要评估||
语句以确定在传递参数之前要运行的函数。
如果b.execScript
存在并且是真实的话,此代码会使用参数a
调用b.execScript
。否则它定义一个新函数并将a
作为参数传递给它。
parens wrap是为了确保在执行函数之前评估||
语句。如果没有它,逻辑基本上就会出现,如果b.exec不存在,则计算自定义函数的值,如果是,则计算为b.exec。
因此,对于parens,逻辑相当于:
if(b.execScript){
b.execScript(a)
}
else{
function (a) {
b["eval"].call(b, a)
})(a)
}
没有它,它相当于
如果(!b.execScript){ 功能(a){ b [“eval”]。电话(b,a) })(一个) }
答案 2 :(得分:3)
它是括号的,因为||
运算符比函数调用运算符()
绑定得更松散。如果没有括号,则表达式将被评估为好像已写入:
b.execScript || (function (a) { b["eval"].call(b, a); })(a)
也就是说,它可以是b.execScript
的普通值,也可以是调用该函数的值。作者想要的是调用b.execScript
(可能是一个函数)或这个小匿名函数的值。
答案 3 :(得分:2)
因为事后(a)
。表达式:
(b.execScript || function (a) {
b["eval"].call(b, a)
})
返回一个闭包,然后以a
作为参数传递执行。
答案 4 :(得分:0)
括号表达式返回b.execScript的结果或新函数。在任何一种情况下,都会使用a作为参数调用结果。 parens确保解释器评估||在调用之前。
答案 5 :(得分:0)
为什么块中的代码包含在像自动执行函数这样的parens中。
因为代码的特定部分是自动执行功能:
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
这里,变量b
引用执行容器,例如, window
和a
包含需要执行的JavaScript代码。
由于某些浏览器支持execScript()
,而有些浏览器仅支持eval()
,因此代码通过测试此浏览器功能来支持它们:
var tmp = b.execScript || function (a) {
b["eval"].call(b, a)
};
这里,tmp
是一个函数,它接受一个参数a
并执行其中的代码;如果execScript
不可用,则使用小帮助函数。然后它被称为:
tmp.call(b, a);
.call()
的第一个参数定义this
在调用tmp
时所指的内容;第二个参数成为tmp
的第一个参数。