块内部的代码包含在parens中。为什么?

时间:2013-03-11 15:03:14

标签: javascript

我遇到了这段代码,并且不明白为什么块中的代码像自动执行函数一样包含在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中。

6 个答案:

答案 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引用执行容器,例如, windowa包含需要执行的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的第一个参数。