js中的原型和原型链
当我们使用构造函数时,每次实例化构造函数的时候,也就是用new改变函数的指向时,在函数中我们有一些属性不能够完全使用时,这些不使用的属性也会被创建出来,这样就会在我们的计算机中无形的增加计算机的内存,所以有了我们更加优化的节省计算机内存的方法,也就是原型。
每个函数在创建的时候都会自带一个原型对象。比如:
var Fn = function () {
this.age = 18;
}
Fn.prototype.name = "tom";
var f = new Fn();
var f1 = new Fn();
这个时候f和f1会继承构造函数Fn中prototype属性中的name值;在构造函数中的值也一样。
当我们在构造函数中也添加
this.name="tim";
这个时候我们输出f1.name和f.name我们得到会是tim,这个一结果是根据原型中的原型链而引发而来。说的通俗一点呢也就是我们在查找一个值时,当有多个属性满足我们所需要的条件时,那么这个时候我们就会从原型链的底层开始查找,当自身满足这个条件时就会使用这个值,自身不满足时就会沿着原型链往上查找,当最终查找不到满足这个条件会得到一个undefined;
下面就说一下原型链;原型链在原型中是很关键的,我们在原型链中的不正确操作会直接影响原型值的获得。
前面说了每一个对象在创建时都自带一个属于自己的原型属性,当然函数也是一个对象,
上述例子中的f,f1是被Fn构造函数实例化的对象,我们的对象都有一个原型对象(__proto__),而这个__proto__指向的是创建这个对象的构造函数的原型属性(prototype),在这个原型属性中的prototype中有拥有constructor来指向构造函数,
这个构造函数是被函数Function构造出来,Function中的prototype中有拥有constructor来指向函数Function, Function的原型属性(__proto__)又指向于Object的原型属性(prototype),Object中的prototype中有拥有constructor来指向函数Object,而函数也属于对象所以Object的原型属性(__proto__)也指向于函数,
注意下面的介绍,才好看原型链的图
-
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是互相创造的,
这在原型中是一个无法解释的特例、就好像先有鸡还是先有蛋。
-
当然我们查看原型链最好的方法就是在页面中查看,虽然数据比较庞大,稍微懂原型的人还是可以看出来的。
-
下面给大家介绍一下如何在网页中查看原型链,自己平时喜欢用谷歌浏览器,所以给大家介绍一下在谷歌中如何查看原型链,首先在自己的编译器中输入如上面的例子,打开调试工具