Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 块中的代码被包装在parens中。为什么?_Javascript - Fatal编程技术网

Javascript 块中的代码被包装在parens中。为什么?

Javascript 块中的代码被包装在parens中。为什么?,javascript,Javascript,我遇到了这段代码,不明白为什么块中的代码像自动执行函数一样包装在paren中 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)

我遇到了这段代码,不明白为什么块中的代码像自动执行函数一样包装在paren中

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);
  }
}
函数foo(a,b){ var b=b | |窗口, a=a.replace(/^\s* 第一个参数是来自脚本标记的文本。我唯一没有得到的部分是为什么脚本eval被包装在parens中。

因为之后的
(a)
。表达式:

(b.execScript || function (a) {
      b["eval"].call(b, a)
    })

返回一个闭包,然后使用作为参数传递的
a
执行该闭包。

由于
|
运算符绑定得比函数调用运算符
()
松散,因此将使用括号括起表达式。如果没有括号,表达式的计算方式将与编写表达式一样:

b.execScript || (function (a) { b["eval"].call(b, a); })(a)
也就是说,它可能是
b.execScript
的普通值,也可能是调用该函数的值。作者想要的是调用
b.execScript
的值(可能是一个函数)或那个小的匿名函数

(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[“评估”]呼叫(b,a) })(a)
}

我想你说的是这一部分:

(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”]。调用(b,a)

分组运算符的目的是在函数调用之前计算
。| |…
,即,无论分组运算符的结果是什么,它都被视为函数,并通过向其传递
a
来调用

看起来代码可以简化为

(b.execScript || b["eval"])(a);

虽然有必要将
this
显式设置为
b
,但函数表达式也有必要,因为要有两个只接受一个参数的函数,
a
,插入式表达式将返回b.execScript的结果或一个新函数。在这两种情况下,都会使用参数。参数确保解释器在调用之前计算| |

为什么块中的代码像自动执行函数一样包装在参数中

因为代码的特定部分是一个自动执行的函数:

(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()的第一个参数
定义了调用
tmp
时该
所指的内容;第二个参数成为
tmp

的第一个参数……除非在非窗口
b
的上下文中不需要调用
eval
。也许,我还没有真正了解该代码应该做什么。在jQuery