2

查看这段 JavaScript 代码:

(function (w, d) {
    var loader = function () {
        var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0];
        s.src = "https://example.org/script.js";
        tag.parentNode.insertBefore(s,tag);
    };
    w.addEventListener ? w.addEventListener("load", loader, false) :
                         w.attachEvent("onload", loader);
}) (window, document);

为什么这段代码的作者使用这种方法在文档中包含一个脚本?该行的用处是什么:

w.addEventListener ? w.addEventListener("load", loader, false) :
                     w.attachEvent("onload", loader);

最后一点:我是一个JavaScript初学者,最后是什么(window, document)

4

10 回答 10

3

第一个问题,代码检查是否window.addEventListener已定义。如果是,则使用它,否则使用window.attachEvent. 这是为了浏览器兼容性。

第二个问题,这段代码是一个匿名函数,它有两个参数,w 和 d。立即调用此函数,传递参数windowdocument.

于 2012-04-09T01:00:24.840 回答
2

首先w.addEventListener ?确定浏览器是否支持window的addEventListener方法

其次,(window, document)只是他之前写的匿名函数的参数调用function(w,d) {}

于 2012-04-09T01:01:33.070 回答
2

下面的 addEventListener 行是注册函数,以便在页面完成加载时调用它。Internet Explorer 和 Firefox (et al) 使用不同的函数来执行此操作。

w.addEventListener ? w.addEventListener("load", loader, false) :
                 w.attachEvent("onload", loader);

在 javascript 中,函数本身就是一个对象。因此,它的“值”可以分配给变量或立即使用。要立即使用它,它必须用括号括起来(否则它不会做你想要的),然后像普通函数一样调用它。

(function (w, d) { ... }) (window, document);

如果我们把它分成两条线,情况会更明显。

var a = function(w, d){ ... };
a(window, document);

这样做是为了不让临时值或函数污染全局范围。更不用说不破坏其他任何变量。这可以分为两部分:

  1. 通过将代码封装在闭包中,任何在内部显式声明的内容都在闭包的范围内,而不是全局范围内。var loader在闭包的范围内。
  2. 通过立即使用闭包,它不会存储在全局范围内的变量中。由于它是匿名声明的,因此它不会作为命名函数存在于全局范围内。
于 2012-04-09T01:16:15.330 回答
1

看起来作者在附加脚本标记之前正在等待页面完全加载。addEventListener(DOM 级别 2)和 attachEvent(微软的东西)是更灵活的附加事件的方式。代码类似于说w.onload = loader

最后一点是将参数传递给匿名函数,它们被命名为wand d。通过将 () 放在末尾,匿名函数立即被调用。

于 2012-04-09T01:00:43.933 回答
1

所以这个函数被包裹在一个闭包中。这又意味着w = windowd = document

当该方法被调用时,它会创建一个被调用的函数,该函数loader是两个可能的事件侦听器触发器之一的回调(意思是,在窗口上调用loador事件时将调用该函数)。onload

x ? y : z语法是速记if then else调用。

如果我们扩展它,它看起来像这样:

if (w.addEventListener) {
  w.addEventListener("load", loader, false);
} else {
  w.attachEvent("onload", loader);
}

该语句用于满足 IE 和其他浏览器的方法。

于 2012-04-09T01:01:18.483 回答
1

这实际上与以下内容相同:

function RegisterEventListener(w, d) {
    var loader = function () {
        var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0];
        s.src = "https://example.org/script.js";
        tag.parentNode.insertBefore(s,tag);
    };
    if (w.addEventListener) {
       w.addEventListener("load", loader, false);
    } else {
       w.attachEvent("onload", loader);
    }
}

RegisterEventListener(window, document);

