本地属性与继承属性
对象通过隐式Prototype链能够实现属性和方法的继承,但prototype(隐式的)也是一个普通对象,就是说它是一个普通的实例化的对象,而不是纯粹抽象的数据结构描述。所以就有了这个本地属性与继承属性的问题。//自己定义的属性和继承过来的属性
首先看一下设置对象属性时的处理过程。JS定义了一组attribute,用来描述对象的属性property,以表明属性property是否可以在JavaScript代码中设值、被for in枚举等。
obj.propName=value的赋值语句处理步骤如下:
1. 如果propName的attribute设置为不能设值,则返回
2. 如果obj.propName不存在,则为obj创建一个属性,名称为propName
3. 将obj.propName的值设为value
可以看到,设值过程并不会考虑Prototype链,道理很明显,obj的内部[[Prototype]]是一个实例化的对象,它不仅仅向obj共享属性,还可能向其它对象共享属性,修改它可能影响其它对象。
用上面CF, Cfp的示例来说明,实例对象cf1具有本地属性q1, q2以及继承属性CFP1,如果执行cf1.CFP1="",那么cf1就具有本地属性CFP1了,测试结果如下:
//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var cf1=new CF("aaa", "bbb");
var cf2=new CF(111, 222);
document.write(cf1.CFP1 + "<br />"); //result: CFP1 in Cfp
document.write(cf2.CFP1 + "<br />"); //result: CFP1 in Cfp
//it will result in a local property in cf1
cf1.CFP1="new value for cf1";//给sf1赋了个本地对象cfp1,在使用cf1.CFP1的时候就优先寻找这个cfp1
//changes on CF.prototype.CFP1 will affect cf2 but not cf1, because there's already a local property with
//the name CFP1 in cf1, but no such one in cf2
CF.prototype.CFP1="new value for Cfp";
document.write(cf1.CFP1 + "<br />"); //result: new value for cf1
document.write(cf2.CFP1 + "<br />"); //result: new value for Cfp
语义上的混乱?
还是使用上面CF, Cfp示例的场景。
根据Prototype的机制,我们可以说对象cf1, cf2等都继承了对象Cfp的属性和方法,所以应该说他们之间存在继承关系。属性的继承/共享是沿着隐式Prototype链作用的,所以继承关系也应当理解为沿着这个链。
我们再看instanceOf操作,只有cf1 instanceOf CF才成立,我们说cf1是CF的实例对象,CF充当了类的角色,而不会说cf1是Cfp的实例对象,这样我们应当说cf1继承自CF? 但CF充当的只是一个第三方工厂的角色,它跟cf1之间并没有属性继承这个关系。
把CF, Cfp看作一个整体来理解也同样牵强。
//在类的实例被创建时,实例存有一个隐式的prototype,这个隐式的prototype存有对原型(是一个实例)的应用,这个应用在实例被创建时就被赋给这个隐式的prototype,所有的实例都有其隐式的prototype,也就是
//有一个原型(都是一个实例,来自实例的模板,即定义它的类).
//如果很多个类的现式的prototype(用于在实例化类时给实例的隐式prototype赋值,即他的所有实例的隐式prototype)都是同一个实例的话,那么在这些类的实例访问属性和方法时,如果自己的类定义里面没有的话, //就会去自己的隐式的prototype所指向的"父类"(也是一个实例)里去找,如果有就能取到(这个取是只读的),所有的这些类的实例看起来就像共享了"父类"的属性和方法,且很巧合地都是只读的(和java等其他面向对象 //语言一样),这个原型(prototype)起了关键作用
Prototype就是Prototype,没有必要强把JavaScript与面向对象概念结合起来, JavaScript只具备有限的面向对象能力,从另外的角度我们可以把它看成函数语言、动态语言,所以它是吸收了多种语言特性的精简版。
对象模型(看不太明白,迷糊..暂时跳过看后面,js这潭水太深...)
Where are we?
1. 了解了JavaScript的数据类型,清楚了象Number这样的系统内置对象具有多重身份: a)它们本身是一个函数对象,只是由引擎内部实现而已,b)它们代表一种数据类型,我们可以用它们定义、操作相应类型的数据,c)在它们背后隐藏了引擎的内部实现机制,例如内部的数据结构、各种被包装成了JavaScript对象的构造器等。
2. 了解了Prototype机制,知道对象是如何通过它们继承属性和方法,知道了在创建对象过程中JS引擎内部是如何设置Prototype关系的。
接下来对用户自定义函数对象本身的创建过程进行了解之后,我们就可以对JavaScript的对象模型来一个整体性的overview了。
函数对象创建过程
JavaScript代码中定义函数,或者调用Function创建函数时,最终都会以类似这样的形式调用Function函数:var newFun=Function(funArgs, funBody); 。创建函数对象的主要步骤如下:
1. 创建一个build-in object对象fn
2. 将fn的内部[[Prototype]]设为Function.prototype
3. 设置内部的[[Call]]属性,它是内部实现的一个方法,处理逻辑参考对象创建过程的步骤3
4. 设置内部的[[Construct]]属性,它是内部实现的一个方法,处理逻辑参考对象创建过程的步骤1,2,3,4
5. 设置fn.length为funArgs.length,如果函数没有参数,则将fn.length设置为0
6. 使用new Object()同样的逻辑创建一个Object对象fnProto
7. 将fnProto.constructor设为fn
8. 将fn.prototype设为fnProto
9. 返回fn
步骤1跟步骤6的区别为,步骤1只是创建内部用来实现Object对象的数据结构(build-in object structure),并完成内部必要的初始化工作,但它的[[Prototype]]、[[Call]]、[[Construct]]等属性应当为null或者内部初始化值,即我们可以理解为不指向任何对象(对[[Prototype]]这样的属性而言),或者不包含任何处理(对[[Call]]、[[Construct]]这样的方法而言)。步骤6则将按照前面描述的对象创建过程创建一个新的对象,它的[[Prototype]]等被设置了。
从上面的处理步骤可以了解,任何时候我们定义一个函数,它的prototype是一个Object实例,这样默认情况下我们创建自定义函数的实例对象时,它们的Prototype链将指向Object.prototype。
另外,Function一个特殊的地方,是它的[[Call]]和[[Construct]]处理逻辑一样。
JavaScript对象模型
红色虚线表示隐式Prototype链。
这张对象模型图中包含了太多东西,不少地方需要仔细体会,可以写些测试代码进行验证。彻底理解了这张图,对JavaScript语言的了解也就差不多了。下面是一些补充说明:
1. 图中有好几个地方提到build-in Function constructor,这是同一个对象,可以测试验证:
//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
Function==Function.constructor //result: true
Function==Function.prototype.constructor //result: true
Function==Object.constructor //result: true
//Function also equals to Number.constructor, String.constructor, Array.constructor, RegExp.constructor, etc.
function fn(){}
Function==fn.constructor //result: true
这说明了几个问题: Function指向系统内置的函数构造器(build-in Function constructor);Function具有自举性;系统中所有函数都是由Function构造。
2. 左下角的obj1, obj2...objn范指用类似这样的代码创建的对象: function fn1(){}; var obj1=new fn1();
这些对象没有本地constructor方法,但它们将从Prototype链上得到一个继承的constructor方法,即fn.prototype.constructor,从函数对象的构造过程可以知道,它就是fn本身了。
右下角的obj1, obj2...objn范指用类似这样的代码创建的对象: var obj1=new Object();或var obj1={};或var obj1=new Number(123);或obj1=/\w+/;等等。所以这些对象Prototype链的指向、从Prototype链继承而来的constructor的值(指它们的constructor是build-in Number constructor还是build-in Object constructor等)等依赖于具体的对象类型。另外注意的是,var obj=new Object(123);这样创建的对象,它的类型仍然是Number,即同样需要根据参数值的类型来确定。
同样它们也没有本地constructor,而是从Prototype链上获得继承的constructor方法,即build-in *** constructor,具体是哪一个由数据类型确定。
3. 关于图中Prototype链的补充说明:
Object.prototype是整个链的终结点,它的内部[[Prototype]]为null。
所有函数的Prototype链都指向Function.prototype。
Function的Prototype链指向Function.prototype,这是规范要求的,因为设计者将Function设计为具有自举性。Function的Prototype链这样设计之后,Function.constructor==Function, Function instanceOf Function都为true。另外Function已经是最顶层的构造器,但Function本身也是一个函数对象,它必然是由某个东西创建出来的,这样自举在语义上合情合理。
Function.prototype的Prototype链指向Object.prototype,这也是规范强制要求的。首先Function.prototype是Function的一个实例对象(typeof Function.prototype可以知道它是一个Function,instanceOf无法通过测试,因为Prototype链在内部被额外设置了),所以按照Prototype的规则,Function.prototype的内部[[Prototype]]值应当为Function.prototype这个对象,即它的Prototype链指向自己本身。这样一方面在Prototype链上造成一个死循环,另一方面它本身成为了一个终结点,结果就是所有函数对象将不是派生自Object了。加上这个强制要求之后,Prototype链只有唯一的一个终结点。
4. 因为Function.prototype是一个函数对象,所以它应当具有显示的prototype属性,即Function.prototype.prototype,但只有FireFox中可以访问到,IE、Opera、Safari都无法访问。所以图中用了个表示不存在的符号。
5. 用户自定义函数(user defined functions)默认情况下[[Prototype]]值是Object.prototype,即它的隐式Prototype链指向Object.prototype,所以图中就这样表示了,但并不代表总是这样,当用户设置了自定义函数的prototype属性之后,情况就不同了。
分享到:
相关推荐
以上是JavaScript学习笔记中提到的一些核心知识点,通过对这些知识点的理解和熟练应用,可以为进一步学习和掌握JavaScript打下坚实的基础。在实际开发过程中,结合具体的项目需求,这些知识会得到更深入的拓展和应用...
- **DOM (Document Object Model)**: 描述了文档对象模型的接口,允许程序和脚本动态地访问和更新文档的内容、结构和样式。 - **BOM (Browser Object Model)**: 提供了一组与浏览器交互的对象,如window、navigator...
2. **函数与对象**:JavaScript中的函数是第一类对象,可以作为变量赋值、作为参数传递或作为返回值。对象是属性和方法的集合,包括字面量语法和构造函数创建。笔记可能详细解析了原型链、闭包、作用域等概念。 3. ...
本学习笔记专为初学者设计,旨在帮助新接触JavaScript的人快速掌握这门语言的核心概念和实用技巧。 首先,"JavaScript特效.chm"可能是一份关于JavaScript实现的各种网页特效的教程。这些特效可能包括图片轮播、下拉...
### JavaScript核心笔记精要 #### 一、定义变量与类型转换 **1.1 定义变量的方法** 在JavaScript中,定义变量有两种方法:显示定义和隐式定义。 - **显示定义**: 使用`var`关键字定义变量。这种方法直到变量首次...
### JavaScript权威指南学习笔记二:客户端JavaScript #### 第十二章:Web浏览器中的JavaScript ##### 一、Web浏览器环境 在客户端JavaScript中,浏览器提供了一个特定的执行环境,其中`window`对象扮演着至关...
JavaScript可以用来动态地修改文档对象模型(DOM),从而改变网页的内容或布局。 **示例6:** ```html ('Down!')">Click ('Click!')">Click ``` - **解释:** 第一个链接在鼠标按下的时候会在页面上输出`Down!`;第二...
最后,`GridPanel`对象被创建,指定了渲染目标、数据源、列模型、选择模型等属性。 ### 总结 Extjs的Tab Panel和Grid组件提供了丰富的特性和自定义选项,使得开发者能够构建出既美观又功能强大的用户界面。通过...
- JavaScript可以操作DOM(文档对象模型),实现对网页元素的增删改查,如`getElementById`、`appendChild`等。 以上就是JavaScript学习笔记中的主要知识点,理解和掌握这些内容对于深入学习JavaScript至关重要。...
【狂神说系列 JavaScript笔记】是一份全面且深入的JavaScript学习资源,旨在帮助开发者和初学者深入理解这门广泛应用于Web开发的脚本语言。这份笔记涵盖了JavaScript的基础语法、核心概念以及高级特性,旨在构建一个...
### JavaScript DOM 编程艺术读书笔记关键知识点解析 #### 一、JavaScript简史与相关技术简介 - **XHTML(可扩展的超文本标记语言)**:这是一种更加严格、更加强大的HTML版本,旨在提高网页的可读性和可扩展性。 ...
2. **BOM(Browser Object Model)**:浏览器对象模型,提供了与浏览器窗口交互的方法和属性。 3. **DOM(Document Object Model)**:文档对象模型,允许JavaScript操作HTML文档结构。 #### 四、基本语法 ##### 1...
DOM(文档对象模型)是JavaScript操作网页内容的主要接口。学会选择元素(如getElementById、querySelector、querySelectorAll等)、修改元素属性、插入和删除节点,是进行网页动态更新的基础。 异步编程是...
【压缩包子文件的文件名称列表】: "第三阶段笔记" 没有给出具体的文件详细信息,但可以推测这可能包含一系列按主题或模块划分的笔记文档,如HTML、CSS、JavaScript的基础知识,数据库管理,面向对象设计原则,类和...
JavaScript基础知识点 JavaScript是一种脚本语言...本笔记涵盖了JavaScript的基础知识点,包括变量、数据类型、流程控制语句、函数、数组、对象、JSON、BOM和Location等概念,为学习JavaScript提供了一个良好的基础。
【标题】"yolo开发t-JavaWeb-m笔记"揭示了这是一个关于快速开发JavaWeb项目的实践笔记。在JavaWeb开发中,"yolo"(You Only Live Once)常常被用来象征快速行动、勇于尝试的精神,而"t-JavaWeb-m"可能是项目代号或者...
在开发过程中,笔记可能记录了如何将这些机器学习模型与前端Bootstrap界面整合,比如创建图表来展示模型的预测结果,或者利用Bootstrap的表单组件来输入和处理数据。这涉及到前后端交互,可能使用了Ajax异步请求,...
总的来说,这份笔记将引导学习者了解Bootstrap的基础知识,包括栅格系统、组件使用、样式定制和JavaScript插件的应用。通过学习和实践,无论是新手还是有经验的开发者,都能快速上手并提升网页开发效率。
**文档对象模型(Document Object Model, DOM)**是HTML或XML文档的标准模型,它提供了对文档结构的访问和修改的方式。 1. **DOM树的概念**: - HTML文档被解析成一个节点树,每个节点代表文档中的一个元素。 - ...
在Web开发中,JavaScript常用于操作文档对象模型(DOM),通过DOM可以改变HTML元素的样式、内容或位置。熟悉DOM API,如getElementById、appendChild等,是前端开发的基本技能。 四、事件处理 JavaScript通过事件...