js函数中的函数问题?

function test(){
    var arr = [];
    for(var i = 0; i < 5; i++){
        arr[i] = function a() {
            return i;
        }
        a();
    }
    return arr;
}
test();//a is not defined
function c(){
    function d(){
        console.log('2');
    }
    d();
}
c(); //2  

为什么第一个是undefined呢,不是明明定义了a吗在之前?

阅读 4.3k
8 个回答

函数表达式的函数名字只属于它自己的作用域


以你第二段代码为样本改成函数表达式:

function c(){
    var test = function d(){
        console.log('2');
    }
    test();
}
c(); //2

上面这样是没有问题的,但是改成这样:

function c(){
    var test = function d(){
        console.log('2');
    }
    d();
}
c();  //Uncaught ReferenceError: d is not defined

引用错误ReferenceError
作用域中查找标识符但是最后没有找到的时候就会抛出这个错误。
也就是说当前作用域中压根就没有以d作为标识符的变量(函数)。
(顺带一提,如果在这里找到了d标识符,但是它不是函数无法运行,会抛出TypeError类型错误。)

那么,标识符d到底在哪个作用域?
答案是它自己:

function c(){
    var test = function d(){
        console.log(d);
    }
    test();
}
c();

这里最后会把函数d打印出来,在函数d内部是可以使用d标识符的。

arr[i]=function a(){
  return i;
}
a();

这里你想错了,它并没有定义一个名叫a的对象,这里的函数定义式是字面量定义,并非函数声明,这个arr[i]=function a(){中的a可以省略,表示的是arr[i]这个函数的name,也就是arr[i].name是字符串"a".

function a(){
  return i;
}

这个function前面没有东西的才是函数声明式写法,它会定义一个函数对象a。
function前面有东西的时候是字面量写法,此时a只是一个名字,不定义变量。

var b = function a(){
  return i;
}
// 这里只有b变量可以用,未定义a,a可以省略,b.name==="a"

我们平时声明函数就是这样:

var a = function(){}  //后面的是匿名函数,赋给a
function a(){}   //带名字的函数

那如果这样呢:

var a = function b(){}
a //b(){}
b //b is not defined(…)

再来看看:

var a = function b(){var i = 1;console.log(b===arguments.callee)}
a() // true
b() // b is not defined(…)

所以,带名字的匿名函数,名字只能在内部作用域使用,不能在外部调用,充当arguments.callee的角色,并且只读。不能在内部调用,否则会栈溢出。

如果要实现你的代码:

function test(){
    var arr = [];
    for(var i = 0; i < 5; i++){
        arr[i] = function() {
            console.log(i);
        }
        arr[i]();
    }
    return arr;
}
test();  //依次打印出i

实际上,你那个a定义了和没定义没什么区别的,请参照我的做法:

function test(){
  var arr = [];
  function a(n){
    return n; 
  } 
  for(var i = 0; i < 5; i++){
    arr[i] = a(i);
  } 
  return arr; 
} 
alert(test());

function a(){};
这是一个函数声明,相当于var a = function(){};
arr[i] = function a(){};
(function a(){})这是一个函数表达式,赋值的是arr[i],执行到这里才解析。

arr[i]=function a(){
    return i;
}

这里你是在给arr[i]赋值,它的值是一个函数,函数的名字是a,而不是声明和定义函数a的意思,如果在arr[i]后面console.log(arr[i]),你会发现有五个a函数。

var func=function theFunc(){
...
}

只是一个变量定义并初始化语句,可以理解为系统创建一个函数对象theFunc,将其值赋给func后立即销毁。这种效果与赋值未命名函数这种直接量是一样的,只是有一个临时对象名。

var a; //这叫声明了a,把a换成一个函数,也叫声明,声明了就可以用了。
var a = 3; //当变量是左值的时候,这叫定义了a。
var b = a; //当变量是右值的时候,这叫用a进行赋值,完全不表示后面就可以使用a了。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题