对于JavaScript中原型链深入理解

深入解析JavaScript作为基于原型的面向对象语言的特点,包括构造函数、prototype、__proto__属性及其与Object、Function对象的关系,以及如何理解每个函数对象都有一个prototype属性指向原型对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  首先,JavaScript被称为“入门容易精通难”的一门语言。对于学习JavaScript并使用开发并不困难。但JavaScript作为一门面向对象的语言,它又与Java之类的有所区别。Java是一门class-based language(基于类的面向对象语言),JavaScript是一门prototype-based language(基于原型的面向对象语言)。而prototype-based相对于class-based更为抽象,class-based简洁明了,类和对象。类为模版,生成对象。Prototype-based则没有类这么一说,在很多书籍中,为了方便读者理解,通常把JavaScript中的构造函数用来模拟一个类。但易于理解的同时,也会带来更多的疑惑。我也是如此。

prototype-based(基于原型)又是什么呢一般在学习JavaScript过程中,为了让初学者便于理解,有那么一句总结的话:“在JavaScript中,所有都是对象,函数也是对象。顶层有ObjectFunction两个对象”。那么,它们之间有什么关系呢?

先来说说new的含义,假如有那么一个构造函数叫Person,当new一个对象时,例如:

<span style="white-space:pre">	</span>var p = new Person(); 
那么总结就是做了那么一件事,Person函数中的prototype给新生成的对象p__proto__。每个函数对象都有一个属性叫prototype,它指向另一个对象,也就是说,如果以这个函数作为构造函数来new一个对象,那么这个构造函数中的prototype指向的对象就是新生成对象的原型。而__proto__为每个对象都拥有的属性(:对象,包括函数对象).

JavaScript中,ObjectFunction都既是对象也是函数,如何理解呢?首先,你可以写这么一些代码:

 <span style="white-space:pre">	</span>var obj = {}; 
<span style="white-space:pre">	</span>alert(obj.constructor);
如果你用chromefirefox打开,你会得到这样的提示: function Object() { [native code] }, 首先解释一下,native code意思是底层代码,一般情况下c/c++完成的内容,我们不管。obj.constructor表示这个对象所对应的构造函数。我们创建的是一个空object对象,得到的constructorObject()。应该没有疑问吧好,我们继续。再写这样的代码
<span style="white-space:pre">	</span>var hello = function(){ }; 
<span style="white-space:pre">	</span>alert(hello.constructor);
得到结果为: function Function() {[ native code]}, 发现问题了吗?其实这两次我们得到的Object()Function(),其实就是我们之前说的那两个顶层对象(目前暂且认为顶层,后面会补充)。那么,前面提到了,每个函数对象都有一个prototype属性,指向原型对象。那么Function()Object()这两个函数中,必须有那么一个属性,那么我们称它们为Function.prototypeObject.prototype再来写这么写代码
<span style="white-space:pre">	</span>alert(Function.constructor);
<span style="white-space:pre">	</span>alert(Object.constructor); 
得到结果为同样的: Function() {[ native code]},这是什么意思呢刚刚我们说的两个顶层对象的构造函数,都为Function,那也就是说,ObjectFunction都由Function构造出来的,而一般最有疑惑的就是FunctionFunction构造出来。为什么呢?其实很简单,可以这么理解:既然Function是一个native函数,那我们就认为它可以帮我们生成所有的对象,但每个对象类型,属性不一样,怎么标识呢?很简单,之前说的prototype派上用场了,就是它。 

如果觉得抽象,请看图:


    我们所说的FunctionObject,其实都是引用名称。堆空间的Function就是生成对象的核心。再来看看,黄色的箭头表示Function引用和堆空间的Function()函数的关系,Function函数中prototype, __proto__Function.prototypeObject.prototype的关系。红表示ObjectFunction()函数关系.

    可以认为,Object.prototypeFunction.prototype中的一个小零件,如果包含Object.prototype,它就是一个对象。而若包含Function.prototype则可以认为它就是一个函数.重点先看Function(native code),通过上文,我们都知道所有对象都由它生成,那么之前所说的Function对象,我们可以这么认为,它是通过这个Function(native code),把其中的prototype指向Function.prototype,或者说,把Function.prototype组装到Function(native code)函数的prototype属性中,然后__proto__指向Function.prototype。经过这么一折腾,所得到的东西,我们不给它新名字,还叫Function(native code),但与组装之前的已经不一样.我们用这个组装完成后的新Function,进行new Function(),那么得到的这个对象,我们就把它赋值给Function引用。同理,通过原先的Function(native code),对里面的prototype__proto__进行组装,我们也可以得到另一个新的Function,但为了区别,我们改名叫Object(native code),这就是我在上文中(本文第四段),提到的function Function() { [native code] },function Object() { [native code] }

    最后,说到这里,其实之前所说的顶层对象FunctionObject,其实指的就是通过图中Function(native code)所生成的两个对象,说其为顶层对象其实并不是百分百准确,因为它们上面依然存在Object.prototypeFunction.prototype这两个最原始的对象,它们才是顶级。但对于我们开发来讲,可以认为FunctionObject这两个对象是顶层,因为我们生成对象,与之直接打交道的,就是ObjectFunction,而不是Object.prototypeFunction.prototype

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值