这段代码为什么输出的是 1 2 3

    var foo = {n:1};
    (function (foo) {
        console.log(foo.n);
        foo.n=3;
        var foo = {n:2};
        console.log(foo.n);
    })(foo);
    console.log(foo.n); 
阅读 4.2k
6 个回答

这段代码解析的重点在于foo.n=3和var foo = {n:2};。

var foo = {n:1};
(function (foo) {
    console.log(foo.n);**此处访问的是全局变量**
    foo.n=3;**相当于修改了全局变量的初始值**
    var foo = {n:2};**在自执行函数中定义了个局部变量**
    console.log(foo.n);**先找自己的作用域中是否存在foo.n存在的话打印出来**
})(foo);
 console.log(foo.n); 
你的代码在js中是如下编译的(建议看下**你不知的JavaScript上卷,保证你对js作用域会豁然开朗**):
var foo = {n:1};
(function (foo) {
    var foo;
    console.log(foo.n);
    foo = {n:2};
    console.log(foo.n);
})(foo);
foo.n=3;
console.log(foo.n); 

你这个问题,可以引申为 js 中的经典问题,就是按值传递 还是按引用传递

你这个问题呢:
首先 foo指向一个对象,是堆中对象的一个引用,当作为参数传递时,又创建了一个对堆中对象的一个引用 ,这里就叫做foo1方便描述,与foo指向的是同一个对象,就好比 var a = {x:1},b = a; 这时候如果修改foo1上的值就是修改堆中的对象的值,所有foo也会改变。接下来 var foo = {n:2},相当于新创建一个对象,与之前的引用断开了,所以不会影响之前的对象

图片描述

提供一点建议就是你在浏览器中执行的的时候可以看控制台的console输出,点击VM607:3或者什么的就能看函数的执行顺序,这样也能加速你的理解。

因为就是按这个顺序执行的啊。建议你把疑问说的更具体一些。
第一句log输出时,foo是函数的参数,指向第一行那个foo。
后面修改了foo的属性n,也就是外面的foo.n
第二句log输出前修改函数内的局部变量foo,指向一个新对象。所以输出是新foo的n,为2。
第三句输出函数外面的foo,n值为函数内修改的值3。

把函数内部的变量名换一下,题主就可以理解了。
把内部的foo改成a,代码等价。

    var foo = {n:1};
    (function (a) {
        console.log(a.n);
        a.n=3;
        var a= {n:2};
        console.log(a.n);
    })(foo);
    console.log(foo.n); 
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题