说实话js这门语言之前没有仔细研究过,如今研究起来感受好麻烦,对于原型链这个说法我也是刚接触不久,就试着说说个人理解吧!html
关于上一篇咱们说了js整个函数体系结构,想了解的能够点击这里,这里随便找到一些对原型的小测试,你能够看看会不会,其中Person是一个构造函数,person1是构造函数的一个实例;函数
person1.__proto__
是什么?//person1.__proto__ == Person.prototype测试
Person.__proto__
是什么?//Person.__proto__
== Function.prototypethis
Person.prototype.__proto__
是什么?//Person.prototype.__proto__ == Object.prototypespa
Object.__proto__
是什么?//Object.__proto__ == Function.prototypeprototype
Object.prototype__proto__
是什么?//Object.prototype__proto__ == null设计
知道了这些就差很少了,咱们继续看;3d
1.特殊的Math和JSONcode
这两个内置对象有点不一样,上次尚未注意看,由于其余的内置对象都是Function的实例,好比Date,Number等,举个例子:htm
Date instanceof Function //true Date.constructor == Function //true Date.__proto__ == Function.prototype //true
可是当咱们用Math对象和JSON对象测试的时候确实false,其实能够把Math和JSON对象看做Object的实例:
//Math和JSON同样,这里以Math为例
Math instanceof Object //true Math.constructor == Object //true Math.__proto__ == Object.prototype //true
这两个对象比较特殊,注意一下和其余的内置对象必定要分开!!!
2.继承
继承能够说是每个面向对象语言确定有的,由于符合咱们现实的想法,子承父业嘛!若是你爸比较有钱,你继承了几个亿的家产确定一辈子无忧;若是你爸是个普通人,那即便继承了家产也没有多少啊!仍是要靠本身奋斗。
在js中的继承也一个样,若是一个构造函数设计得很好,那么儿子等后代就会很舒服啊!继承的话,从Object开始,下图所示,你看Object中你以为哪一个部分最重要,应该被继承下去,固然是原型啊!因此说继承就是指的是原型中的全部东西都会被继承到后代中。。。。
咱们能够验证一下:
Object.prototype.say = function(){alert("你好!")}; var obj = new Object(); obj.say();//页面会有弹窗“你好!“,说明在obj实例中调用的say方法其实就是调用的是Object中原型中的say方法 //还能够用另一个方式,就是用Math或者JSON对象也会有一样的效果 Object.prototype.say = function(){alert("你好!")}; Math.say();
这个可能有点晦涩难懂,没关系咱们继续往下看!看了他们的调用机制就懂了;
3.js方法调用机制
简单测试一下,我就是分别在Object原型内外,构造函数Person原型内外,以及per实例中写了一些方法,可能不少人看着都头晕了。。。
Object.say = function(){alert("object----say")} Object.listen = function(){alert("object----listen")} Object.prototype.say = function(){alert("Object.prototype---say")}; Object.prototype.listen = function(){alert("Object.prototype---listen")}; var Person = new Function(); Person.say = function(){alert("Person>>>>>>say")}; Person.run = function(){alert("Person>>>>>>run")};
Person.listen = function(){alert("Person>>>>>>listen")}; Person.prototype.say = function(){alert("Person.prototype>>>>>>say")}; Person.prototype.run = function(){alert("Person.prototype>>>>>>run")}; var per = new Person(); per.say = function(){alert("per+++++++say")}; per.say(); //per+++++++say per.listen(); //Object.prototype---listen per.run(); //Person.prototype>>>>>>run
上面的太繁琐,没耐心看就算了,我就说说我得出的结论:原型外面的函数(也能够叫作方法)不会被继承,也就是说只要是在原型外面的函数只能本身用,不能给后代用;而对于原型里面的函数,对于后代来讲是可见的,
注意:图中我为了看起来简洁,省略了一点东西,就是那么__proto__属性,为何实例可以找到它爸爸构造函数的原型呢?就是经过这个属性,而构造函数中也有一个__proto__属性,指向Object的原型,经过这个原型的话,咱们的实例就可以慢慢往上找原型,一直能够找到Object的原型,这就是所谓的原型链。。。。
因此根据这个特性,js一开始就在Object的原型中放置了一些经常使用的函数,因此自定义构造函数的实例一开始就能够调用一些方法,这些方法不是咱们定义的,而是官方帮你先放到Object的原型中的,固然你也能够在实例或构造函数中弄个一样名字的函数,将官方那个给覆盖掉。。。。。
4.js中方法类型
我js中的方法大概分为三种(对于js这样的语言来讲,没有类的概念好不爽,咱们就把构造函数看做类吧。。。。):类方法,实例方法,原型方法
那么这三种方法究竟是干吗的呢?我就随便举个例子:
var Person = function(name){ this.name = name; this.say = function(){alert("say.....")};//实例方法 } Person.say = function(){alert("Person say.....")}//类方法,只能经过构造函数名来调用 Person.prototype.say=function(){alert("prototype say.....")}//原型方法 var per = new Person(); per.say();//调用实例方法,注意当实例方法和原型方法同名的时候优先调用实例方法,若是实例方法没有say方法,那就会调用原型中的say方法 Person.say();//调用类方法 Person.prototype.say();//调用原型方法
5总结
怎么说呢?感受js结构太糟糕了,看了很久才知道一个大概的轮廓,还有不少的东西没看到,好比咱们知道原型实际上是一个当前构造函数的实例,那么咱们可不能够把其余对象的实例赋值过来呢?好比Student.prototype = new Person(),这样行吗?固然能够,这样的话可让Student的实例访问Person的原型的方法,实现了继承。。。。
哎,有机会再来啃js吧,还有好多东西要看。。。。因为看js没多久,有什么说得有误的地方欢迎指出!