search

Home  >  Q&A  >  body text

javascript - JS中的闭包问题

无意中在网上看到了一段关于闭包的代码:

var name = "The Window";   
var object = {
    name : "My Object",   
    getNameFunc : function(){   
        return function(){   
            return this.name;   
        };   
    },

    getName:function(){
        alert(this.name);
    }   
};   
alert(object.getNameFunc()());  //The Window
object.getName();  //My Object

为什么alert(object.getNameFunc()());会弹出The Window?大大们指点一下迷津,多谢!

感谢各位的回复

PHPzPHPz2894 days ago381

reply all(7)I'll reply

  • PHP中文网

    PHP中文网2017-04-10 14:27:39

    我认为代码写成下面这个形式可能更利于你理解:

    var name = "The Window";
    var object = {
        name : "My Object",
        getNameFunc : function(){
            return (function(){
                 alert(this.name);
            })();
        },
    
        getName:function(){
            alert(this.name);
        }
    };
    object.getNameFunc();  //The Window
    object.getName();  //My Object
    

    函数 getNameFunc 内返回一个闭包,因此 this 指向全局对象,所以 this.name 即为定义在全部作用域下的 name("The Window")
    而函数 getName 内并未返回闭包,因此 this 指向当前对象,所以 this.name 即为当前作用域下的 name("My Object")
    你要明白一点,正是因为闭包的使用,才使得当前作用域可以访问外部的作用域成为可能。
    为了让题主明白,我再举一个 this 不指向全局对象的例子:

    var name = "The Window";
    var object = {
        name : "My Object",
        getNameFunc : function(){
            return (function(){
                 alert(this.name);
            }.bind(this))();
        },
    
        getName:function(){
            alert(this.name);
        }
    };
    object.getNameFunc();  //My Object
    object.getName();  //My Object
    

    这样也可以:

    var name = "The Window";
    var object = {
        name : "My Object",
        getNameFunc : function(){
            return (function(){
                 alert(this.name);
            }.bind(object))();
        },
    
        getName:function(){
            alert(this.name);
        }
    };
    object.getNameFunc();  //My Object
    object.getName();  //My Object
    

    看到了吧,不能说闭包内的 this 就一定是指向全局对象,你要明白我们使用闭包的目的是什么,这里就是为了连接函数内部和外部的作用域,还有一个用处就是保存变量,例如循环中的闭包。
    我之前译过两篇博文,题主可以一读:

    • 《细说 Javascript 函数篇(二) : this 的工作机制》
    • 《细说 Javascript 函数篇(三) : 闭包和引用》

    题主,我刚刚总结了一篇关于闭包的博文,你可以读下:

    《Javascript - 深入闭包机制》

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-10 14:27:39

    getNameFunc 中,this已经不是指向object,而是闭包引用的对象。object.getNameFunc()()没有传递对象到闭包,默认就是window.你可以alert(this),会看到this是window对象,不是Object对象。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 14:27:39

    这么写你就明白了

    var fn = object.getNameFunc();
    fn() // The Window 
    // fn 等价于 window.fn  所以 此时的this 指的是 window
    
    //而 getName 是 object 调用的, this 指的是 object 
    object.getName();  //My Object
    

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 14:27:39

    因为getNameFunc return的那个function,是在对象外创建的,创建时的上下文是window,所以this指向了window,window.name 就是前面那个全局变量

    reply
    0
  • 迷茫

    迷茫2017-04-10 14:27:39

    object.getNameFunc()的返回原地展开就是function(){return this.name;}

    所以 (function(){return this.name;})()执行的时候this是window

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 14:27:39

    将对象的this付给一个变量,比如that,最后return that.name;

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 14:27:39

       // 你可以这样理解
       // 因为它return返回是个函数,我把这个函数赋给fn,fn就是函数名
        var fn=object.getNameFunc();
        fu();其实就是window.fu(),所有返回The Window

    reply
    0
  • Cancelreply