js对象探究(1)

llyy112233 2010-11-26 12:45:09
js对象,越玩越有味道,呵呵,下面总结一些知识,供大家参考。

一、js对象起源
首先申明,这里讨论的对象不包括BOM对象(即浏览器对象window、BOM等),只谈论javascript语言本身的对象Object。

先来看一个现象:


    alert(Object instanceof Object); //true 

alert(Function instanceof Object); //true

alert(Object instanceof Function); //true

alert(Function instanceof Function); //true



由此我们可以知道:

1、对象是对象的实例
2、函数是对象的实例
3、对象是函数的实例
4、函数是函数的实例

呵呵,看到这里是不是晕了,别急,我们慢慢来分析。大家都知道js是基于对象(而不是基于类)和基于原型(protoytpe)的语言,每个函数对象都有一个prototype属性,接下来请看第二个现象:

alert(Object.prototype); //[object Object]
alert(Object.prototype instanceof Object); //false



上面第一句说明Object.prototype是个对象,第二句又说明它不是个对象,这不是自相矛盾了吗?那么这里Object.prototype到底是什么呢?

Object.prototype是所有js对象的源头,在ECMAScript语言规范中是这样写的:

The initial value of Object.prototype is the Object prototype object.

This property has the attributes { DontEnum, DontDelete, ReadOnly }.

The value of the internal [[Prototype]] property of the Object prototype object is null and the value of the internal [[Class]] property is “Object”.

Object.prototype的初始值是the Object prototype object.

它包含一些属性,这些属性是不可枚举、不可删除、只读的。(这些属性以后介绍)

Object prototype object的prototype是null,别的函数对象的prototype是一个Object。

由此我们可知Object.prototype是js原型链的顶层了,这还可从下面例子中得证(SpiderMonkey是firefox等一些浏览器的js引擎,它为我们提供了一个prototype的私有属性__proto__,下面的例子测试这个属性,所以请在以SpiderMonkey为js引擎的浏览器中测试,推荐firefox),先介绍下__proto__是指向父对象的prototype.

  function F1(){};
F1.prototype = {
print : function(){
alert("F1.prototype");
}
}
var F2 = new F1();
F2.__proto__.print(); //输出F1.prototype
alert(Object.prototype.__proto__); //输出null




上面的第一个输出说明了__proto__确实指向了父对象的prototype,第二个输出说明Object.prototype没有父对象了,至此我们找到了js原型链的源头,也是js对象的源头。接下来分析Function与Object的关系就比较简单了。

二、Function与Object的关系
首先我们可以把对象分为两类:函数对象(构造器对象)、普通对象。

函数对象包括Function本身,包括Object、String、Number、Boolean,还包括我们定义的函数;

普通对象是除了函数对象外的其他对象如var o = {'attr' : 'test'} , o就是一个普通对象。

要特别强调的是所有的对象(包括函数对象和普通对象),都是由函数对象创建(new)出来的。

创建对象的格式就是

也许有人会问:像上面的o对象就不是由函数对象new的呀? 我们可以看下来这个例子:
  

   var o = {};

alert(o.constructor instanceof Function); //true

alert(typeof o.constructor); //function


上面的例子说明o的构造器(创建出o的)是个函数,其实var o = {'attr' : 'test'}和var o = new Object({'attr' : 'test'})是完全一样的,前面一种写法只是后面写法的简写罢了。看下面的例子:


      var o = new Object({'a' : 'test'});
var oo = {'a' : 'test'};
alert(o.a);
alert(oo.a);
alert(oo.toString() === o.toString()); //true



接下来讲下对instanceof方法的理解。首先要强调一点,只有函数对象才有prototype属性,普通对象如果没有特别定义的话是没有prototype的。例子如下:

    var f = function(){} ;

var o = {};

alert(f.prototype); //[object Object]

alert(o.prototype); //undefined


o.prototype = {};

alert(o.prototype); //[object Object]


instanceof用法: o1 instanceof o2 返回值 true/false,这里我想强调的是o1可以是任何对象,但是o2只能是函数对象,即使是有定义了prototype属性的普通对象也不行,例子如下:


     var f = function(){} ;

var o = {};

o.prototype = {};


alert(o instanceof f); //false

alert(f instanceof o); //浏览器报错


instanceof判断机制,如果o2是o1构造出来的(即 o1 = new o2()),那么毫无疑问,放回true;

当o2不是o1构造出来的时候,是否全部放回false呢? 不是的,请看下面的例子(请在firefox中测试,理由同上,用到了__proto__属性):


    var f1 = function(){};

var f2 = function(){};

f2.prototype = new f1(1);

var o1 = new f2();


alert(o1 instanceof f2); //true
alert(o1 instanceof f1); //true
alert(o1 instanceof Object); //true

alert(f2.prototype.__proto__ === f1.prototype); //true
alert(f2.prototype.__proto__.__proto__ === Object.prototype); //true
alert(f1.prototype.__proto__ === Object.prototype); //true



上面全部返回true,即使o1不是f1构造出来的,但是o1 instanceof f1仍然是返回true,最后三行恰好解释了原因,f2.prototype.__proto__指向了f1.prototype,最终指向了Object.prototype。这就很好的解释了为什么js是基于原型链的语言,这也是js实现原型继承的基础。



至此,我们就可以总结一下Function与Object的关系了:


