我只是在观看Douglas Crockford的视频,他还做了以下练习:
编写一个函数,当传递一个变量时,返回一个函数 如果被调用,则返回变量的值。
所以我写了以下函数:
function funcky(o) {
return function send(o){ // notice the o in send
return o;
}
}
var x = funcky(3);
console.log(x()); // i get undefined why ??
注意发送中的o
。我已经编写了一段时间的JavaScript,但我仍然不明白为什么我得到未定义?
crockfords解决方案如下:
function funcky(o) {
return function send(){
return o;
}
}
var x = funcky(3);
console.log(x()); // get 3 now .
现在该解决方案如何运作,而我的解决方案是什么?我没有看到我的解决方案有太大的不同,我看到的任何事情都没有明显错误。有人可以解释一下吗?
答案 0 :(得分:4)
o
中的send(o){
是您犯错误的地方。它不是继承'来自原始父级参数的o
。将它置于该函数声明中是在该函数的新范围内创建一个新的o
。
send
在调用时未传递任何内容,并返回其第一个参数,因此返回undefined
。
您的代码,注释:
function funcky(o) {
return function send(o){ // DECLARES NEW VARIABLE, happens to have same name
return o; //returns the first argument passed to send
}
}
var x = funcky(3); //nothing is passed to the inner function send
console.log(x()); // undefined due to lack of arguments
实际发生的事情的一个更清晰的例子:
function funcky(o) {
return function send(someArgument){
return someArgument; //return o; here would find the correct o, the first arg of funcky
}
}
答案 1 :(得分:3)
这与o
的范围有关。当你写:
return function send(o){ // notice the o in send
return o;
}
o
的范围是函数send的本地范围。但是,如果你写:
return function send(){
return o;
}
o的范围不是函数send的本地范围,而是本地范围内的funcky。
所以,当你写function send(o){/*...*/}
时,真正发生的是o
成为一个参数,并且需要像这样调用:funcky()(10)
,但你想要的是什么要做的是funcky(10)()
。
编辑:
有关JavaScript中变量范围的详细信息,请参阅this very detailed answer on SO。
答案 2 :(得分:2)
function funcky(o) {
return function send(o){ // notice the o in send
return o;
}
}
您的内部函数的o
参数会隐藏最初传递给o
的{{1}}。因此,当您编写funcky
时,x只是一个var x = funcky(3);
函数,它需要返回一个参数,在闭包中没有捕获任何内容。
(换句话说,在你的情况下,x没有对原始send
- 3的引用,因为通过名称o它调用x本身被调用的参数。)
答案 3 :(得分:2)
由于范围。
函数send会覆盖其内部范围内的var o。
function funcky(o) {
// o here is whatever you passed in funcky
return function send(o){
// now o here is whatever you pass in send
// since you didn't pass anything the result is undefined
return o;
}
}
检查另一个例子
function funcky(o) {
return function send(a){
console.log(a);
console.log(o); // this o is the parent o
return o;
}
}
var x = funcky(3);
console.log(x());