调用 Javascript 函数的混淆

Confusion of calling a Javascript function

有人可以解释为什么 "myPet = pet(Vivie);" 实际上没有调用 pet 函数,但 myPet() 调用了吗?它与我学习的编程语言不同 Java。谢谢

var pet = function(name) {                
  var getName = function() {    
    return console.log(name);               
  } 
  return getName;                   
},

myPet = pet("Vivie"); // ????????
myPet(); // Returns "Vivie"

pet() returns 函数并将其分配给 myPet。如果你想调用 pet() returns 的函数你也可以这样做: pet('Vivie')();

pet() returns 函数并将其分配给您的变量 myPet。所以 Mypet() 实际上调用了函数。如果你想调用 pet() returns 的函数,你也可以这样做:pet("some name")();

您可以尝试编辑以下示例以更好地理解:

如果您注释掉 myPet = pet("Tushar"); 代码将不会 运行 因为 mypet() 尚未分配任何内容。试试吧。

var pet = function(name) {                
  alert(name);                   
},

myPet = pet("Tushar"); 
myPet(); 

如果你将控制台中的代码一一执行,你可能会得到答案。

myPet = pet("Vivie");

上面这行是给 myPet 分配一个函数,它有一个 body 像下面这样

function () {    
    return console.log(name); 
  }

此处 name 的值来自 pet 函数的闭包。

当您调用 myPet 时,它使用 name as Vivie.

调用该函数

所以如果你担心你的函数 pet 没有调用方法,那是因为在 pet 函数中 no-where 函数被调用了。它只是返回函数定义本身。

如果你想要pet函数打印结果,像下面这样定义它

var pet = function(name) {                
  var getName = function() {    
    return console.log(name);               
  } 
  return getName();                   
}

通过这条线myPet = pet("Vivie"); 您正在为 var myPet 分配一个函数和一个参数。所以 myPet 将成为另一个功能

var getName = function() {    
 console.log(name);               
  } 

因此你必须调用 myPet();作为获取 return 的函数。

这就是js函数和可变函数的区别,下面是对这些很好的解释

JS Functions Vs Variable Functions

您可以通过修改您的代码直接调用此函数:

    var pet = function(name) {                

    return console.log(name);               

};

pet("test1"); 

调用 pet 时所做的是 return 函数,并在函数范围变量 name 上设置字符串 "Vivie"。因此,您的 myPet 变量接收 getName 值,该函数打印函数作用域名称变量的值。 当您调用 myPet 时,您已经在调用由 pet 编辑的函数 return,它是 getName 打印具有预设值 "Vivie" 的名称变量].

希望这有助于清除它。 :)

javascript中函数被视为数据。所以你被允许使用函数作为变量。

在下一行中,

myPet = pet("Vivie");

你实际做的是调用 pet 函数,包装 returned 函数并将其放入 myPet.

但是当你编写代码时,

myPet();

您正在调用 myPet() 函数[来自 pet 的 returned 函数。这就是您将宠物分配给它后得到的确切 myPet。

这就是当您编写代码 myPet(); 时调用函数的原因。

现在有一件有趣的事,

当你编码时,

var pet = function(name) {                
  return console.log(name);                 
},

myPet = pet("Vivie");

有效!!!!为什么它起作用了???

在这里,当您调用 pet 函数时,它会控制您的名字并 returns 控制台。它没有 return 任何功能。

但是在 myPet 的代码中,您得到了一个函数。

让我们测试一下我们从 pet,

中看到 returned 对象的类型

你的情况:

var pet = function(name) {                
  var getName = function() {    
    return console.log(name);               
  } 
  return getName;                   
}

var myPet = pet("Vivie");
console.log(typeof myPet); // consoles : function.

您正在调用 pet,但您并未在 returned 函数中执行任何操作。相反,你是说你可以使用 myPet.

执行这个 returned 函数

另一种情况:

var pet = function(name) {                
  return console.log(name);                 
}

var myPet = pet("Vivie");  // consoles : Vivie
console.log(typeof myPet); // consoles : undefined

首先你正在执行 pet 和 return 控制台,这就是为什么当你请求 typeof myPet 时你没有得到任何定义的类型。

最后,如果您想立即调用 returned 函数,那么您应该以这种方式使用自调用函数。

myPet = pet("Vivie")();

故事的寓意:

myPet = pet("Vivie");

这里我的宠物指的是宠物。并且

myPet();

此处 myPet 调用 pet.

参考资料: typeof

为什么您认为 myPet = pet("Vivie"); 不调用 pet 函数? pet 显然被调用并且 returns 分配给 myPet 的新函数。

现在回到您的代码。

myPet = pet("Vivie"); // ????????

嗯,它不会打印任何东西。它只是 returns 另一个功能。这称为 currying。您可以了解有关柯里化的更多信息 here

myPet(); // Returns "Vivie"

之所以returns"Vivie"是因为pet形成了一个闭包并且返回的getName 函数在其范围内。因此 getName 可以看到并捕获 pet 的参数值(在本例中为 "Vivie")并保留它。 myPet() 所做的实际上是调用 getName 的定义。您可以了解有关闭包的更多信息 here

如果您使用的语言不支持 第一个 class 函数,那么当您遇到支持的语言时可能会感到困惑。 第一个 class 函数 是一个可以传递给函数或从函数 returned 的函数,就好像它是普通数据,如字符串或数字.下面的代码应该能说明一些问题:

var pet = function(name) {   // assign anonymous func to pet               
  var getName = function() { // assign nested anonymous func to getName
    console.log(name);       // prints to console; no return value               
  };
  return getName;            // return getName value: func definition   
};

myPet = pet("Vivie");        // assign getName value to myPet 
myPet();                     // appending () invokes defined func

"Vivie" 被传递给 pet 持有的函数,但 console.log() 打印它!这是通过称为 闭包 的功能实现的。由于 name 存在于嵌套函数的直接外部环境中,变量绑定到它并继续存在,甚至 外部函数(包含在 pet 中)执行之后。

关于console.log(),请注意,将其写为 return 语句的一部分是不正确的,因为日志记录方法从来没有 return 值;它只是打印到控制台。所以用下面的代码:

var pet = function(name) {                
  var getName = function() {    
    return console.log(name);               
  } 
  return getName;                   
},

myPet = pet("Vivie"); 
console.log(typeof myPet());  

在最后一条语句中,myPet() 执行导致 "Vivie" 打印到控制台,但它 returns nothing。因此,typeof returns "undefined" 和该结果也被打印到控制台。参见 http://jsfiddle.net/yu75k5tz/

回到传递函数的主题,再次考虑前面的代码片段。使用函数调用链,还有一种更经济的替代方法,如下所示:

pet("Vivie")();

第一组括号调用 pet,它 return 是一个函数,尽管是匿名的。第二对括号导致 returned 函数执行。此代码消除了将 getName 分配给变量的麻烦,这反过来又将两个语句减少到这一行。

最后,函数定义的结尾分号可能看起来很奇怪,但它们在语法上是正确的。每个匿名函数都被分配给一个变量,所以这些分号中的每一个实际上都终止了一个赋值语句。

现场演示:http://jsfiddle.net/kLghedp3/8/