唯一真正的区别是:

  1. 如果您定义匿名函数(使用function () {};)而不将其分配给任何东西,则它只能用于有限的使用(因为无法引用它)。同时,匿名函数也允许立即执行(就像你的问题代码中的那个function(a, b) {}(a, b);
  2. (condition ? true : false三级运算符) 只是编写简单if语句的简写,因此它需要更少的输入来写出,但有些人也认为它的可读性较差。
于 2012-04-09T01:02:07.000 回答
1

我可能错了,但这是 Google 使用他们的分析脚本的实现。

这称为闭包,这是一个自动执行的函数并将变量包含在其中,因此它们不会与您的代码混淆。

这段代码实质上创建了一个脚本标签,并将其附加到 DOM 中它在文档中找到的第一个脚本标签之前。

第一个问题的答案是关于浏览器兼容性。一些浏览器使用addEventListener和其他浏览器attachEvent将事件附加到页面中的元素(在本例中为窗口),它会在窗口的加载事件上启动(当所有内容加载时,文档准备好后)。看看这个以获得更详细的答案:window.onload vs $(document).ready()

第二个答案很简单。这是闭包(自动调用函数)中使用的参数,可以这样读取:

function anonymous(w, d) {
    ...
}
anonymous(window, document);
于 2012-04-09T01:05:52.433 回答
1

这段代码的作者使用了一个封装在闭包中的匿名函数来触发该函数,该函数注册了一个加载事件。在窗口的 onload 事件触发之前,页面上的脚本实际上不会被加载。

作者可能会延迟脚本加载的原因可能是在实际加载其他脚本之前给网页更多时间来呈现。这是一种很好的技术,可以快速加载页面内容,同时延迟加载不需要的资源。

作者使用的技术是一个封装在闭包中的匿名函数。想象一下:

myFunction (window, document);

现在,我将用匿名函数替换函数调用:

function(w, d) {
    // do stuff
    alert("w = " + w); 
    alert("d = " + d);
}

现在我要让这个函数立即运行,而不是给它一个名字。我还将向该匿名函数传递两个参数:

( function(w, d) {
      // do stuff
      alert("w = " + w);
      alert("d = " + d);
})  ("1234", "5678");

此示例中的输出将是:

w = 1234
d = 5678

如果你观察括号并将它们匹配起来,第一个外括号匹配最后一行字符 2 处的右括号,即函数名称,下面的一组括号将作为参数传递给函数的两个值包装起来。

一开始这可能是一个很难掌握的概念。在你看到它做了几次之后,它开始变得更有意义了。

于 2012-04-09T01:06:06.257 回答
1
  1. 以这种方式添加脚本允许作者将该脚本包含在文档中,而无需直接编辑 HTML 文件。也可用于仅在需要时动态加载脚本。(即,如果您有一堆代码来编辑页面上的某些内容,则在用户实际单击编辑按钮之前您不想下载它,因此您不会在不需要时浪费带宽)。

  2. addEventListener 和 attachEvent 是在页面完成加载时触发要调用的函数的方法。在这种情况下,有一个函数名为loader The 两者的原因是有些浏览器支持一个,有些支持另一个。我已经使用 jQuery 足够长的时间了,以至于我不记得哪个是哪个。

  3. (window, document) 是一种将这些变量封装在范围内和/或通过简写 w 和 d 引用它们的方法。作者正在创建一个需要这些参数的函数,然后将 window 和 document 作为参数传递给它们。

关闭还有助于作者避免他的脚本与页面上的其他脚本发生冲突。将其中声明的每个变量想象成其他语言中的私有变量。

于 2012-04-09T01:06:08.140 回答
1

window, document一个代码块末尾的 是代码块其余部分中定义的匿名函数的参数。由于 Javascript 几乎是一种函数式语言,因此允许程序员定义这些匿名函数,甚至可以在不给它们命名的情况下使用它们。

您粘贴的带有问号的代码块是中缀表示法的一个示例,一种适合这种模式的语言结构:condition ? ifTrueExpression : ifFalseExpression. 如果condition为真,则整个表达式将等于ifTrueExpression。否则,整个表达式将等于ifFalseExpression

您粘贴的中缀符号的使用在检测正在使用哪种类型的 Internet 浏览器时很常见。虽然,我不确定这段代码试图检测哪个浏览器,但它的目的是以浏览器特定的方式实现事件处理程序。

于 2012-04-09T01:14:10.807 回答