调用 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 分配给变量的麻烦,这反过来又将两个语句减少到这一行。
最后,函数定义的结尾分号可能看起来很奇怪,但它们在语法上是正确的。每个匿名函数都被分配给一个变量,所以这些分号中的每一个实际上都终止了一个赋值语句。
有人可以解释为什么 "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 分配给变量的麻烦,这反过来又将两个语句减少到这一行。
最后,函数定义的结尾分号可能看起来很奇怪,但它们在语法上是正确的。每个匿名函数都被分配给一个变量,所以这些分号中的每一个实际上都终止了一个赋值语句。