javascript - window.a和一个在window环境中的a不一样吗
PHPz
PHPz 2017-04-10 17:53:37
[JavaScript讨论组]
    var a = 2;
    var func = (function(){
        var a = 3;
        return function(){
            a++;
            alert(a);
        }
    })();
    console.log(func);
    func();
    func();

返回结果:4,5
但是最后第二行执行func()时,所在this指针为window,本以为是指的外面的a=2,实际上指的是内部的a=3

    var a = 2;
    var func = (function(){
        var a = 3;
        return function(){
            this.a++;
            alert(a);
        }
    })();
    console.log(func);
    func();
    func();

返回结果3,4

不是很能理解这种行为,window.a和一个在window环境中的a不一样吗

    var name = "this window";
    var object = {
        name:"my object",
        getNameFunc:function(){
            console.log(this);
            return function(){
                return name;
            }
        }
    };
    alert(object.getNameFunc()());

这时返回的就是"this window" ,内部函数也能找到name变量,但是却用了外部的name,
所以比较困惑,这是什么原因造成的呢

PHPz
PHPz

学习是最好的投资!

全部回复(9)
阿神

首先指出题目的第2段代码输出为3,3

var a = 2;//[1]
var func = (function(){
    var a = 3;//[2]
    return function(){
        a++;
        console.log(a);
    }
})();
console.log(func);
func();
func();

输出 4,5

func是一个闭包函数,函数体内的变量a绑定到的[2]处的变量

var a = 2;//[1]
var func = (function(){
    var a = 3;//[2]
    return function(){
        this.a++;//[3]
        console.log(a);//[4]
    }
})();
console.log(func);
func();
func();

输出 3,3
func是一个闭包函数,函数体内的变量a([4])绑定到的[2]处的变量
this.a中的this依你的func的不同的调用方式的不同而不同,a的值也会不同
在目前的func();这种调用方式,this指向的时window对象(nodejs下为global)
所以每次调用++后,修改的都是[1]处变量的值,不会影响到[2]处的值,
故输出3,3

var name = "this window";//[1]
var object = {
    name:"my object",
    getNameFunc:function(){
        console.log(this);
        return function(){
            return name;
        }
    }
};
console.log(object.getNameFunc()());

在object定义的时候getNameFunc属性对应的函数对象的返回函数是一个闭包函数,其变量name绑定到[1]处的变量(当前函数体找不到这个变量声明,就到向外层函数中寻找,一直到全局,如果还没未找到,就保错ReferenceError;如果找到,就绑定所在位置的变量)

大家讲道理

这两个例子中a的指向不一样。第一个例子中的a指的是func这个外部函数中的a = 3,第二个例子中this.a指的是window.a = 2。如果把第一个例子改成这样:

var a = 2;
var func = (function(){
    var b = 3;
    return function(){
        a++;
        alert(a);
    }
})();
console.log(func);
func();
func();

结果就是3,4。这是因为执行a++的时候,在外部函数func中找不到a,于是找到了全局中的a,这时alert的就是全局中的a了。


第三个例子,你仔细想想getNameFunc()()是在什么环境中执行的。如果return name那个闭包在getNameFunc函数内部执行了,它的name就会找object里的name。但事实上,getNameFunc()()是在全局作用域中执行的,它会在全局中找name。这就是我们常说的,在全局中调用闭包,闭包内的this指向window的缘故。

下面这道思考题,你看看结果是什么。

var name = "this window";
var object = {
    name:"my object",
    getNameFunc:function(){
        console.log(this);
        var that = this;
        return function(){
            return that.name;
        }
    }
};
alert(object.getNameFunc()());

一般使用这种方式来返回闭包外部函数中的变量。

天蓬老师

先看这一段

var a = 2;
console.log(a);     // 2
console.log(window.a);     // 2

说明 window 上下文的 a 就是 window.a

然而下面这段代码的输出不应该是 3, 4,应该是 3, 3,因为你加的是 windows.a,弹出的是函数里面定义的 var a = 3,值是没变的,你可以把这个值改成 var a = 30,这样就更容易区分。

var a = 2;
var func = (function(){
    var a = 3;
    return function(){
        this.a++;
        alert(a);
    }
})();
console.log(func);
func();
func();

javascript 会找最近作用域的变量,所以看哪个定义得最近(window.a 这种显示指定的不属于这种情况)

怪我咯

题主的疑惑在于把两个不同的问题搞混了。这两个问题是:

  1. 函数中this的指向问题

  2. 函数中变量(标识符)如何确定的问题

这两个问题正是函数执行时最重要的两个问题。但它们又是两个独立的、没有关系的问题。

前者(即this是谁)是由函数被调用方式确定的,在函数定义时无法确定。

后者(即某个局部变量是指谁)是由函数所处的词法环境决定的,在函数定义时就能确定,与函数怎么被调用无关!说白了就是由函数间的嵌套关系决定的,只要你代码写完了,就确定了。

所以,很明显,题主觉得“this是什么”会影响“变量a是谁”是不正确的。

至于这两个问题的详细解决方法,相关文章和问题太多了,就不多说了。我这个回答的目的,就是告诉题主关键的一点:不要把这两个独立无关联的问题混为一谈。

巴扎黑

作用域的问题,当前作用域有a,就用自己的,没有就会向更高一级作用域查找,直到window作用域 作用域的冒泡,可以参考《你不知道的javascript》

PHP中文网

首先第二段代码的返回值应该是3,3,实际上你应该是想写alert(this.a)。

其实两段代码的区别就在this上,需要理解的是this到底指向谁。通常this可以这么理解,this指向调用它的对象。

而第二段代码之所以会出现理解误差,是因为当直接调用function的时候,this默认指向全局对象,这个其实是javascript当初设计的时候的一个问题。

天蓬老师

后面function的作用于是在window下,返回的是window.name,所以输出的是外部的name

PHPz

这是this指向以及作用于链的问题,在第一个函数中函数内部定义了a,这个a=3,你这个局部变量a相当于window.func下面的变量a;所以两次闭包函数执行了3++ 以及4++.
而第二个函数中关于this指向在直接调用函数this是指向window的,所以第二个函数的this.a相当于window.a这个变量;this.a++与下面的alert(a)是两个不同的变量,所以这个执行函数时是3和4

PHPz

大部分的语言,在你未指明变量所属作用域时会默认你指的是最近一个作用域内的变量,

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号