JS做为发展了多年了对象语言,支持继承,和彻底面向对象语言不一样的是,JS依赖原型链来实现对象的继承。函数
首先JS的对象分两大类,函数对象和普通对象,每一个对象均内置__proto__属性,在不人为赋值__proto__的前提下,普通__proto__属性指向其构造函数的.prototype属性,例如:spa
var test={};prototype
此时test.__proto__指向Object.prototype,Object为原型链的顶端,一切对象都可追朔到Object.对象
function money(){};继承
var test=new money();ci
此时test.__proto__指向money.prototype.原型链
普通对象没有prototype属性。(Object除外)原型
再来看函数对象:io
function money(){};console
此时money是一个函数对象,其__proto__指向Function.prototype
Function.prototype也是一个普通对象,又回到了上面所说的,因此Function.prototype中的__proto__属性指向Object.prototype。
这里只需记住一点,一切对象均有__proto__属性,一切对象继承链顶端都是Object对象,那么Object.prototype.__proto__又指向哪里呢?
console.log(Object.prototype.__proto__)
//null
即顶端的对象再也不继承任何对象,他的父级是空。
既然知道了JS原型链,再一块儿来了解实际项目中的应用
这里咱们定义了一个函数对象
var father=funcion(){};
var son=new father();
var son1=new father();
这里咱们得到了两个普通对象son,son1
两个普通对象的__proto__均指向father.prototype,由于他们都是由father函数对象构造出来的。
若是这时咱们须要为son增长一个属性,咱们能够这么写
son.say=function(){alert(‘hello world!’)}
son.say();
//hello world!
固然没问题,若是咱们须要son1也有一样的属性呢,son1.say=function(){alert(‘hello world!’)}
son1.say();
//hello world!
代码没有任何问题,运行良好。
若是咱们用father构造了不少对象,son1,son2.....son10000,这是咱们须要这些构造出来的对象都有这个属性该怎么办!
father.prototype.say=function(){alert(‘hello world!’)}
var son1000=new father();
son1000.say();
//hello world!
咱们没有为son1000添加任何属性方法,但它依然能够正常运行。
来看原理:
JS约定在获取对象内置属性时,首先会去当前对象中寻找,若是找不到,则去.__proto__所指向的对象中去寻找,因为.__proto__所指向的对象自己也有.__proto__属性,因此若是没有找到则继续根据当前对象.__proto__所指向的对象去继续寻找,在整个过程当中,若是找到则终止继续向上查询,不然一直会追踪到Object.prototype,若是整条链上均没有找到,那么结果就是undefined!