Javascript闭包
介绍:
闭包:一个闭包是可以在该函数环境中绑定变量和共享变量的表达式(一种特殊的function).闭包是javascript的最强大的特性之一,但是不理解就没法使用。然而,闭包是相对简单编写的,但是编写可能极具潜在的问题,特别是在一些常用的web浏览器。为了避免各浏览器的残缺和利用其优势,就有必要了解其机制了。这很大程度上取决于域链(作用域链)在标识符的解析处理方案和对象的属性名的解析处理方案中扮演的角色。
最简单的闭包就是js的functon(体)的内部function:把Function定义和function表达式放入function体中,并且这些内部function是允许访问(function体)所有的局部变量,参数和声明的其他内部函数。
当一个内部function去访问其所在function体之外的function时,闭包就形成了。因此它会在外部的function执行后执行。Function体内的变量,参数都可以被这些内部function所访问和修改,所以这是值得注意的。
不幸的是:正确理解闭包需要理解他们背后的运行机制和一些技术细节。虽然一些ECMA 262的算法已被抛弃,但是不能省略,如果属性的人,可以跳过这部分。
对象的属性解析方案:
ECMAScript识别两类对象目录:本地对象和内建对象:就是本地对象的一个子目录。本地对象属于语言,主机对象是环境提供的,也许是,比如:document对象,DOM节点之类的。
本地对象是离散和动态的属性表()。这定义命名成对象的属性将赋予一个值,这可能是一个到其他对象的引用或者一个原始的值:String, Number, Boolean, Null or Undefined。未定义的原始类型可能有点古怪:它可能被undefined值标示,类似于对象的一个属性,它并没有删除任何对象属性。它包含一个undefined命名的属性,它只有值:undefined.
接下来是如何为对象的属性设置值和取值的简述:
赋值操作:
对象的属性可以被创建,或给已有属性赋值:
Var objectRef = new Object();//create a generic javascript object
//testNumber属性的创建:
objectRef.testNumber = 5;
//或者
objectRef[“testNumber”] = 5;
对象没有某属性时,会创建属性并赋值。如果有了属性,则只赋值,不需要创建属性了。
Javascript的对象有原型也是对象,也可被简单的描述。原型也许有命名的属性,但是没有被标示。如果这个值被标示,那实际上对象没有一个这名字的属性创建和赋值,如果它有这个属性,就会被重设值。所以:对象的原型是不能为对象创建属性并赋值的。
读取属性值:
从对象来读取属性值是由对象原型来完成的。如果对象有个命名的属性,那么用属性运算符就额可以访问该属性,并返回属性值:
objectRef.testNumber = 8;
//read the value back from the property
Var val = objectRef.testNumber;
但是所有的对象都有原型,并且原型也是对象,反过来,也许有原型,也有其原型等等就会造成所谓的原型链(prototype chain)。原型链终结于原型链中的某个对象是空原型。Object对象的默认的原型就有个null原型。
var objectRef = new Object();//create a generic js object
用Object的原型创建一个对象:对象就有了一个null原型。因此,objectRef的原型链只有一个对象:Object.prototype.然而:
<script type="text/javascript">
function MyObject1(formalParameter){
this.testNumber = formalParameter;
}
function MyObject2(formalParameter){
this.testString = formalParameter;
}
MyObject2.prototype = new MyObject1( 8 );
var objectRef = new MyObject2( "String_Value" );
</script>
MyObject2实例提供了objectRef变量的原型链。原型链的第一个对象是:MyObject1实例(已被创建和标示为MyObject2对象的原型)。MyObject1有一个原型,这个对象被标示为MyObject1的原型属性。这个对象也有原型,就是Object对象默认的原型,可以通过Object.prototype的简称来通信。Object.prototype有个null原型,因此这个原型链在这个点终结。
当尝试去访问一个命名的属性时,整个原型链会参与到访问过程。如:
var val = objectRef.testString;//String_Value
实例MyObject2为objectRef提供一个属性:“testString”,因此就是这个属性的值,设为”String_Value”,也被标示为值。然而:
原型链(prototype chain)
objectRef.prototype-> (MyObject2.prototype) -> MyObject1.prototype->Object.prototype
Var val = objectRef.testNumber;
不能从MyObject2实例读取这个名字的属性。因为他没有这样的属性。而MyObject2的原型:MyObject1实例已被创建并创建属性:testNumber,并且赋值8;因此属性运算符返回值8.
还有MyObject1和MyObject2都没有一个toString()方法,如果尝试从objectRef去访问去获取值:
var val = objectRef.toString;
那么val变量被标示为一个function的引用。这个function是Object.prototype的一个属性并且返回值。
最后:
var val = objectRef.madeUpProperty;
如果这么做,遍历了所有的原型都没有找到这个属性或者方法,那么就返回undefined
了。
读属性值会返回第一个找到的值,在对象找或者原型链。对象的属性在被赋值时,如果没有该属性就赋值,否则会创建。原型链类似于java 的类基础。
每个对象都有自己的原型链,返回自己的原型链的值。如果通过原型链去找属性值,那么返回的是就近的属性值。
标识符解析,执行上下文和作用域链
执行上下文:是个抽血概念,用于ECMA 262的定义来描述ECMA要求的实现方式。这个定义没有说任何关于执行上下文是如何实现的,但是执行上下文有关联属性来提供定义结构,因此他们可能被接受为objects和属性,虽然没有公共属性。
所有的js代码被执行在一个执行上下文,全局代码开始执行是在全局执行上下文,并且每个函数调用都有一个相关联的执行上下文。Eval函数的执行会获取不同的执行上下文,Eval函数从来不被常规的使用在js编程中,所以也不在这里讨论了。执行上下文的细节会在ECMA 262的10.2节找到。
当一个js函数被调用,js函数就进入了一个执行上下文,如果另一个函数也被调用了,那么一个新的执行上下文会被创建并在这个函数调用期间。当执行结束后,返回原来的执行上下文。所以,js代码的执行形式是一个栈结构。后进先出。
当执行上下文创建了很多东西时,首先,在上下文函数中,”Activation”对象被创建,这个对象是另一个规范机制。可以视为一个对象,但是它没有属性,也不能在js代码里直接引用这个对象。
下一步就是创建一个 arguments 对象,长得像一个数组有整形索引来快速的返回参数,为了序列,它又长度和callee的属性。激活对象的属性被创建并命名为:“arguments”并且提供到每一个对象。
下一步:执行上下文标示一个域:一个包含了很多对象的list,每个对象都有范围内的属性,也包含了一系列的对象。范围是分配给执行上下文的一个函数调用由列表中所提到的【[范围] ]属性对应的函数对象的激活对象添加在前面的链(或列表的顶部)。
相关推荐
在深入讨论JavaScript闭包之前,首先需要了解JavaScript的变量作用域。在JavaScript中,变量的作用域分为两种:全局变量和局部变量。全局变量是在函数外部定义的变量,可以在JavaScript程序的任何地方被访问。局部...
JavaScript 闭包是一种高级编程概念,它在JavaScript中扮演着至关重要的角色,特别是在函数式编程和模块化设计中。闭包本质上是函数和其能够访问...通过学习这些实例,你将能够更好地掌握JavaScript闭包这一核心概念。
通过具体例子来学习闭包是十分有效的。文章中提到了两个例子:第一个例子中,通过一个循环来创建带有闭包的函数数组,但是由于JavaScript变量作用域和循环的作用,所有函数最终都只访问到了循环的最终值。第二个例子...
JavaScript 闭包究竟是什么? 用JavaScript一年多了,闭包总是让人二丈和尚摸不着头脑。陆陆续续接触了一些闭包的知识,也犯过几次因为不理解闭包导致的错误,一年多了资料也看了一些,但还是不是非常明白,最近偶然...
本教程将深入讲解如何使用XMLHTTPRequest来实现自定义的Ajax请求,并探讨JavaScript的闭包模式。 首先,让我们理解XMLHTTPRequest对象的工作原理。它主要有五个状态(0-4),分别代表不同的通信阶段。状态0表示请求...
理解并掌握JavaScript闭包是成为专业前端开发者的关键一步。在实际开发中,合理利用闭包可以提高代码的复用性和可维护性,同时也能避免一些常见的编程陷阱。通过深入学习和实践,可以更好地运用闭包这一强大的工具来...
### JavaScript闭包详解 #### 一、什么是闭包? 闭包是JavaScript中一个重要的概念,它涉及函数如何访问外部作用域中的变量。虽然官方定义较为复杂:“闭包是一个拥有许多变量和绑定了这些变量的环境的表达式...
闭包是JavaScript编程中的一个重要概念,它涉及到函数、作用域、内存管理和变量持久化等多个方面。闭包本质上是一个函数,它能够访问并操作其自身作用域内的变量,即使在函数执行完毕后,这些变量依然保持活性。闭包...
描述:详细描述JavaScript闭包,适合更进一步了解闭包。 标签:javascript 闭包 从给定的文件信息来看,主要围绕JavaScript中的闭包概念进行深入探讨。闭包是计算机科学中一个重要的概念,特别是在函数式编程语言...
JavaScript中的闭包、匿名函数和作用域链是编程中至关重要的概念,它们是理解JavaScript运行机制的关键。在本文中,我们将深入探讨这三个概念,并通过实际示例来展示它们的运用。 首先,我们来讨论“闭包”。闭包是...
JavaScript 闭包是一种高级编程概念,它在JavaScript中扮演着重要的角色,特别是...通过深入学习和实践这些内容,你将能够更好地理解和掌握JavaScript闭包的精髓,并将其应用于实际项目中,提高代码的质量和可维护性。
JavaScript学习(一) JavaScript是一种广泛应用于网页和网络应用的脚本语言,由 Netscape 的 Brendan Eich 在1995年发明。它主要用于客户端的网页交互,赋予网页动态功能,如响应用户操作、处理数据、与服务器通信...
总之,JavaScript的闭包是一种核心概念,理解和掌握闭包对于深入学习JavaScript以及使用jQuery等库进行前端开发至关重要。通过闭包,开发者可以实现更灵活和高效的设计模式,提高代码质量与可维护性。
以下是一些关于JavaScript闭包的关键知识点: 1. **函数嵌套**:闭包最常见的形式是内部函数引用了外部函数的变量。例如: ```javascript function outerFunction() { var outerVar = 'I am from the outer ...
这个“JavaScript帮助学习文档”包含了丰富的资源,旨在帮助初学者和进阶者深入理解和掌握JavaScript的核心概念。 首先,JavaScript的基础知识是至关重要的。这包括变量、数据类型(如字符串、数字、布尔值、数组、...
JavaScript闭包是指有权访问另一个函数作用域中的变量的函数。在初学者接触这个概念时,往往对它的理解和应用感到困难,但其实闭包是JavaScript编程语言中非常重要的一个特性,它是基于词法作用域书写代码时自然产生...
在深入理解JavaScript闭包之前,我们需要明确什么是闭包,以及闭包的重要性。 闭包是JavaScript中一个较为高级的概念,指的是有权访问另一个函数作用域中变量的函数。通俗地讲,JavaScript中的函数都可视为闭包,...