资讯专栏INFORMATION COLUMN

JavaScript闭包和this绑定

Airy / 2529人阅读

摘要:首先来讲讲阮一峰的文章中的两道思考题。环境记录包含包含了函数内部声明的局部变量和参数变量,外部引用指向了外部函数对象的上下文执行场景。

本文最主要讲讲JavaScript闭包和this绑定相关的我的小发现,鉴于这方面的基础知识已经有很多很好的文章讲过了,所以基本的就不讲了,推荐看看酷壳上的理解Javascript的闭包和阮一峰的学习Javascript闭包(Closure),写的都非常好。

首先来讲讲阮一峰的文章中的两道思考题。

代码片段一

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

这段代码最后输出的是

The Window

原因在同一片文章的评论中已经有人指出了

  

George Wing 说:

上面本人说得不太正确。
this的指向是由它所在函数调用的上下文决定的,而不是由它所在函数定义的上下文决定的。

对于最后返回的这个匿名函数

function(){
    return this.name;
};

它是作为一个独立的函数返回的,它的调用域是在全局上,所以会输出全局变量name。

代码片段二

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

代码片段二最后输出的是

My Object

这里就要考虑var that = this;这句的作用了,由于getNameFuncobject内部的函数,所以它调用的上下文this保存的是object的信息,将其保存到that变量,这样作为内部函数的匿名函数就可以直接访问了。

可以注意到的是,阮一峰文章中的代码,都是将通过一个JSON对象来访问内部的函数,这样其实有些地方还不够清晰,毕竟不怎么严格地说,闭包就是函数内部的函数,所以我借用CoolShell上的文章中的例子来进一步说明。

代码片段三

function greeting(name) {
    var text = "Hello " + name; // local variable
    // 每次调用时,产生闭包,并返回内部函数对象给调用者
    return function() { alert(text); }
}
var sayHello=greeting("Closure");
sayHello()  // 通过闭包访问到了局部变量text

这段代码输出

Hello Closure

看上去好像很好理解,接下来看代码片段四:

代码片段四

var text = "findingsea";
function greeting(name) {
    var text = "Hello " + name; // local variable
    // 每次调用时,产生闭包,并返回内部函数对象给调用者
    return function() { alert(this.text); }
}
var sayHello=greeting("Closure");
sayHello()  // 通过闭包访问到了局部变量text

这段代码输出

findingsea

这是为什么呢?

针对代码片段三,CoolShell上的原文有解释:

  

文法环境中用于解析函数执行过程使用到的变量标识符。我们可以将文法环境想象成一个对象,该对象包含了两个重要组件,环境记录(Enviroment Recode),和外部引用(指针)。环境记录包含包含了函数内部声明的局部变量和参数变量,外部引用指向了外部函数对象的上下文执行场景。全局的上下文场景中此引用值为NULL。这样的数据结构就构成了一个单向的链表,每个引用都指向外层的上下文场景。

针对代码片段四,就是我们之前讲过的,this保存是调用环境下的上下文内容,所以会输出全局的text

总结

本文想说明的是以下两点:

在函数闭包中,不使用this对变量进行访问时,函数会通过文法环境中的外部引用(指针),一级级地往上找(单向链表),直到找到(或者最终找不到)对应的变量。这个结构是在函数定义的时候就决定了的。

在函数闭包中,使用this对变量进行访问时,和绝大多数语言不同,JavaScript的this保存的是调用环境的上下文,也就是说this中的内容是在调用的时候决定的,所以访问到的是当前环境下的对应变量,并不会像前一种情况一样进行逐级查找。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87555.html

相关文章

  • 十分钟快速了解《你不知道的 JavaScript》(上卷)

    摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...

    赵春朋 评论0 收藏0
  • JavaScript学习之路 — 函数、闭包与原型链

    摘要:全局的函数第个对象第个对象作为构造器进行调用也就是利用运算符进行调用。与操作的共同使用只有通过操作产生的对象,可以使用构造器函数原型链上的内容,否则对象只能使用自己原型链上的内容。 今天这个话题是因为这几天看了《JavaScript忍者秘籍》,感觉这本书把这几个内容讲的蛮透彻了,特撰本文,以便日后翻阅。(应该都会以知识点的形式给出吧。) 函数 1.【基本类型】 JavaScript中函...

    klivitamJ 评论0 收藏0
  • javascript 语言学习

    摘要:被调用的函数一定是在当前函数体内被调用的。所以,当前函数并没有暂停,只是交出了控制权而已。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。 函数 调用一个函数会暂停当前函数的执行,传递控制权和参数给新调用的函数,除了声明时传递的形式参数外,每个函数还会接受两个附加的参数: this和arguement. 其实在读到这句话的的时候,我产生了两个莫名其妙的疑问1.调用一个函数...

    wenyiweb 评论0 收藏0
  • javascript中关于作用域闭包

    摘要:在代码执行时,对应的作用域链常常是保持静态的。当语句执行完毕后,会把作用域链恢复到原始状态。在全局作用域中创建的函数,其作用域链会自动成为全局作用域中的一员。 列表项目 前言 学习了javascript已经很久了,关于这个语言中的这两个特性也是早已耳熟能详,但是在实际的使用的过程中或者是遇到相关的问题的时候,还是不能很好的解决。因此我觉得很有必要深入的学习并且记录这个问题,以便在今后的...

    zacklee 评论0 收藏0
  • js 闭包的使用技巧

    摘要:闭包的学术定义先来参考下各大权威对闭包的学术定义百科闭包,又称词法闭包或函数闭包,是引用了自由变量的函数。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 前言 上一章讲解了闭包的底层实现细节,我想大家对闭包的概念应该也有了个大概印象,但是真要用简短的几句话来说清楚,这还真不是件容易的事。这里我们就来总结提炼下闭包的概念,以应付那些非专人士的心血来潮。 闭包的学术...

    dendoink 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<