想请教一个JavaScript函数作用域问题

想请教一下下面的代码中,为什么A函数在执行时,我为A重新赋值为1,可是后面的alert(A)弹出的结果任然显示A为function?而如果A=1改为var A=1,就会弹出1。

另外:一般立即执行的函数都是匿名函数吧,这里让一个非匿名函数立即执行有点诡异啊。。呵呵

<script>
(function A(){
    A=1;
    alert(A)  //显示function A(){..}
})()
function B(){
    B=2
    alert(B)  //2
}
B();
B()    //undefined
</script>
阅读 4.5k
6 个回答

第一个问题:

这里涉及到了作用域和作用域链的问题。

第一个函数一创建就会立即执行,分解这个2个过程来看下:

  • 首先是创建过程:

    立即执行的函数A乍看起来是在全局环境(window)下面定义的,实际上是在一个脱离了window的环境下创建的。暂且叫这个环境为env.那么函数A相当于env的一个属性(方法). 这是在函数创建过程中发生的,env属于函数A的[[scope chain]]属性的最底层

  • 执行过程
    函数A会创建一个活动对象(call object)属于[[scope chain]]的最高层.它包含了arguments属性,在这里为[],同时还创建了全局变量A,为window的属性。因此在执行过程中首先会从自身的活动对象查找是否有A属性,明显没有。那么往下一层env中寻找,发现了A属性为function A().window对象不在这个作用域链当中。因此最后会输出function A(){}

你说的另外一种情况:

(function A(){
    var A=1;
    console.log(A);  //输出 1
    }) 

这里由于var A=1;属于定义局部变量,在函数A执行的过程中会给活动对象(call object)附加上属性A,因此console.log(A)获取到的即在活动对象上的属性A=1;所以最后输出1;第二次为什么不能输出暂时没搞明白,明天再想吧。


第二个问题:

这里的B现在不是立即执行的函数,那么作用域链的最底层是window对象,你在函数B中定义的全局变量B是能在window对象上访问的到的。所以第一次执行会输出 2.在B()执行完后,会将这个值类型

先说一下 A=1; B=2;代表的是 全局变量A B分别赋值1 2 ,另外,函数声明表达式,你可以立即在当前作用域定义了对应的一个变量 并赋值一个函数 第一个A,执行一个表达式,作用域是有个作用域链,局部作用域像全局作用域冒泡,直到找到为止,所以,在匿名函数作用域内,所以A指函数,B最开始应该是函数的,然后被你重新赋值了!结果就为你新的赋值 2 !!!

ECMA-262-3 in detail. Chapter 5. Functions 中提到了函数表达式的作用范围

The definition also states that FE is created at the code execution stage and is not stored in the variable object. Let’s see an example of this behavior:

javascript// FE is not available neither before the definition
// (because it is created at code execution phase),

alert(foo); // "foo" is not defined
  
(function foo() {});

// nor after, because it is not in the VO

alert(foo);  // "foo" is not defined

另外在 ECMA-262 的 Runtime Semantics: Evaluation 一节也提到了函数表达式的执行过程。

英文不是很好,所以没有完全找到答案,只能帮你到这里了………

要是我会尽量避免这种搞不清楚的事情

函数表达式中,变量获取的优先级:局部变量>形参>全局变量;这个规律可以很好的解释你上面提到的问题。

楼上都是大虾 。 就说一下战斗力只有5的渣渣的见解

你迷惑不是作用域,而是 有名字的匿名函数 NFE
NFE的特点:

- 你只能内部访问
- 你改不了他名字 除非你定义一个跟他同名的 eg

(function A(){
    A=1;
    //var A = 1;
    //let A = 1;
    alert(A)  //显示function A(){..}
})()
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