js中的原型和原型链
当我们使用构造函数时,每次实例化构造函数的时候,也就是用new改变函数中this的指向时,在函数中我们有一些属性不能够完全使用时,这些不使用的属性也会被创建出来,这样就会在我们的计算机中无形的增加计算机的内存,所以有了我们更加优化的节省计算机内存的方法,也就是原型。
每个函数在创建的时候都会自带一个原型对象。比如:
var Fn = function () { this.age = 18; this.name = "jack"; } Fn.prototype.name = "jim"; Object.prototype.name = "miss"; var f = new Fn(); var f1 = new Fn(); alert(f1.name); alert(f.name);
这个时候f和f1会继承构造函数Fn中prototype属性中的name值;在构造函数中的值也一样。
当我们在构造函数中也添加
this.name="tim";
这个时候我们输出f1.name和f.name我们得到会是tim,这个一结果是根据原型中的原型链而引发而来。说的通俗一点呢也就是我们在查找一个值时,那么这个时候我们就会从原型链的底层开始查找(也就是构造函数的属性中先),当自身不满足时就会沿着原型链往上查找,最终查找不到满足这个条件会得到一个undefined;
解析:
1.大家不明白为什么是将this写作是原型链中的底层,这里解释一下,在我们的原型链中构造函数实例化的对象如果要调用构造函数中的原型会使用 f1.name这样去得到这个值,当我们调用这个被构造函数实例化对象的时,其实这个对象的原型是构造函数的prototype原型属性,而构造函数又是我们原型链中最底层的一个小的原型链,所以称为原型链的底层当自身满足这个条件时就会使用这个值,
下面就说一下原型链;原型链在原型中是很关键的,我们在原型链中的不正确操作会直接影响原型值的获得。
上述例子中的f,f1是被Fn构造函数实例化的对象,我们的对象都有一个原型对象(__proto__),而这个__proto__指向的是创建这个对象的构造函数的原型属性(prototype)
注意下面的介绍,才好看原型链的图
-
constructor是构造函数prototype(原型属性中的属性),他指的是构造函数本身。
-
__proto__指的是对象的原型对象,但是__proto__是一个非标准属性。
-
prototype是构造函数的原型属性;也就是我们常说的原型
-
我们在设置prototype时只能给构造函数设置,对象上是不可以设置的,如果我们想用对象
来获得构造函数中的prototype中的值只能通过非标准属性(__proto__)来获得,但是不建议使用,只建议在测试中使用__proto__属性
这是一个非常复杂的原型链,其中在原型链中最饱受争议的就是Object创建了Function,还是Function创建了Object,我们如果沿着原型链展开Function和Object会发现他们是无群无尽的。
一张完整的原型链图来方便大家理解。
本来打算给大家再添一张原型链的图方便大家理解的,可是添加不上去,如果大家有兴趣的话可以去下面这个网址中浏览
通过以上的介绍我们可以得到以下结论:
-
每个对象有一个constructor属性,指的是这个对象的构造函数。
-
当对象没有constructor这个属性时他通过__proto__来继承构造函数中的constructor的属性。
-
每个函数都有prototype(原型属性);每个对象有一个__proto__(原型对象)
-
函数都继承于Function函数,对象都继承于Object对象,
-
函数Function也是对象Object,Object也有自己的构造函数Function,所以Function和Object是互相创造的,
这在原型中是一个无法解释的特例、就好像先有鸡还是先有蛋。 当然我们查看原型链最好的方法就是在页面中查看,虽然数据比较庞大,稍微懂原型的人还是可以看出来的。下面给大家介绍一下如何在网页中查看原型链,自己平时喜欢用谷歌浏览器,所以给大家介绍一下在谷歌中如何查看原型链,首先在自己的编译器中输入如上面的例子,打开调试工具
点击+然后输入在原型链中的对象,比如f1,Fn得到的就是各自的原型链了