JavaScript原型和原型链的终极详解
JavaScript原型和原型链的终极解释。
1.普通对象和功能对象。
在JavaScript中一切都是对象!但是对象也不一样。分为普通对象和函数对象。对象和函数是JS自带的函数对象。例子如下。
函数f1(){ };var F2=function(){ };var f3=新函数(' str ',' console . log(str)');var o3=新f1();var O1={ };var o2=新对象();控制台日志(对象类型);//functionconsole.log(函数的类型);//functionconsole.log(类型为O1);//object console . log(O2的类型);//对象console.log(类型为O3);//objectconsole.log(类型为f1);//functionconsole.log(类型为F2);//functionconsole.log(类型为F3);//函数在上例中,o1 o2 o3是公共对象,f1 f2 f3是函数对象。如何区分其实很简单。新Function()创建的所有对象都是函数对象,其他都是普通对象。归根结底,f1和F2都是由新的Function()创建的。函数对象也通过新函数()创建。
二.原型对象。
在JavaScript中,只要定义了一个对象(函数),该对象就包含一些预定义的属性。函数对象的属性之一是原型对象原型。注意:普通对象没有原型,但是有_ _ prototype _ _属性。
原型对象实际上是一个普通的对象(除了Function.prototype,它是一个函数对象,但是它非常特殊,它没有原型属性(如前所述,所有的函数对象都有原型属性))。请看下面的例子:
函数f1(){ };console.log(f1。原型)//f1 {}console.log(类型为f1。原型)//Objectconsole.log(函数的类型。prototype)//Function console . log(object . prototype的类型)//object console . log(Function . prototype . prototype的类型)//undefined From console . log的输出(f1。prototype)//f1 {},我们可以看到f1.prototype是f1的一个实例对象。创建f1时,会创建一个实例对象并将其分配给原型。基本流程如下:
var temp=new f1();f1。原型=温度;因此,函数的原因。原型是一个很容易解决的功能对象。上面改进了新Function()生成的所有对象都是函数对象,所以temp是函数对象。
变量温度=新函数();功能。原型=温度;原型对象用于什么?主要用于继承。举个例子:
var person=function(name){ this . name=name };person . prototype . getname=function(){ return this . name;}var zjh=新人('张家豪');zjh . getname();//张家豪从这个例子中,我们可以看到,通过将一个函数对象属性设置为person.prototype,带有person实例的普通对象(例如:zjh)继承了这个属性。如何实现继承,我们要讲下面的原型链。
三.原型链
当JS创建一个对象(无论是普通对象还是函数对象)时,它都有一个名为__proto__的内置属性,用来指向创建它的函数对象的原型对象原型。以上面的例子为例:
console.log(zjh。_ _ proto _ _===person . prototype)//true
同样,person.prototype对象也有一个_ _ prototype _ _属性,它指向创建它的函数对象的原型。
console . log(person . prototype . _ _ proto _ _===object . prototype)//true
继续,Object.prototype对象也有一个_ _ prototype _ _属性,但它是特殊的空属性。
控制台.日志(对象.原型. __原型_ _)//空
我们称这个链为__proto__串在一起,直到Object.prototype.__proto__作为原型链为空。下图:
四.内存结构图。
为了更深入更直观地理解,下面我们来画一下上面的内存结构图:
绘图惯例:
疑问的解释:
1 . object . _ _ proto _ _===function . prototype//true
对象是一个函数对象,由新的function()创建,所以对象。__proto__指向函数。原型。
2 .函数. _ _ proto _ _===function . prototype//true
函数也是一个对象函数,也是由新的函数()创建的,所以函数。__proto__指向函数。原型.
我自己创造了自己,这似乎不合逻辑,但仔细想想,现实世界中也有一些相似之处。你是怎么来的,你妈妈是怎么出生的,你妈妈是怎么来的,你奶奶是怎么出生的,类人猿进化了,类人猿是从哪里来的,它们被追溯到哪里.也就是没什么。
正如《道德经》所言,“没有什么是成名的开始”。
3 . function . prototype . _ _ proto _ _===object . prototype//true
其实这个我有点疑惑,不过也可以试着解释一下。
函数原型是一个函数对象。理论上,他的_ _ prototype _ _应该指向Function.prototype,也就是指着自己的自己,是没有意义的。
JS总是强调一切都是对象,函数对象也是对象。给他一个祖先,指向对象。原型。对象。原型。_ _ proto _ _==null,确保原型链可以正常结束。
动词(verb的缩写)。构造器
原型对象原型中有一个预定义的构造函数属性,用于引用其函数对象。这是一个循环引用。
person . prototype . constructor===person//true function . prototype . constructor===function//true object . prototype . constructor===object//true改进上面的内存结构图:
有两点需要注意:
1.注意Object.constructor===Function==函数;//true本身,对象由Function函数构造。2.如何找到对象的构造函数,就是找到对象原型链中第一个构造函数属性所指向的对象。
不及物动词摘要
1.原型和原型链是JS继承的模型。
2.原型链实际上是由__proto__而不是原型构成的。
要深入理解这句话,我们再举一个例子,看看你之前是否真的理解。
var animal=function(){ };var dog=function(){ };动物.价格=2000;//dog.prototype=动物;var tidy=new dog();console . log(dog . price)//未定义console.log (tidy.price)//2000为什么?画一张记忆地图:
这是什么意思?执行dog.price时,发现没有价格属性。虽然原型所指的动物具有这种属性,但它并没有沿着这条“链条”去寻找。同样,当执行tidy.price时,没有这样的属性,但是__proto__指向animal,它会沿着这个链寻找它。动物有价格属性,所以要整齐。价格输出2000。所以原型链是由__proro__真正形成的,而不是原型。
因此,如果狗。_ _ proto _ _=动物是这样指定的。那么狗。价格=2000。
!-[如果!support list]-1。
!-[endif]-最后,一个比喻不太准确,但可能有助于理解原型。
父亲(功能对象),老师生了一个大儿子(原型),也就是你大哥,而他父亲给你大哥买了很多玩具。你出生时,你们之间的家庭纽带(_ _ prototype _ _)自然会让你拥有大哥的玩具。同样,你也教了你的大儿子,给他买了很多玩具。当你再生你的儿子时,你的小儿子自然会拥有你大儿子的所有玩具。至于他们会不会打,不关我们的事。
于是,你从大哥那里继承了下来,印证了“大哥如父”这句话。
版权声明:JavaScript原型和原型链的终极详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。