javascript如何解析参数?

tho*_*hal 8 javascript

我是一个陌生的人JavaScript,来自不同的编程背景,我很难理解如何JavaScript知道如何解析传递给函数的参数。

让我们看一个简单的例子。从jQuery文档中 .on,我看到2个不同的签名:

.on(事件[,选择器] [,数据],处理程序)

.on(事件[,选择器] [,数据])

但是,以下代码段可以产生完全有效的代码,并且可以完成预期的工作:

$(function() {
  let dat = {a: 1, b: 2}
  $('#do').on('click', dat, function(evt) {
    alert(evt.data.b);
  });
  $('#do2').on('click', function(evt) {
    alert("click");
  });
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="do">
  Click!
</button>
<button id="do2">
  Click!
</button>
Run Code Online (Sandbox Code Playgroud)

如何JavaScript“知道” dat第一种情况下的数据(而不是selector)?显然,两个签名都没有位置匹配吗?那么,它在内部如何工作?如何在自己的功能中使用此模式?

ggo*_*len 5

查看的jQuery源代码on,手动检查类型,手动忽略所有省略的参数(参数始终从左到右填充):

function on( elem, types, selector, data, fn, one ) {
    var origFn, type;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {

        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {

            // ( types-Object, data )
            data = data || selector;
            selector = undefined;
        }
        for ( type in types ) {
            on( elem, type, selector, data, types[ type ], one );
        }
        return elem;
    }

    if ( data == null && fn == null ) {

        // ( types, fn )
        fn = selector;
        data = selector = undefined;
    } else if ( fn == null ) {
        if ( typeof selector === "string" ) {
Run Code Online (Sandbox Code Playgroud)

...等等。

非动态类型背景可能会令人震惊,但这在JS中非常普遍。

  • 我还需要检查源代码,以了解jQuery的这一功能只是将if语句与typeof结合使用。 (2认同)
  • 是的,这有点像您在JS中看到的流畅语法,例如`expect(foo).not.toBe(bar)`。首先,它的工作原理令人惊奇,然后研究它之后,发现它根本不是魔术,然后再进一步看,实际上对于图书馆的客户来说似乎不太清楚,我想知道为什么他们会经历所有麻烦。 (2认同)

T.J*_*der 4

\n

JavaScript 如何“知道”第一种情况是数据(而不是选择器)?

\n
\n\n

事实并非如此。该语言只是将调用者给出的参数传递给函数。弄清楚调用者传递的内容是由函数而不是语言来处理的。

\n\n
\n

显然两个签名都没有位置匹配?

\n
\n\n

JavaScript使用位置匹配。从 ES2015+ 开始,它还将为缺少的参数(或传递的参数为 value 的参数undefined)提供默认值。

\n\n
\n

那么它在内部是如何工作的以及我如何将这种模式用于我自己的功能呢?

\n
\n\n

在 JavaScript 中,您不必向函数传递与函数声明的参数数量相同的参数;你可以通过更少或更多。该函数可以通过三种方式告诉您传递的内容:

\n\n
    \n
  • 通过查看为arguments每个函数创建的特殊的类似数组的对象,该对象包含参数和一个length表示有多少个参数的属性。
  • \n
  • 通过查看参数的值和/或其类型。如果调用者未提供参数的参数,则参数的值将是该值undefined
  • \n
  • 在 ES2015+ 中,通过使用剩余参数来收集该位置处的所有提供的参数,然后将其收集到一个真正的数组中。
  • \n
\n\n

这是一个例子:

\n\n

\r\n
\r\n
function example(obj, number, str) {\r\n    console.log("Arguments received: " + arguments.length);\r\n    if (typeof number === "string") {\r\n        // Caller provided a string, not anumber, as the second\r\n        // argument; move things around\r\n        str = number;\r\n        number = undefined;\r\n    }\r\n    console.log("obj", obj);\r\n    console.log("number", number);\r\n    console.log("str", str);\r\n}\r\nconsole.log(\'Calling example({}, 42, "forty-two");\');\r\nexample({}, 42, "forty-two");\r\nconsole.log(\'Calling example({}, "no number given");\');\r\nexample({}, "no number given");
Run Code Online (Sandbox Code Playgroud)\r\n
.as-console-wrapper {\r\n    max-height: 100% !important;\xc2\xa3\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

这是使用剩余参数的示例:

\n\n

\r\n
\r\n
function example(obj, ...rest) {\r\n    let number, str;\r\n    if (rest.length === 2) {\r\n        [number, str] = rest; // This is called "destructuring assignment"\r\n    } else {\r\n        [str] = rest;\r\n    }\r\n    if (typeof number === "string") {\r\n        // Caller provided a string, not anumber, as the second\r\n        // argument; move things around\r\n        str = number;\r\n        number = undefined;\r\n    }\r\n    console.log("obj", obj);\r\n    console.log("number", number);\r\n    console.log("str", str);\r\n}\r\nconsole.log(\'Calling example({}, 42, "forty-two");\');\r\nexample({}, 42, "forty-two");\r\nconsole.log(\'Calling example({}, "no number given");\');\r\nexample({}, "no number given");
Run Code Online (Sandbox Code Playgroud)\r\n
.as-console-wrapper {\r\n    max-height: 100% !important;\xc2\xa3\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n