【问题标题】:How Previous Function passes its result to callbackPrevious Function 如何将其结果传递给回调
【发布时间】:2015-04-26 19:21:56
【问题描述】:

我试图了解在这种情况下回调是如何工作的。

例如给出这段代码:

var images = jQuery.map((1234567 + '').split(''), function(n) {
  return '<img src="' + n + '.png" />'
})

一个匿名函数作为回调传入,但每次拆分后如何神奇地填充“n”?它是如何传递给 n 参数的?我的意思是我不会假设 split 会将其价值注入 n..它怎么知道这样做?

让我们再举一个例子,但这一次,我们显式地将参数传递给回调函数

function randomGenerator(min, max, callback)
{
   var myNumber = Math.floor(Math.random() * (max - min + 1)) + min;
   setTimeout(function() { callback(myNumber); }, 500);
}

这很简单,很明显 myNumber 是如何连接(显式传递)到 callback();

问题是在我的第一个示例中隐式是如何做到的?我的意思是我可以假设 map() 在引擎盖下发生的事情比我知道的要多得多吗?也许我必须深入研究我猜想的 jQuery 库中 Map() 的实现......或者是否有一些关于 JS 中的隐式赋值如何工作的一般常识?

【问题讨论】:

  • 我的问题仍然没有得到真正的回答。我想知道 JS 是如何在幕后做到这一点的。地图函数 JS 如何将数字传递给回调的参数。我的意思是它不可能是魔法,但它是如何在非常低的水平上做到这一点的?我不只是从表面上看这个东西,所以这就是为什么我试图更深入地弄清楚它在 JS 中是如何工作的。而且我已经明白我正在发送一个回调函数,我说过。我只是不明白它将数字连接到 n 有多么神奇(我猜在非常低级的 JS 中)
  • 我的意思是我可以创建自己的函数来接受回调,其中回调有一个参数,并且我的初始函数以某种方式神奇地将某些东西映射到该回调的参数?我不明白如何
  • 我并不是想从顶层理解 map 函数的定义,我想知道 JS 是如何在后台工作以实现这种参数注入的!
  • 我在原帖中更新并添加了更多内容,请再次阅读,希望这有助于您了解我想要达到的目的
  • 这不是隐含的——它是.map() 工作方式的定义。它在内部是如何工作的?那么,any 函数调用是如何工作的呢?运行时可以访问数组,并且可以调用函数。传递参数是调用函数的固有部分。

标签: javascript callback


【解决方案1】:

这就是.map() 函数的作用。 .split() 调用只是构建.map() 将在其上迭代的数组。

传递给.map() 的函数对数组中的每个元素(第一个参数)调用一次。每次调用都使用三个参数:数组中元素的值;元素的 index 和数组本身。您的匿名函数只有一个参数(这是常见的),所以这将是元素值。

