繁体   English   中英

需要解释函数表达式如何作为函数声明中的参数传递

[英]Need an explanation on how a function expression is being passed as an argument in a function declaration

将函数表达式作为参数传递

例:

var greeting = function(first,last) {
return "Hello " + first + last;
};
function greet(frst,lst,word) {
var result = word(frst,lst);
console.log(result);
}
greet("Joe","Bob",greeting);

我知道var greeting被分配了匿名函数,这个函数作为表达式传递。

我理解在全局执行上下文中,变量问候语是留出一些内存空间,而不是它内部的函数。

我知道函数greet,是预留内存空间,当我们调用函数greet时,它为局部变量result创建内存空间。 现在变量结果被分配给word(frst,lst)这是否使它成为一个函数? 意思是word(frst,lst)一个函数表达式?

我不明白的是......

当我们用以下函数调用函数时是怎么回事?

greet("Joe","Bob",greeting);

浏览器能够接受参数“Joe”和“Bob”并将它们放入word(frst,lst)然后使用参数greeting,这是一个运行函数的变量来添加它的两个参数,当参数来自变量和函数greet有不同的名称? 我不明白如何传递参数给我们"Hello Joebob"的结果。

如果我在任何陈述中出错,请纠正我,我非常感谢你的帮助。

请帮忙!!

谢谢!

好吧,我们一个接一个。

1.作为JS中的第一类对象

在JS中,函数被视为第一类对象,这意味着您可以存储,将其作为参数传递,以与您对其他对象或变量相同的方式接收函数参数。

在您的情况下,匿名函数被分配给变量greeting 此函数/函数引用可以作为常规变量传递给任何其他函数。

当您将任何函数传递给另一个函数时,它将通过引用传递,为了执行此操作,您必须使用一对括号greeting(..)来调用它。

2.在函数引用中传递参数

JS函数在调用函数时不执行类型检查或传递给函数的参数数量。 传递的参数在函数定义中作为参数接收时保持相同的顺序。 例如 - function dummy(x, y, x){}如果被调用为dummy(1,2,3)x接收为1y接收为2 ,依此类推。 如果没有传递某些参数,例如dummy(1, 3) ,则JS本身将相应的参数设置为undefined 这些是由JS引擎隐式完成的。

JS函数arguments对象

JavaScript函数有一个名为arguments对象的内置对象。 参数对象包含调用(调用)函数时使用的参数数组。 对于每个函数调用,此对象都使用传递的参数进行设置,并且可以在函数内检索。 例如。

x = findMax(1, 123, 500, 115, 44, 88);

  function findMax() {
    var i;
    var max = -Infinity;
    for (i = 0; i < arguments.length; i++) {
     if (arguments[i] > max) {
        max = arguments[i];
     }
  }
 return max;
}

在上面的例子中,因为findMax参数是dyanmic即。 我们不确定它将调用多少个数字,最好从arguments对象而不是直接函数参数中检索参数。

好读 - http://bonsaiden.github.io/JavaScript-Garden/#function http://bonsaiden.github.io/JavaScript-Garden/#function.arguments

让我们一起完成评估过程:

// Def 1
var greeting = function(first, last) {
  return "Hello " + first + last;
};

// Def 2
function greet(frst, lst, word) {
  var result = word(frst, lst);
  console.log(result);
}

// Call
greet("Joe", "Bob", greeting);

当执行到达(Def 1)时,在全局上下文中评估作为函数表达式的右侧以生成闭包,该数据结构包含指向已编译函数的指针和指向全局上下文的指针(因为这是定义此功能的地方)。 此评估的结果与此顶层中的标识符greeting相关联。

接下来执行到达(Def 2),类似地,创建闭包并将结果存储在greet

有趣的事情始于(电话)。 为了评价greet("Joe", "Bob", greeting) ,编译器增加了对真实在顶层用于与槽最上面的一个的顶部上的新的堆栈帧/激活记录greet的三个形式参数(即frstlst ,和word )及其一个局部变量(即result )。 然后,评估"Joe""Bob"greeting ,并将它们的值分配给这些插槽。 "Joe""Bob"评估这些名称的一些字符串表示,我们从Def 1知道的greeting评估为闭包。 然后在那个堆栈框架中,从我们知道的Def 2开始的greet的评估开始。

  • 首先,现在分配了由greeting命名的闭包的值的word将被应用于frstlst的值,在该堆栈帧中,编译器已经分配了字符串"Joe""Bob"
    • 为了评估greeting的值,编译器创建第一个堆栈帧,其firstlast为其2个形式参数提供两个插槽,分别为这些参数分配"Joe""Bob" ,并开始执行greeting主体。 greeting的主体连接“Joe”和“Bob”并在其前面添加“Hello”,返回字符串“Hello JoeBob”。
  • 接下来,该结果存储在名为result的槽中。
  • 接下来,将分配一个新的堆栈帧来调用内置函数console.log (这个故事与其他调用非常相似,所以我不会详细介绍)。
  • 最后, greetundefined返回到其调用站点,该站点不对该值执行任何操作。 程序然后完成执行。

如果你要逐步分析这个(干运行),那么当你打电话greet("Joe","Bob",greeting);时会发生这种情况greet("Joe","Bob",greeting);

第1步

first| lst | word
================================================
Joe  | Bob  | function(first,last) {
     |      |     return "Hello " + first + last;
     |      |  };

第2步

var result = word(frst,lst);

这里发生的是,在第一步和第一个变量的值中调用变量字在步骤1中引用的函数。

ie. word('Joe', 'Bob');

所以我们得到了这个功能

var greeting = function(first,last) {
   return "Hello " + first + last;
};

first | last | return value = ("Hello " + first + last) | result
================================================================
Joe   | Bob  |  Hello JoeBob                            | Hello JoeBob

所以, console.log(result); = Hello JoeBob

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM