`
panyi5202
  • 浏览: 56689 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

理解 JavaScript 闭包二

阅读更多
三、值的读取


当读取对象的属性值时,原型对象的作用便体现出来。如果对象的原型中包含属性访问器(property accessor)所使用的属性名,那么该属性的值就会返回:

/* 为命名属性赋值。如果在赋值前对象没有相应的属性,那么赋值后就会得到一个:*/
objectRef.testNumber = 8;

/* 从属性中读取值 */
var val = objectRef.testNumber;

/* 现在, - val - 中保存着刚赋给对象命名属性的值 8*/

而且,由于所有对象都有原型,而原型本身也是对象,所以原型也可能有原型,这样就构成了所谓的原型链。原型链终止于链中原型为 null 的对象。Object 构造函数的默认原型就有一个 null 原型,因此:

var objectRef = new Object(); //创建一个普通的 JavaScript 对象。

创建了一个原型为 Object.prototype 的对象,而该原型自身则拥有一个值为 null 的原型。也就是说, objectRef 的原型链中只包含一个对象-- Object.prototype。但对于下面的代码而言:

/* 创建 - MyObject1 - 类型对象的函数*/
function MyObject1(formalParameter){
/* 给创建的对象添加一个名为 - testNumber - 的属性
并将传递给构造函数的第一个参数指定为该属性的值:*/
this.testNumber = formalParameter;
}
/* 创建 - MyObject2 - 类型对象的函数*/
function MyObject2(formalParameter){
/* 给创建的对象添加一个名为 - testString - 的属性
并将传递给构造函数的第一个参数指定为该属性的值:*/
this.testString = formalParameter;
}

/* 接下来的操作用 MyObject1 类的实例替换了所有与 MyObject2 类的实例相关联的原型。而且,为 MyObject1 构造函数传递了参数 - 8 - ,因而其 - testNumber - 属性被赋予该值:*/
MyObject2.prototype = new MyObject1( 8 );

/* 最后,将一个字符串作为构造函数的第一个参数,创建一个 - MyObject2 - 的实例,并将指向该对象的引用赋给变量 - objectRef - :*/
var objectRef = new MyObject2( “String_Value” );

被变量 objectRef 所引用的 MyObject2 的实例拥有一个原型链。该链中的第一个对象是在创建后被指定给 MyObject2 构造函数的 prototype 属性的 MyObject1 的一个实例。MyObject1 的实例也有一个原型,即与 Object.prototype 所引用的对象对应的默认的 Object 对象的原型。最后, Object.prototype 有一个值为 null 的原型,因此这条原型链到此结束。

当某个属性访问器尝试读取由 objectRef 所引用的对象的属性值时,整个原型链都会被搜索。在下面这种简单的情况下:

var val = objectRef.testString;

因为 objectRef 所引用的 MyObject2 的实例有一个名为“testString”的属性,因此被设置为“String_Value”的该属性的值被赋给了变量 val。但是:

var val = objectRef.testNumber;

则不能从 MyObject2 实例自身中读取到相应的命名属性值,因为该实例没有这个属性。然而,变量 val 的值仍然被设置为 8,而不是未定义--这是因为在该实例中查找相应的命名属性失败后,解释程序会继续检查其原型对象。而该实例的原型对象是 MyObject1 的实例,这个实例有一个名为“testNumber”的属性并且值为 8,所以这个属性访问器最后会取得值 8。而且,虽然 MyObject1 和 MyObject2 都没有定义 toString 方法,但是当属性访问器通过 objectRef 读取 toString 属性的值时:

var val = objectRef.toString;

变量 val 也会被赋予一个函数的引用。这个函数就是在 Object.prototype 的 toString 属性中所保存的函数。之所以会返回这个函数,是因为发生了搜索 objectRef 原型链的过程。当在作为对象的 objectRef 中发现没有“toString”属性存在时,会搜索其原型对象,而当原型对象中不存在该属性时,则会继续搜索原型的原型。而原型链中最终的原型是 Object.prototype,这个对象确实有一个 toString 方法,因此该方法的引用被返回。

最后:

var val = objectRef.madeUpProperty;

返回 undefined,因为在搜索原型链的过程中,直至 Object.prototype 的原型--null,都没有找到任何对象有名为“madeUpPeoperty”的属性,因此最终返回 undefined。

不论是在对象或对象的原型中,读取命名属性值的时候只返回首先找到的属性值。而当为对象的命名属性赋值时,如果对象自身不存在该属性则创建相应的属性。

这意味着,如果执行像 objectRef.testNumber = 3 这样一条赋值语句,那么这个 MyObject2 的实例自身也会创建一个名为“testNumber”的属性,而之后任何读取该命名属性的尝试都将获得相同的新值。这时候,属性访问器不会再进一步搜索原型链,但 MyObject1 实例值为 8 的“testNumber”属性并没有被修改。给 objectRef 对象的赋值只是遮挡了其原型链中相应的属性。

注意:ECMAScript 为 Object 类型定义了一个内部 [[prototype]] 属性。这个属性不能通过脚本直接访问,但在属性访问器解析过程中,则需要用到这个内部 [[prototype]] 属性所引用的对象链--即原型链。可以通过一个公共的 prototype 属性,来对与内部的 [[prototype]] 属性对应的原型对象进行赋值或定义。这两者之间的关系在 ECMA 262(3rd edition)中有详细描述,但超出了本文要讨论的范畴。
分享到:
评论

相关推荐

    JavaScript闭包

    Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态...本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包。

    深入理解javascript原型和闭包

    深入理解javascript原型和闭包(01)——一切都是对象 深入理解javascript原型和闭包(02)——函数和对象的关系

    javascript闭包详解中文word版

    本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAscript语言规范来使读者可以更深入的理解闭包。闭包是Closure, 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    深入理解_JavaScript_闭包

    理解 JavaScript 闭包 要成为高级 JavaScript 程序员,就必须理解闭包

    理解_JavaScript_闭包

    本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从“嵌套的函数”深入到“标识符解析、执行环境和作用域链”等等 JavaScript 对象背后的运行机制当中,真正领会到闭包的实质。

    JavaScript闭包深入理解.pdf

    JavaScript闭包深入理解.pdf

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...

    理解 JavaScript 闭包

    要成为高级 JavaScript 程序员,就必须理解闭包。 本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从“嵌套的函数”深入到“标识符解析、执行环境和作用域链”等等 ...

    深入理解javascript原型和闭包.pdf

    javascript原型和闭包

    JavaScript闭包的定义和理解,含代码示例

    JavaScript闭包的定义和理解,含代码示例

    揭开Javascript闭包的真实面目

    对于初学者来说,理解Javascript闭包(closure)还是比较困难的,而撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目,让初学者理解起来更加容易一些。

    【JavaScript源代码】详解JavaScript闭包问题.docx

    详解JavaScript闭包问题  闭包是纯函数式编程语言的传统特性之一。通过将闭包视为核心语言构件的组成部分,JavaScript语言展示了其与函数式编程语言的紧密联系。由于能够简化复杂的操作,闭包在主流JavaScript库...

    深入理解JavaScript系列

    深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaScript系列(3):全面解析Module模式 深入理解JavaScript系列(4):立即调用的函数表达式 深入理解JavaScript系列(5):强大的原型和原型链 ...

    javascript深入理解js闭包.docx

    javascript深入理解js闭包.docx

    深入理解JavaScript的闭包技术整理.pdf

    深入理解JavaScript的闭包技术整理.pdf

    javaScript闭包的理解

    网上的例子很多,讲解的和理解起来的简易程度不禁相同,整理的例子和吸收的帖子供大家参考

    JavaScript对闭包的理解.md

    为了帮助大家快速和较好地理解JavaScript函数中的闭包,本文对JavaScript的闭包进行了分析并进行简易的代码演示,希望本文能够给有需要的人带来一点小小的帮助。

    深入理解Javascript闭包 新手版

    最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目。

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(16):闭包(Closures) 深入理解JavaScript系列(17):面向对象编程之一般理论 深入理解JavaScript系列(18):面向对象编程之ECMAScript实现 深入理解JavaScript系列(19):求值策略...

Global site tag (gtag.js) - Google Analytics