【讨论】:

    【解决方案2】:

    您已指定匿名函数,其签名采用参数“n”。 在内部,map 函数调用匿名函数,为参数“n”提供具体对象。如果你删除参数它不会工作

    【讨论】:

      【解决方案3】:

      为数组中的每个元素调用指定的映射函数。字符串只是一个字符数组。

      【讨论】:

        【解决方案4】:

        函数是与 JavaScript 中的任何其他对象一样的对象。您可以将它们作为参数传递给其他函数,然后其他函数可以随心所欲地使用它。

        function do_something_with_two_numbers(something, num1, num2) {
            return something(num1, num2); 
        }
        
        function add(a,b) { return a + b };
        function subtract(a,b) { return a - b };
        
        alert(do_something_with_two_numbers(add, 2, 1));
        alert(do_something_with_two_numbers(subtract, 2, 1));

        MDN has a polyfill 作为map 的完整示例:

        // Production steps of ECMA-262, Edition 5, 15.4.4.19
        // Reference: http://es5.github.io/#x15.4.4.19
        if (!Array.prototype.map) {
        
          Array.prototype.map = function(callback, thisArg) {
        
            var T, A, k;
        
            if (this == null) {
              throw new TypeError(' this is null or not defined');
            }
        
            // 1. Let O be the result of calling ToObject passing the |this| 
            //    value as the argument.
            var O = Object(this);
        
            // 2. Let lenValue be the result of calling the Get internal 
            //    method of O with the argument "length".
            // 3. Let len be ToUint32(lenValue).
            var len = O.length >>> 0;
        
            // 4. If IsCallable(callback) is false, throw a TypeError exception.
            // See: http://es5.github.com/#x9.11
            if (typeof callback !== 'function') {
              throw new TypeError(callback + ' is not a function');
            }
        
            // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
            if (arguments.length > 1) {
              T = thisArg;
            }
        
            // 6. Let A be a new array created as if by the expression new Array(len) 
            //    where Array is the standard built-in constructor with that name and 
            //    len is the value of len.
            A = new Array(len);
        
            // 7. Let k be 0
            k = 0;
        
            // 8. Repeat, while k < len
            while (k < len) {
        
              var kValue, mappedValue;
        
              // a. Let Pk be ToString(k).
              //   This is implicit for LHS operands of the in operator
              // b. Let kPresent be the result of calling the HasProperty internal 
              //    method of O with argument Pk.
              //   This step can be combined with c
              // c. If kPresent is true, then
              if (k in O) {
        
                // i. Let kValue be the result of calling the Get internal 
                //    method of O with argument Pk.
                kValue = O[k];
        
                // ii. Let mappedValue be the result of calling the Call internal 
                //     method of callback with T as the this value and argument 
                //     list containing kValue, k, and O.
                mappedValue = callback.call(T, kValue, k, O);
        
                // iii. Call the DefineOwnProperty internal method of A with arguments
                // Pk, Property Descriptor
                // { Value: mappedValue,
                //   Writable: true,
                //   Enumerable: true,
                //   Configurable: true },
                // and false.
        
                // In browsers that support Object.defineProperty, use the following:
                // Object.defineProperty(A, k, {
                //   value: mappedValue,
                //   writable: true,
                //   enumerable: true,
                //   configurable: true
                // });
        
                // For best browser support, use the following:
                A[k] = mappedValue;
              }
              // d. Increase k by 1.
              k++;
            }
        
            // 9. return A
            return A;
          };
        }
        

        【讨论】:

          【解决方案5】:

          阅读 documentation 的 JQuery 映射,特别是它讨论回调的部分。

          在 JavaScript 中,可以使用任意数量的参数调用函数,无论它是如何定义的。所以在jquery.map 的定义中,它调用提供的回调 n 次,其中 n 是数组中元素的数量,并且在每次调用中传递两个参数,第一个是 Object 形式的数组元素,第二个是数组中项目的索引,它是一个整数。

          如果您只想从零参数函数生成一个长度为 n 的新数组,您的回调在技术上可以具有零参数。

          【讨论】:

            【解决方案6】:
            var images = jQuery.map((1234567 + '').split(''), function(n) {
              return '<img src="' + n + '.png" />'
            })
            

            你有这段代码:(1234567 + '')。它将数字转换为字符串。然后split('') 将只拆分数组项中的所有数字。为每个项目调用回调函数,n 将获取数组中的每个值。 $.map 的本质是保存在原始数组中的项目之上,无论回调将返回什么。 在这种情况下,您将拥有一个看起来像 ["1","2","3","4","5","6","7"] 的数组。运行地图后,您将获得图像数组

            images=[
                    '<img src="1.png" />',
                    '<img src="2.png" />',
                    '<img src="3.png" />',
                    '<img src="4.png" />',
                    '<img src="5.png" />',
                    '<img src="6.png" />',
                    '<img src="7.png" />'
                ]
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-01-11
              • 2021-05-09
              • 2017-06-30
              • 1970-01-01
              • 1970-01-01
              • 2020-10-18
              相关资源
              最近更新 更多