1、所有的Object的实例都是由Function构造出来的,包括Object和Function本身。

2、对象分为两种类型:函数对象和普通对象,Function和Object都是函数对象。

这就是本文开头第一个例子的原因。

哇,终于写完了,第一次写这么长的技术帖,希望对大家有所帮助,有错误在所难免,欢迎大家指正。这周末再总结一些js的对象的一些知识贴上来。下面是一些参考文章的链接,有兴趣的可以去看看。

http://helephant.com/2009/01/javascript-object-prototype/

http://hi.baidu.com/lansesansan/blog/item/43aa41c0d8aa5c170ff47766.html

http://www.jb51.net/article/21804.htm

http://www.cnblogs.com/siemon/archive/2009/08/11/1537095.html

最后祝大家早安哈!!
...全文
284 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dywane 2010-11-27
  • 打赏
  • 举报
回复
哦呵呵~ 了解一点
llyy112233 2010-11-26
  • 打赏
  • 举报
回复
沙发不留,哈哈,睡觉去咯。
  • 打赏
  • 举报
回复
好,应该还有系列吧
llyy112233 2010-11-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 theforever 的回复:]
好,应该还有系列吧
[/Quote]

嗯,打算总结对js对象比较混淆的地方做一些总结,只有把这些东东都弄懂了,去看一些js框架的源码,才不会觉得无从下手。
llyy112233 2010-11-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 xzgyb 的回复:]
分析的很精彩,多谢。

关于FF下的这个__proto__私有属性, 请参见

<<JavaScript: The Definitive Guide, 5th Edition>>
9.2 Prototypes and Inheritance

After creating the empty object, new sets the prototype of that object.……
[/Quote]

呵呵,__proto__可以帮助弄清楚原型链的来龙去脉
llyy112233 2010-11-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 falizixun2 的回复:]
专业词语的解释我不知道是否完全正确,但是写得不错,简单明了,不过FF下的这个__proto__私有属性,它到底有何实际意义呢??楼主是否分析过这个问题?
[/Quote]

呵呵,一些词语是根据自己的理解写的,有错的地方请大家指出,知识总是越辨越明。__proto__这个属性在确实没什么实际应用,但是这个属性可以帮助我们更好的理解js的原型链,以及对象prototype的指向。
十一文 2010-11-26
  • 打赏
  • 举报
回复
zzh24401 2010-11-26
  • 打赏
  • 举报
回复
给个传送门给大家
http://blog.csdn.net/llyy112233/archive/2010/11/26/6036268.aspx
licip 2010-11-26
  • 打赏
  • 举报
回复
总结得不错,不错。
leehuat 2010-11-26
  • 打赏
  • 举报
回复

对js Prototype分析很好
适合我新手。
感谢楼主
hemen1218 2010-11-26
  • 打赏
  • 举报
回复
学习,能帮助我这新手!
xzgyb 2010-11-26
  • 打赏
  • 举报
回复
分析的很精彩,多谢。

关于FF下的这个__proto__私有属性, 请参见

<<JavaScript: The Definitive Guide, 5th Edition>>
9.2 Prototypes and Inheritance

After creating the empty object, new sets the prototype of that object. The prototype of an object is the value of the prototype property of its constructor function.

而用FF的__proto__,可以证明这一点
porschev 2010-11-26
  • 打赏
  • 举报
回复
看看、。。。
jiashu912387 2010-11-26
  • 打赏
  • 举报
回复
帮你顶下吧。。总结得不错
kaifadi 2010-11-26
  • 打赏
  • 举报
回复
专业词语的解释我不知道是否完全正确,但是写得不错,简单明了,不过FF下的这个__proto__私有属性,它到底有何实际意义呢??楼主是否分析过这个问题?
探究JavaScript原型数据共享与方法共享实现   数据共享  需要共享的数据就可以写原型中  原型的作用之一:数据共享  属性需要共享,方法也需要共享:   不需要共享的数据写在构造函数中 需要共享的数据写在原型中   下面我们看一个案例  数据共享案例  每个学生的名字,年龄,性别都是独特的,我们要设置  所有学生的身高都是188,所有人的体重都是55 所有学生都要每天写500行代码 所有学生每天都要吃一个10斤的西瓜  就可以把共有数据写到原型中           内容概要:本文介绍了浅拷贝和深拷贝的概念、区别以及各自的实现方式,特别是在 JavaScript 中的具体运用。浅拷贝仅拷贝第一层级的对象并共用内部层次的引用,而深拷贝则将所有层次的内容都完整地复制下来。通过示例代码展示了使用 Object.assign 方法实现浅拷贝,以及自定义递归函数 deepClone 来完成深层嵌套对象结构的深度复制。 适合人群:对于有 JavaScript 编程经验的人士非常有益,尤其是那些正在深入研究对象克隆机制或者参与相关项目开发者。 使用场景及目标:①需要在程序执行期间创建独立的对象副本但不想要原始对象受到影响;②希望通过理解两者的本质来更好地优化应用程序性能;③掌握不同情况下的最佳实践。 阅读建议:本文不仅解释了概念层面的知识点,同时也提供了具体实现的例子,在实际操作中可以通过实验验证所学内容,加深理解和记忆。此外还应注意区分不同环境下的拷贝行为(如 V8 引擎)可能带来的细微差别。

87,997

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